
简介面向铁路基础设施巡检与计算机视觉目标检测、实例分割场景这份轨道缺陷数据集完整提供了四千二百七十八张原始轨道图像及对应的COCO JSON格式标注像素级标注可识别轨道表面裂缝、间隙等典型缺陷适合用于训练、验证与评测缺陷检测模型可有效支撑裂缝检测、间隙测量等任务。资源包共包含两千个文件由一千九百九十七张jpg图像与三个json标注文件组成压缩后约二百七十二兆图像覆盖不同光照、角度与场景环境标注文件遵循COCO标准可配合YOLO、MMDetection等主流框架直接开始训练文件结构与标注字段一目了然。目前已有一千三百六十六人学习下载数据命名方式保留了采集场景与增强信息便于筛选、划分训练集或进行针对性扩充。对于高校实验室、职业技术培训以及工业巡检算法研究者这份数据集能节省大量现场采集和人工标注时间帮助快速验证模型在不同轨道缺陷上的检测效果是开展实践教学与算法调优的实用资源。1. 铁路轨道缺陷数据集4278张图能做什么不能做什么铁路轨道缺陷数据集4278张原始图片附带COCO JSON格式的标注检测目标就两个有没有裂缝、有没有间隙缺陷。这个规模在工业缺陷检测里不算小但离“拿到就能训”还差得很远。我拿到类似数据的第一反应从来不是直接训练而是先拆开标注看一遍——COCO JSON格式虽然规范但实际里面可能藏着类别ID混乱、标注框偏移、缺陷目标只有几个像素的问题。这篇笔记讲清楚COCO格式怎么读、怎么转成YOLO训练格式、哪些参数对轨道缺陷最敏感以及怎么验证模型不是只在验证集上好看。想用这份数据把缺陷检测落地的人按这个路径走能少踩一半坑。2. COCO JSON标注结构拆解为什么缺陷检测选它而不是VOC或TXT2.1 五个顶层字段图片、标注、类别是怎么关联起来的COCO JSON是一份完整的标注文件里面通过ID把图片和标注关联起来。顶层有五个关键字段info、licenses、images、annotations、categories。实际训练里最常用的是后三个前两个更多是元信息。下面是一份精简的结构示例和你拿到的轨道缺陷数据集标注格式基本一致{ info: { description: rail track defect dataset, version: 1.0 }, licenses: [], images: [ { id: 1, file_name: track_0001.jpg, width: 1920, height: 1080 } ], annotations: [ { id: 1, image_id: 1, category_id: 1, bbox: [512.5, 380.2, 45.1, 12.3], area: 555.73, iscrowd: 0 } ], categories: [ { id: 1, name: crack, supercategory: defect }, { id: 2, name: gap, supercategory: defect } ] }这段结构里最关键的是images和annotations的关联方式。每张图片有一个唯一id每条标注也带一个image_id指向它属于哪张图。bbox是[x, y, width, height]注意不是YOLO那种中心点加宽高的写法而是左上角坐标加框的宽高。这里x和y是像素坐标width和height是框的实际像素宽高没有归一化。area在纯框标注里通常用width * height算但如果后面要用pycocotools评估mAP这个字段必须和bbox一致否则会报错或算出的AP不对。另一个容易忽略的是categories的id。COCO官方数据集的类别ID是从1开始的但很多工具和脚本习惯从0开始。你这个轨道数据集如果categories里crack的id是1gap的id是2那么转换成YOLO格式时就得做一次减一映射否则训练时候类别就错了。我后面会给出专门的转换脚本。2.2 与VOC/YOLO格式对比COCO在缺陷场景的三个实际优势工业缺陷检测场景里最常见的数据格式有三种VOC XML、YOLO TXT、COCO JSON。很多人问为什么不用更简单的TXT我的回答是简单不等于可靠。YOLO TXT每张图一个文本文件每个文件里几十行类别 cx cy w h一旦图片文件名和标注文件名对不上或者图片被resize过所有坐标就全废了。而COCO JSON把图片元信息和标注放在一起谁和谁对应一目了然。第一个优势是数据完整性。COCO JSON里每张图都带着width和height转换脚本可以通过这个字段自动校验标注坐标有没有超出图片边界。这个在轨道缺陷数据里特别重要。4278张图里面如果混着一批1920x1080和一批1280x720的图YOLO TXT没法感知尺寸变化但COCO JSON可以。第二个优势是扩展性。annotations里除了bbox还能存segmentation多边形、iscrowd标志、area。像裂缝这种细长目标矩形框里会混进大量背景如果后续想用分割模型或者混合标签训练COCO格式不用重新标直接在原文件上加字段就行。VOC格式虽然也能存多边形但文件散落太多维护成本高。第三个优势是工具链成熟。CVAT、labelImg、X-AnyLabeling这些标注工具都支持COCO JSON导入导出pycocotools可以直接算mAP和混淆矩阵。我自己做数据检查时习惯用一行Python脚本把COCO标注画回图片上这个操作在YOLO TXT时代要自己写解析器现在直接用cocoapi就行。对于这个轨道缺陷数据集来说用COCO格式等于给自己留了后悔药后面想切模型、加类别、换评估方式都不用重标数据。3. 从COCO JSON到YOLOv8训练转换脚本与三个必须调的参数3.1 第一步用Python脚本校验COCO标注先看数据再动手拿到数据别急着训练先跑一轮数据校验。我一般会写一个脚本统计三件事图片数量、标注数量、类别分布。顺带检查有没有图片文件名对不上、标注框越界、类别ID空白这些低级问题。过去在好几个数据集上翻过车原因都是某个标注文件里混了一条category_id不存在的记录训练时loss直接异常。import json from pathlib import Path from collections import Counter coco_path Path(annotations/instances_train.json) coco json.loads(coco_path.read_text(encodingutf-8)) print(图片数量:, len(coco[images])) print(标注数量:, len(coco[annotations])) print(类别:, [(c[id], c[name]) for c in coco[categories]]) # 统计每张图上的标注数量找出异常样本 img_ann_count Counter(ann[image_id] for ann in coco[annotations]) print(标注数最多的5张图:, img_ann_count.most_common(5)) # 检查bbox是否越界 img_map {img[id]: img for img in coco[images]} bad_boxes [] for ann in coco[annotations]: img img_map[ann[image_id]] x, y, w, h ann[bbox] if x w img[width] 1 or y h img[height] 1: bad_boxes.append((ann[id], img[file_name])) print(越界标注数量:, len(bad_boxes))这段代码的逻辑很简单先加载整个JSON打印基础统计量然后用Counter统计每张图的标注数最后遍历所有bbox判断有没有超出图片边界。最后的加1是容忍浮点误差。这个脚本跑完你基本能判断这个轨道缺陷数据集是干净还是需要返工。参数说明encodingutf-8必须加Windows下默认编码可能是GBKJSON里有中文类别名时会解码失败。越界判断里的容忍值看具体情况COCO里有些标注工具会生成比图片宽1到2像素的框如果超过5像素说明标注时图片尺寸和实际模型输入尺寸不匹配后面转换时要重点处理。3.2 第二步COCO转YOLO标注的脚本和类别ID偏移YOLO系列训练需要TXT格式标注每行一个目标格式是类别索引 归一化中心x 归一化中心y 归一化宽度 归一化高度。转换时最容易出错的点有两个归一化时除的是图片原始宽高不是数据集里最大宽高类别ID要从COCO的id映射到从0开始的索引。import json from pathlib import Path def coco_to_yolo(coco_json_path, output_dir): coco json.loads(Path(coco_json_path).read_text(encodingutf-8)) output_dir Path(output_dir) output_dir.mkdir(parentsTrue, exist_okTrue) # COCO的category_id到YOLO索引的映射必须是连续0..n-1 cat_ids sorted({c[id] for c in coco[categories]}) cat_id_to_idx {cat_id: i for i, cat_id in enumerate(cat_ids)} img_map {img[id]: img for img in coco[images]} anns_by_img {} for ann in coco[annotations]: anns_by_img.setdefault(ann[image_id], []).append(ann) for img_id, img in img_map.items(): w img[width] h img[height] lines [] for ann in anns_by_img.get(img_id, []): x, y, bw, bh ann[bbox] cx (x bw / 2) / w cy (y bh / 2) / h nw bw / w nh bh / h lines.append(f{cat_id_to_idx[ann[category_id]]} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) if lines: stem Path(img[file_name]).stem Path(output_dir / f{stem}.txt).write_text(\n.join(lines), encodingutf-8) coco_to_yolo(annotations/instances_train.json, labels/train)这个脚本的核心在于cat_id_to_idx映射。如果你直接拿category_id当YOLO类别索引而COCO里crack的id是1、gap的id是2那么训练时类别索引1会在names: [crack, gap]里对应gap全部错位。用排序后的enumerate生成连续索引就从根源上堵住这个问题。归一化时还有一个容易忽略的细节x bw / 2这一步。YOLO用的中心点坐标而COCO给的是左上角坐标。如果你只拿x直接除宽模型会学到一个偏左上方的目标中心推理时框会整体偏移。我见过好几个新手在这个地方翻车损失函数看着在下降但预测框位置总是不对。3.3 第三步训练配置里的分辨率、batch和类别权重数据转换完接下来是训练配置文件。用YOLOv8训练自己的数据集需要一个YAML文件描述数据路径和类别。对于铁路轨道缺陷数据集我的标准配置是这样# rail_track.yaml path: ./datasets/rail_track train: images/train val: images/val nc: 2 names: [crack, gap]训练命令我一般这样跑yolo train datarail_track.yaml modelyolov8n.pt imgsz1280 batch16 epochs150 patience20三个参数对缺陷检测影响最大第一个是imgsz。轨道裂缝和间隙缺陷很多是细长条宽度只有十几个像素如果按默认的640输入这些小目标在特征图里可能只剩1到2个像素模型根本学不到纹理。我建议至少用1280显存不够就降低batch但不要动分辨率。imgsz1280配合YOLOv8的mosaic增强对小目标召回率的提升是肉眼可见的。第二个是batch。这个参数不是越大越好而是取决于你的显存和图片分辨率。1280分辨率下16张图大约需要12GB显存。如果你只有8GB把batch降到8否则会出现CUDA out of memory这不算玄学是实际计算量决定的。第三个是类别权重。如果这个数据集里裂缝有3000条标注而间隙缺陷只有300条模型会偏向学裂缝。这时可以在loss里提高稀有类别的权重或者在yolo train命令里调cls1.5这类参数。更稳妥的做法是先看数据分布再决定别盲目调权重。4. 轨道缺陷数据集避坑指南裂缝和间隙标注的5个典型事故4.1 裂缝被标成多个小框模型学成“碎渣”现象训练出来的模型在裂缝上输出一堆零散的小框明明是一条连续裂缝被检测成好几段。原因标注员把一条长裂缝手动切成了多个矩形框每个框只覆盖裂缝的一小段。这是轨道缺陷数据里最常见的问题。解决在标注规范里明确“一条裂缝算一个目标”除非中间断裂超过一定像素否则必须合并。对于已有数据可以写脚本判断多个框是否有大面积重叠重叠超过阈值就合并成一个外接框。但这个操作要谨慎如果两条裂缝平行且靠近合并后会把中间的正常区域包进去。4.2 间隙缺陷的框过大把背景也包进去现象模型把轨道间隙周围的道砟、石子误检成缺陷误报率特别高。原因标注间隙缺陷时标注员把框画到了整个缝隙区域而不是缺陷本身。间隙缺陷的特点是纵向细长横向宽度不大如果框的高度包含了太多背景模型就会把背景纹理也学到。解决用pycocotools或OpenCV把标注框画回原图逐张查看间隙缺陷的框是否贴合。如果框宽超过缺陷实际宽度两倍以上应该改成多边形标注或者把框收紧到缺陷边缘。CVAT里可以直接调整现有框比重新标快得多。4.3 类别ID在COCO和YOLO之间差1训练直接崩现象训练时log里loss正常下降但验证集mAP一直是0。原因COCO的category_id从1开始YOLO的类别索引从0开始。如果你没有做cat_id_to_idx映射crack的id1会被当成第二个类别gap而gap的id2越界模型只学了一个类别。解决在转换脚本里打印映射表确认{1: 0, 2: 1}这样连续从0开始。这个错误很隐蔽因为训练不会报错只有查看预测结果时才发现类别全乱了。我现在每转一次数据都会随机抽十张图跑一次可视化把YOLO TXT转回坐标画在原图上人工确认。4.4 图片EXIF旋转后标注框整体偏移现象训练集和真实场景图片里有手机拍摄的照片模型在部分图片上预测框整体偏到右上角。原因部分图片带EXIF旋转信息显示时是正立的但OpenCV和PIL读取原始像素时没有自动旋转导致标注坐标和实际图像内容错位。比如一张旋转90度的图标注框仍然按旋转前的坐标系画训练时模型看到的图和标注不一致。解决在数据预处理阶段统一用ImageOps.exif_transpose处理所有图片并重新生成图片文件确保实际像素方向与标注坐标一致。这个坑在公开数据集里很少见但自己收集的轨道缺陷图片经常遇到。4.5 部分图片没有任何标注loss出现NaN现象训练跑到一半loss变成NaN然后模型权重全部失效。原因数据集里有一批图片没有任何目标的标注但被放进了训练集。YOLO在损失计算里遇到空目标时会除以零某些版本直接产生NaN。解决先用脚本检查每张训练图对应的TXT文件是否为空把所有空标注的图片从训练集里剔除或者单独放到一个background类别目录里。另外检查是否有损坏的图片文件用cv2.imread读不出来的图也要删掉。这个操作应该放在数据校验阶段不要等训练崩了再排查。5. 用CVAT做二次标注把4278张图的价值榨干5.1 把COCO JSON导入CVAT检查并修正误标标注工具里我推荐CVAT它对COCO JSON的支持最完整。把现有的instances_train.json导入CVAT可以直接在Web界面上逐张查看标注框、调整边界、删除误报、补充漏标。具体操作是创建项目时选“COCO JSON 1.0”作为导入格式上传压缩包或者标注文件CVAT会自动识别images和annotations。导入后建议按类别分组检查先看所有gap的标注再看crack的不要混着看混着看容易漏掉系统性错误。检查时重点看两类问题一是框是否和缺陷边缘贴合二是同一个缺陷有没有被重复标注。轨道裂缝常常延伸到图片边界如果标注框只画了可见部分后续模型会把截断处当成目标边界影响定位精度。CVAT里可以直接拖拽框的端点把裂缝延伸到图外或补齐到完整目标。5.2 裂缝该用多边形还是矩形框标注规范建议回到这个数据集本身原始标注用的是COCO矩形框。但裂缝和间隙这两种缺陷形状差异很大矩形框的适用性完全不同。间隙缺陷形状相对规整垂直方向宽度稳定用矩形框没问题。裂缝则不同它是细长曲线矩形框会把大量轨道表面背景包进去导致模型学到的是“图像局部区域的特征”而不是裂缝本身的特征。我的建议是如果后续要用YOLOv8这类检测模型继续用矩形框也可以但框必须贴合裂缝的方向。不要用一个水平框去包一条45度角的裂缝那样框面积膨胀很多。更好的方案是在CVAT里把裂缝改成多边形标注导出的COCO JSON里保留segmentation字段同时让CVAT自动计算外接bbox。这样检测模型仍然能训练以后要转实例分割模型也不用重新标。5.3 类别不平衡与数据增强4278张不够时的补救方式4278张原始图片听上去不少但真正含缺陷的图可能只有几百张。如果你发现crack和gap两类标注数量差距超过5倍必须处理类别不平衡。常见做法是给少数类提高采样权重或者在增强时对少数类图片做额外复制。我一般会先统计每类标注数量再决定用哪种方案不要一上来就调loss权重。对于轨道缺陷数据数据增强要注意场景约束。随机旋转90度对轨道图来说可能是合理的因为铁轨方向在图片里不一定固定但上下翻转要谨慎因为轨面和轨底的纹理差异很大。更有效的是Mosaic增强和Copy-Paste增强把多个缺陷区域粘贴到正常轨道图上相当于凭空多出大量正样本。但粘贴时要注意光照和透视一致性直接硬贴会让模型学到明显的图像拼接痕迹这在缺陷检测里是个常见翻车点。6. 验证模型是否真的能用按缺陷尺寸分层看mAP再看混淆矩阵训练完模型后不要只盯着总mAP。轨道裂缝有很多是小于32x32像素的小目标总mAP高可能只是大目标拉起来的小目标实际一塌糊涂。我习惯用pycocotools跑一个分尺寸的评估按area阈值分成小目标小于32x32像素、中目标32到96、大目标大于96分别看AP。这个操作在YOLOv8的验证输出里没有直接体现需要写几行脚本手动调。from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval coco_gt COCO(annotations/instances_val.json) coco_dt coco_gt.loadRes(outputs/predictions.json) evaluator COCOeval(coco_gt, coco_dt, bbox) evaluator.evaluate() evaluator.accumulate() evaluator.summarize() # 按尺寸查看AP for area_range, name in [([0, 1024], small), ([1024, 9216], medium), ([9216, 100000000], large)]: evaluator.params.areaRng [area_range] evaluator.evaluate() evaluator.accumulate() evaluator.summarize()predictions.json是模型推理结果按COCO格式整理后的文件每项包含image_id、category_id、bbox和score。如果小目标AP明显低于中目标和大目标说明需要提高输入分辨率或者用更擅长小目标的模型结构。除了mAP混淆矩阵也要看。轨道场景里最常见的误检是把裂缝识别成间隙或者反过来这两种缺陷在灰度图上确实容易混淆。混淆矩阵能告诉你模型到底错在哪一类上而不是只知道“精度不够”。我现在的习惯是每次训练完先按缺陷尺寸分层看AP再画混淆矩阵最后剪辑一段包含真实轨道视频的测试片段用模型逐帧跑一遍观察检测框的稳定性。这三步做完才敢说这个模型能现场试运行。这个方法救过我很多次希望帮到你。本文还有配套的精品资源点击获取