简介铁路轨道缺陷检测数据集面向计算机视觉目标检测研究者与智慧铁路维护工程师旨在训练可自动识别轨道裂缝、间隙等缺陷的模型。压缩包为zip格式内共2000个文件全部为PASCAL VOC XML格式的标注数据包体约273.84MB。该格式通用性强可被LabelImg等标注工具直接打开验证XML内记录目标类别与边界框位置能直接引入YOLO、Faster R-CNN、SSD等主流检测框架训练与评估省去标注环节。文件名中的aug_prefix等前缀表明包含大量数据增强样本的对应标注可有效扩充正负样本增强模型泛化性同时可配合配套博文获取原始图片完成完整数据集构建。目前已有1688人学习下载适用于工业质检、轨道交通巡检、桥梁隧道结构监测等场景也可作为目标检测课程设计或算法对比实验的基础数据。1. 铁路轨道缺陷数据集到底是什么4278张原始图能支撑什么样的裂缝与间隙检测拿到这份铁路轨道缺陷数据集建议先别为4278张原始图的数量高兴得太早。轨道缺陷检测真正耗时间的从来不是有没有数据而是标注能不能信、能不能顺利喂进模型。这套数据的特点是每张轨道图都带一份PASCAL VOC格式的XML标注标题里的PASICAL是笔误文件结构就是标准VOC标注目标有两类裂缝crack和间隙缺陷gap。拿到手就把最苦的数据标注阶段跨过去了可以直接做目标检测训练、验证和二次补标。它适合钢轨表面裂缝识别、轨道结构巡检的算法工程师与在读研究生。可以用它训练YOLO系、Faster R-CNN或SSD也可以拿它当基座叠加自己采集的夜轨、隧道图继续扩充。先按标题给出的出处下载核对解压后第一件事是数文件。好不好用取决于你能不能把VOC XML干净地转成训练框架要的格式以及能不能绕开小目标裂缝后面那一串坑。2. 认识数据集VOC XML标注结构、两类缺陷的标注边界与类别分布2.1 PASCAL VOC XML的标注字段一张轨道图对应一个XML文件VOC数据集的目录约定非常固定常见的是JPEGImages放原图Annotations放同名XML。这套轨道缺陷数据集如果沿用同样约定你会看到类似下面的结构rail-track-defect/ ├── JPEGImages/ │ ├── img_00001.jpg │ ├── img_00002.jpg │ └── ... ├── Annotations/ │ ├── img_00001.xml │ ├── img_00002.xml │ └── ... └── ImageSets/ └── Main/我一般拿到手第一件事就是核对JPEGImages里jpg数量和Annotations里xml数量是否一致都是4278最好。缺一个训练时就会在某个epoch报KeyError让你误以为代码写错了实际上是数据文件没对齐。打开任意一个XML典型的VOC结构长这样annotation folderJPEGImages/folder filenameimg_00001.jpg/filename size width1920/width height1080/height depth3/depth /size object namecrack/name truncated0/truncated difficult0/difficult bndbox xmin512/xmin ymin400/ymin xmax580/xmax ymax448/ymax /bndbox /object /annotation训练脚本里一般只用name、bndbox和size但truncated和difficult会影响你要不要把某个框计入训练。关键字段的处置方式参考下表字段含义训练时处置filename图片文件名拼接图片路径的依据注意Windows反斜杠size.width/height/depth原图尺寸与通道数归一化坐标时要用name类别名crack或gap必须与类别映射表严格一致truncated目标是否被图像边界截断轨道场景里可保留也可过滤difficult难例标记1表示很难判别推荐保留但单独评估别直接删bndboxxmin/ymin/xmax/ymax整数像素转YOLO时唯一要换算的坐标提示VOC和YOLO的坐标都是像素值但VOC给的是绝对像素YOLO要的是相对于宽高的比例具体换算放在第4章细说。2.2 裂缝与间隙缺陷的界定标注框长什么样容易混的框是哪类两类缺陷的形态差别很大理解它后续做增广和调anchor才有依据。裂缝crack标注框几乎都是细长条短边可能只有十几像素长边却有几十上百像素长宽比常常大于5甚至超过10。它对应的是轨面或轨腰上的疲劳裂纹放大看是一条不规则的线框往往是斜着包的所以XY轴对齐框里会带不少背景。间隙缺陷gap在轨道上通常指轨缝异常、接头错位或扣件区段的非正常间距。它和裂缝最大的区别是裂缝是“材料裂了”间隙是“结构分开了”。间隙的框一般面积更大、形状更接近方块或横向长条不会像裂缝那样瘦。最容易混淆的是“裂缝末端伴有间隙”的复合缺陷。如果你在补标阶段拿不准我的习惯是把这类框的difficult置1让模型学习但评估时单独算别混在干净类里拉低均值。标注的难点在于裂缝是小目标间隙是大目标两类在同一个尺度下训练天然有尺度冲突。这直接决定了后期要么用原分辨率训练要么做切片。2.3 用Python统计4278张图的类别分布与框尺寸不要直接开训。先写一个统计脚本搞清楚类别数量、每张图的框数分布、框宽高的中位数。这个脚本十分钟能写完却能帮你避免后面好几个小时的定位排错。import os import xml.etree.ElementTree as ET from collections import Counter xml_dir rail-track-defect/Annotations files sorted(os.listdir(xml_dir)) cls_counter Counter() box_per_image [] widths, heights [], [] for f in files: if not f.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, f)) root tree.getroot() objs root.findall(object) box_per_image.append(len(objs)) for obj in objs: name obj.find(name).text.strip().lower() cls_counter[name] 1 bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) widths.append(xmax - xmin) heights.append(ymax - ymin) print(xml数量:, len(files)) print(类别分布:, dict(cls_counter)) print(单图框数 均值/中位数:, sum(box_per_image) / len(box_per_image), sorted(box_per_image)[len(box_per_image) // 2]) print(框宽中位数:, sorted(widths)[len(widths) // 2]) print(框高中位数:, sorted(heights)[len(heights) // 2])这段脚本做的事情遍历Annotations下所有XML逐个解析出object的name和bndbox把类别名统一转小写后计数同时记录每张图的框数以及每个框的宽高。输出结果基本决定了后续策略。如果裂缝框宽中位数只有15像素输入尺寸小于640就是灾难如果gap和crack的框数比例超过3比1就要在采样上下功夫。参数说明xml_dir换成你解压后的实际路径统计粒度最好按训练集和验证集分两次跑别混在一起。遇到某个XML没有object这段脚本不会报错会计入0框这种“空XML”在转换阶段要单独处理。假定统计结果是crack有6000框、gap有2000框单张图平均2.1个框、最大9个框这种偏态分布就该做类别重采样。如果反过来gap远多于crack说明数据集侧重轨缝巡检训练时要注意别让gap主导loss。3. 标注工具回看与二次标注LabelImg、CVAT和labelme哪个能直接吃VOC XML3.1 目标检测常用标注工具对VOC的支持程度很多人拿到标好的数据集就直接训练了这是浪费。你应该先抽20到50张在标注工具里肉眼过一遍看有没有错框、漏框和越界框。目标检测常用标注工具里能直接吃VOC XML的有三个梯队工具打开VOC方式导出格式适合场景LabelImg直接Open XML DirVOC XML / YOLO txt本地单机快速回看、补标CVAT导入VOC XML任务VOC / YOLO / COCO团队协作、分人质检labelme原生只认json需要转JSON / 可转VOC做多边形标注、实例分割时CVAT标注工具和LabelImg在轨道场景里的地位很难互相替代LabelImg胜在轻量、打开目录即用CVAT胜在能按类别筛选、能多人标注、能导出时过滤difficult。如果只为了复查4278张图我一般用LabelImg如果要让两个实习生一起补标注就上CVAT。3.2 用LabelImg回看和补标打开XML目录的操作LabelImg的用法关键词是“Open Dir”和“Open XML Dir”配对。具体步骤打开LabelImg左侧工具栏点击Open Dir选择JPEGImages目录。点击Open XML Dir选择Annotations目录保证XML文件名与jpg文件名一一对应。顶部PascalVOC按钮要处于选中态这样保存时默认写VOC XML。翻图检查。看到明显框错的用Edit Rect拖动看到漏检的用Create Rect画新框类别从右侧列表选crack或gap。保存时LabelImg会写回XML。这里有个常见坑LabelImg对中文路径支持不好。如果你把数据集放在“D:\轨道缺陷\”这种带中文的路径下保存时可能报“could not open annotation file”。解决很简单数据集目录一律用英文、不要带空格。这也是数据标注的通用规矩目录命名里出现中文后面任何脚本都可能翻车。3.3 用CVAT做批量质检导入VOC XML后按类别筛选如果数据集要交给多人复核CVAT比LabelImg合适。我不细讲服务器部署只说导入、导出和质检这两条链路。导入时在CVAT里创建新任务数据选择JPEGImages里的图片下方Label列表填crack、gap。创建后在任务列表点Open再通过Upload annotations把某个VOC XML传进去CVAT会按filename把框对回图片。质检时最该用的是Filter功能在标注画布右侧按name字段筛选出crack快速翻一遍确认没有把钢轨扣件阴影误标成裂缝再筛选gap确认正常轨缝没有被标成缺陷。导出时选择Pascal VOC 1.1格式CVAT会把所有任务里的标注合并导出一份大XML回到第2章的脚本重建Annotations目录即可。3.4 从labelme标注到VOC再到YOLO的链路经常有人问labelme标注用于yolov8怎么弄。labelme原生保存的是JSON每个JSON里有shape_typerect或polygon和points。如果你的新数据是用labelme画的矩形框要进这个轨道数据集的VOC体系得先把JSON转成VOC XML如果直接进YOLO第一次用labelme标注用于yolov8时容易卡在“坐标没归一化”上。我一般这样做转换读labelme JSON里的points矩形框取第一个点和第二个点组成对角除以JSON里的imageWidth和imageHeight得到归一化的cx、cy、w、h再按类别编号写txt。如果你想保持VOC统一管理就先转XML再走第4章的脚本好处是后面想换框架时数据源统一不用再返工。到这里你就知道第3章这些工具不是给你从零标4278张图用的而是用来“回看、补标、复核”。做完这一步才轮到最核心的动作格式转换。4. 把VOC转成YOLO格式转换脚本与四个边界坑4.1 转换脚本用xml.etree.ElementTree解析并生成归一化txtYOLO的标注格式是每张图一个txt每行代表一个目标class_index cx cy w h四个坐标都归一化到[0,1]。下面是我常用的转换脚本兼容Python 3.6以上不需要额外依赖import os import glob import xml.etree.ElementTree as ET # 参数区只改这里 voc_xml_dir rail-track-defect/Annotations jpg_dir rail-track-defect/JPEGImages yolo_txt_dir rail-track-defect/labels class_names [crack, gap] # 顺序就是类别编号别随意换 min_side_pixel 8 # 过滤太小的框轨道裂缝常见极端细条 def voc2yolo(xml_file, jpg_dir, yolo_txt_dir, class_names): tree ET.parse(xml_file) root tree.getroot() filename root.find(filename).text img_width int(root.find(size).find(width).text) img_height int(root.find(size).find(height).text) txt_name os.path.splitext(filename)[0] .txt txt_path os.path.join(yolo_txt_dir, txt_name) if os.path.exists(txt_path): os.remove(txt_path) lines [] for obj in root.findall(object): name obj.find(name).text.strip().lower() if name not in class_names: print(未知类别:, filename, name) continue cls_id class_names.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 过滤极端小框防止归一化后数值小到被下采样吃掉 if (xmax - xmin) min_side_pixel or (ymax - ymin) min_side_pixel: continue # 裁剪越界坐标到图像边界 xmin max(0.0, min(xmin, img_width - 1)) ymin max(0.0, min(ymin, img_height - 1)) xmax max(0.0, min(xmax, img_width - 1)) ymax max(0.0, min(ymax, img_height - 1)) # YOLO框中心 宽高全部归一化 cx ((xmin xmax) / 2.0) / img_width cy ((ymin ymax) / 2.0) / img_height w (xmax - xmin) / img_width h (ymax - ymin) / img_height # 浮点保留位数6位足够多了徒增文件体积 lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) if lines: with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) xml_files glob.glob(os.path.join(voc_xml_dir, *.xml)) os.makedirs(yolo_txt_dir, exist_okTrue) for xmlf in xml_files: voc2yolo(xmlf, jpg_dir, yolo_txt_dir, class_names) print(转换完成共处理, len(xml_files), 个XML)转换完成后随便打开一个生成的txt看格式应该是“0 0.2543 0.4012 0.0312 0.0521”这样一行。4.2 逻辑说明与参数类别映射、图像路径、min_size过滤上面代码里最值得你调的是class_names的顺序。YOLO的类别编号不是字符串而是列表下标crack对应0gap对应1这个顺序要原样带进训练配置data.yaml里否则模型学到的类别和你的认知对不上。jpg_dir参数在脚本里目前只用于占位实际目录统一管理时可以拿它拼绝对路径替换掉XML里的相对路径。min_side_pixel默认8指像素不是归一化值。轨道裂缝很多标注框短边只有几像素过滤太狠会直接丢掉真样本太松又会产生大量训练噪音。我的经验是先跑一遍第2章的统计脚本看短边分布低于P5百分位的才设成阈值。如果你用的图分辨率是1920x10808到12像素是合理起点。另外脚本里“未知类别”分支只打印不中断这个设计是有意的。很多VOC XML里会出现类别名大小写混写、或者多一个空格比如“ Crack”。如果直接报错退出你就要在4278个XML里人肉找脏数据先打印出来集中看一遍再回头统一清洗。我实际跑下来最脏的往往不是crack和gap本身而是标漏的gap被写成了gaps或final_gap。提示转换完成后不要急着删Annotations。YOLO txt一旦丢了几列原始XML还在可以从头再转。XML是后悔药txt不是。4.3 四个边界坑标签大小写、difficult框、坐标越界、空XML这四个坑依次说现象、原因和解决。第一个是标签大小写不统一。现象训练时类别总数莫名变成4个精度一路玄学波动。原因部分XML里写Crack部分写crack框架把大小写当成两个不同类。解决转换脚本里强制name.strip().lower()同时在统计脚本里把类别名打印出来核对一遍。统一用全小写是数据标注环节就该遵守的约定。第二个是difficult与truncated框的去留。现象验证集mAP比预期高但实际场景推理时全是误检。原因训练框里混着一堆不完整目标模型学会了“不完整的钢轨也判缺陷”。解决把difficult1的框单独复制一份训练集可用但验证集过滤掉。做研究要比数就把difficult框单拎出来做一个hard_set。第三个是坐标越界。现象转换后出现负数cx或大于1的w。原因标注时框拖出画布边缘或是从其他软件导出的坐标本身就超了。解决用上面代码的clip逻辑把xmin/xmax/ymin/ymax夹到图像边界内clip后如果w或h变成0这个框直接丢弃。别只在YOLO里夹训练框架很可能直接报AssertionError。第四个是空XML和完全无目标的背景图。现象某一张jpg在labels目录找不到对应的txt训练时图像和标签对不齐。原因XML里一个object都没有脚本的lines为空就不写文件。解决空XML也生成一个空txt文件文件大小为0这能让YOLO按背景图参与训练学习“这张图没有缺陷”对抑制误检有帮助。很多铁路图是净空的轨枕和道床这恰恰是模型最需要的负样本。5. 训练前的避坑清单标注质量、类别不平衡与小目标漏检5.1 裂缝框过细导致训练翻车不要直接用640输入现象训练loss正常下降验证集上gap的mAP到了0.85crack只有0.4。把预测结果可视化出来大片裂缝没被框上。原因裂缝的框瘦长短边经常不足10像素。在YOLO的输入尺寸缩放里短边被压缩到1到2个像素特征图上的细节基本消失。这不是模型问题是输入分辨率配不上目标尺度。解决先把输入尺寸从640提到1280甚至原图尺寸。用ultralytics训练时就是imgsz1280显存不够就调小batch。仍然漏检的用SAHI做切片推理把原图切成512x512的重叠patch每个patch单独预测再合并。轨道场景我验证下来切片的收益远比换更大模型明显。5.2 两个类别的框数差距太大按类别重采样现象统计脚本显示crack有6000框gap只有1800框训练后gap类的召回率一直拉不上去。原因类别不平衡让loss被多数类主导少数的gap即使预测错也对总体loss贡献不大。解决常见做法是给训练集按类别做重采样随机复制gap较多的图片或者用copy-paste增广把gap框贴到无缺陷背景图上。不要只追求目录文件数量一致目标检测里“框数平衡”比“张数平衡”更重要。只复制图片不打乱容易让同一条钢轨在训练集里反复出现造成过拟合记得配合平移、翻转一起做。5.3 间隙缺陷的尺度横跨太大固定anchor不如无anchor现象gap框从几十像素到几百像素都有用YOLOv5固定anchor训练日志里最佳召回率始终到不了理想值。原因anchor预设聚不到跨度这么大的分布。轨道上的gap既可能是扣件段的小缝隙也可能是接头处的大错位。解决优先用anchor-free的检测头这样能省掉anchor聚类这一步如果非要用带anchor的版本先用数据集的框宽高做k-means聚类生成anchor别用COCO预设。聚类结果会和COCO预设相差很远因为轨道缺陷的框普遍比自然图像小。5.4 直接随机split让验证集失真按序列分层划分现象随机把4278张图按8比2分成训练和验证验证集mAP虚高0.06以上换一次随机种子结果波动特别大。原因轨道图是连续巡线拍摄的相邻图高度相似。随机划分会把同一段钢轨的相似图同时塞进训练和验证验证等于开卷考试。解决先按文件名前缀或拍摄时间把图分成若干序列同一个序列的所有图必须落在同一个集合里。再做按类别分层保证验证集里crack和gap的框数比例和全量一致。这个操作写进数据划分脚本不要每次训练手动拖。6. 从4278张图到可用模型最小训练配置与验收技巧6.1 最小训练配置rail.yaml与train命令先写数据集配置文件以ultralytics YOLO系为例版本号以你本地pip装好的为准path: D:/rail-track-defect train: images/train val: images/val nc: 2 names: 0: crack 1: gap这里train和val指向整理好的子目录把第4章转换出来的txt按同样的子目录结构放好images/train/xxx.jpg和labels/train/xxx.txt一一对应。之前转换脚本输出的是扁平labels目录训练前要按8比2重新分目录划分时用第5章的分层逻辑。训练命令我一般写成yolo detect train datarail.yaml modelyolov8s.pt imgsz1280 epochs150 batch8 lr00.01逐项看参数imgsz1280是轨道小目标的关键不要怕慢先用小模型验证pipelinebatch8按显存调12G显存够跑不够就减到4epochs150对这种四五千张的中等规模数据集足够前50轮看loss如果明显过拟合优先降epoch而不是升batch。6.2 验收技巧在原始分辨率上做切片检查训练完先别急着交差。我的验收动作固定在三个第一用训练好的模型对原图直接预测imgsz设成原图最接近的1280保存预测图人工看裂缝多不多漏检。第二把漏检样本的框短边尺寸统计出来看是不是集中在15像素以下。如果是说明模型尺度学到位了是分辨率不够直接上SAHI切片。第三挑20张完全无缺陷的净空轨枕图数误报框这决定模型能不能上线。最后说一个我的个人习惯这类缺陷数据集最大的价值不是原始图片数量而是XML标注里沉淀下来的缺陷形态。我会把转换后的txt和XML都留档每次调参失败不删数据只改配置重跑。做过三轮就知道轨道裂缝检测的瓶颈百分之八十在分辨率不在网络结构。希望帮到你。本文还有配套的精品资源点击获取