小样本轨道故障检测:380张标注图也能训好YOLOv8 📅 发布时间:2026/9/14 14:11:12 👁 浏览次数: 简介铁路轨道故障图像识别数据集面向铁路运维巡检与人工智能初学者提供约380张已标注轨道图像围绕‘损坏’与‘未损坏’两类目标构建二分类任务分类索引及标签映射统一存放在json文件中便于直接读取与验证。数据集已经按训练集、验证集、测试集拆分好目录并附带show可视化脚本可快速抽查每个文件夹中的图像及其标注是否对应从而减少人工整理和排查时间更适合需要快速上手图像分类项目的学习者。整个压缩包共387个文件主体为368张jpg和15张jpeg轨道图片另有少量webp、png格式样本py脚本和json文件分别负责可视化与类别说明压缩包大小约159.73MB目录结构清晰。基于此数据集读者可以实践CNN分类网络也可以参考作者公开的YOLOv5分类博客开展从数据读取、模型训练到效果评估的完整流程适合作为课程设计、算法练习或工业视觉异常检测的入门素材。目前已有190人学习下载。1. 铁路轨道故障图像识别数据集380 张标注图能撑起多大的事一套只有 380 张已标注图像的铁路轨道故障图像识别数据集能撑起多大的项目我的判断是缺陷检测的基线研究和方案论证够用前提是数据核查和训练策略做扎实。难点不在模型结构而在目标本身——轨面裂纹、剥离掉块、扣件缺失在巡检图里常只占几十到几百个像素背景是纹理极强的钢轨道床。这套数据集把深度学习图像识别在轨道巡检上的起点拉平拿到手一两天就能跑出基线。适合刚接手轨道视觉项目的工程师和想验证智能巡检可行性的工务负责人。先说结论380 张用好了完全可能比几千张粗糙标注拿到更高 mAP因为小数据集逼着你把核对、类别平衡、增强幅度这些基本功做到位。2. 数据集的构成与标注规范训练前先把 380 张图的底细摸清2.1 轨道故障图像里通常会标哪几类从我做铁路视觉项目的经验看这类已标注数据集的图像大多来自两类采集设备安装在巡检车底部的轨面相机拍钢轨顶面和两侧或便携式巡检仪沿扣件区域扫拍的近景。标注目标按任务分两派缺陷检测用水平矩形框想把裂缝边界抠得细的团队会用 labelme 这类工具标成多边形甚至参考遥感图像标注里常见的旋转框思路对长条状裂纹做带角度的外接框。类别数一般在 4 到 8 类之间380 张如果超过 6 类大概率存在类别极不均衡的问题训练前必须数一遍。典型类别和视觉特征如下表后两列列的是训练时最容易出问题的地方类别视觉形态占图面积比最容易误检的干扰轨面裂纹细长线状方向多沿钢轨纵向1%水渍、焊缝、划痕剥离掉块片状脱落边界不规则1%5%阴影、油污扣件缺失承轨台结构残缺几何特征改变5%15%杂草遮挡、异物螺栓松动/缺失圆形小目标纹理与周围不同2%8%锈迹、光照反射小目标的检出率上不去很多时候不是模型不行而是标注框把背景包进去太多模型学的特征被钢轨纹理带偏。所以拿到数据集的第一件事不是划分 train/val而是按类别统计实例数量同时抽样看十张最有代表性的图。2.2 标注格式的取舍YOLO txt、COCO 与 VOC先确认交付格式。三种主流格式在轨道项目里都出现过YOLO 的 txt 最轻量一个框一行COCO 是 JSON 结构适合用 mmdetection 的团队VOC 是 XML老项目还在用。格式转换工具一抓一把真正消耗时间的是转换后的逐项核对而不是转换本身。YOLO 格式的一行数据长这样2 0.4851 0.6312 0.0215 0.0478含义是类别 id 为 2框中心点在图像宽 48.51%、高 63.12% 处框宽占整图 2.15%、高占 4.78%。注意第四第五个值是归一化后的宽和高不是右下角坐标。常见的转换错误是把 x1y1x2y2 四个角点直接除以图像宽高得到两个点而不是宽高训练时 loss 会直接发散。另一个高频坑是类别编号从 1 开始而不是从 0 开始yolo 标注数据集一旦整体错位loss 不报警验证时才发现所有类别都预测成相邻类。2.3 用脚本核对标注的三个关键检查点380 张的标注全用眼睛看一遍不现实但训练前花二十分钟跑个检查脚本能拦下九成低级错误。我一般检查三件事类别 id 是否越界、框是否超出图像边界或面积为负、以及每张图的实例数分布是否合理。import os from collections import Counter img_dir images/train label_dir labels/train class_names [rail_crack, spalling, fastener_missing, bolt_missing] cls_counter Counter() for label_file in os.listdir(label_dir): img_id os.path.splitext(label_file)[0] img_path os.path.join(img_dir, img_id .jpg) # 第一层检查标签文件必须能找到对应图像 if not os.path.exists(img_path): print(f[缺图] {label_file}) continue lines open(os.path.join(label_dir, label_file)).read().strip().splitlines() if not lines: print(f[空标注] {label_file}) continue for line in lines: # 第二层检查类别越界与坐标合法范围 cls, xc, yc, w, h line.split() if int(cls) len(class_names): print(f[类别越界] {label_file}: {cls}) if not all(0 float(v) 1 for v in (xc, yc, w, h)): print(f[坐标异常] {label_file}: {line}) cls_counter[int(cls)] 1 # 第三层检查打印类别分布看是否存在极端稀疏类 print(类别分布:, dict(cls_counter))这段脚本按文件粒度扫了三层标签和图像的对应关系、单行数据的数值合法性、全局类别分布。输出为空说明格式层没有硬伤类别分布里如果某个类只有十几二十个实例就得在训练策略里单独照顾它。注意脚本拦不住框标偏了二十个像素这类质量问题还得人工抽检。2.4 比格式更关键的一步先查重复帧这里要泼一盆冷水。380 张里如果有一半来自同一段连续视频相邻帧的相似度极高模型拿到的有效信息量远小于 380。我用感知哈希pHash做过一次统计一段十秒巡轨视频抽出的 60 帧里超过四十帧的哈希距离在 2 以内基本是同一画面的轻微位移。这类重复帧会让验证集虚高mAP 看着不错换一段新线路立刻掉点。处理办法是训练前按图像级相似度去重或者至少按视频分组切分训练集和验证集同一段视频的帧只能进同一侧。如果数据集标注说明里带巡轨视频截帧相机连续采图字样这一步必做。去重完再谈标注工具顺手不顺手。2.5 标注工具的工程选择labelme 与 CVAT个人补标用 labelme 就够多边形标注在裂纹这种长条目标上比矩形框贴近真实边界也方便以后做实例分割但多人协作、几百张以上的补标任务我建议直接用 CVAT 标注工具。它的优势在轨道小目标场景里很具体支持视频帧插值前一帧标完中间帧自动生成能省掉大量重复劳动支持模型预测结果回灌成预标注人工只改错这就是自动标注的标准玩法导出 YOLO 格式不用自己写转换脚本。数据标注规范这件事人越多越值得写成文档框要框住缺陷的最小外接矩形还是包含一部分钢轨纹理做上下文不同标注员的理解差异最后都会变成训练数据里的噪声。开源生态里也有把标注、数据集管理、模型训练、导出串成一体的平台和 CVAT 的任务队列接起来很顺小团队可以省掉自建标注管线的成本。3. 用 YOLOv8 在该数据集上跑通轨道故障检测训练3.1 目录结构与 data.yaml 的最小写法无论交付格式是 COCO 还是 VOC训练前先统一成 YOLO 需要的目录结构images 和 labels 两个根目录下面各放 train、val 子目录同名文件一一对应。整理命令很简单mkdir -p datasets/rail_fault/{images/{train,val},labels/{train,val}} mv train_imgs/*.jpg datasets/rail_fault/images/train/ mv train_labels/*.txt datasets/rail_fault/labels/train/ mv val_imgs/*.jpg datasets/rail_fault/images/val/ mv val_labels/*.txt datasets/rail_fault/labels/val/然后写 data.yamlpath: datasets/rail_fault train: images/train val: images/val names: 0: rail_crack 1: spalling 2: fastener_missing 3: bolt_missing这里最容易犯的错是 path 写绝对路径换台机器就得改文件建议 path 用相对路径训练命令在工作目录下执行。names 的编号必须和标签文件第一列的数字严格对应id 从 0 开始很多标注平台导出时从 1 开始不改就是整体错位的后果。380 张的划分比例我一般按 8:2 左右验证集 60 到 80 张足够看出趋势。3.2 训练命令与关键参数对照数据集小、目标小而杂我建议直接上 YOLOv8 而不是 YOLOv5。v8 把增强开关、EMA、自动锚框这些细节收敛成了显式参数调试时翻车的概率低之前用 YOLOv5 在自己数据集上练过的人迁移过来的学习成本只有命令参数层面的差异。最小可跑的训练命令yolo detect train \ modelyolov8s.pt \ datadatasets/rail_fault/data.yaml \ imgsz640 \ epochs100 \ batch16 \ patience20 \ projectruns/rail_fault \ nameexp1核心参数在轨道故障数据上的取值建议参数取值说明modelyolov8s.pt预训练权重起步s 是精度与体积的平衡点imgsz640 或 1280裂纹占比低于 1% 时 1280 收益明显显存翻倍batch16 或 8显存够优先 16批量归一化的统计量更可靠epochs100配合 patience 使用不必真跑满patience20val 指标连续 20 轮不涨自动停防过拟合device0单卡无 GPU 用 cpu 训练速度慢一个量级建议先用小 imgsz 验证流程3.3 为什么必须从预训练权重而不是随机初始化开始380 张图平均每个类别不到一百个实例随机初始化一个检测头去学钢轨裂纹长什么样参数空间太大收敛极慢且几乎必然过拟合。预训练权重在 COCO 上学到的边缘、纹理、形状组合特征是通用的钢轨表面虽然不在 COCO 的类别里但线状暗色区域圆形金属件边缘这类底层特征完全可以复用。实践里最常见的差距是随机初始化训 100 轮 mAP 不到 0.1预训练微调 30 到 50 轮就过 0.5。这条路没有悬念直接选用带预训练权重的版本。3.4 与开源数据集的差距轨道视觉为什么没有现成迁移目标做故障检测的人第一反应是找开源数据集。公开的故障开源数据集轴承齿轮类大多以振动信号为主和图像识别是两个模态桥墩病害、路面裂缝这类视觉数据与轨道场景有形态相似性但采集视角、背景干扰差异大直接迁移权重收益有限。轨道视觉目前缺一个像 KITTI 之于自动驾驶那样被反复打磨的公共基准很多团队只能在内部数据上从零攒。所以在轨道故障这个小类上预训练在 COCO、微调在自己的数据集是相对可靠的标准路线。后续想抬高基线可以关注最新的图像识别模型如 RT-DETR但第一版别上先用 YOLOv8 把数据质量和评估流程跑通再谈换更强的主干。3.5 半监督思路用伪标签把 380 张扩到上千张380 张实在紧张时常见的做法是半监督学习用第一版模型对着没有标注的巡检视频逐帧推理按置信度阈值过滤出高置信度检测框再人工复核。这个流程在 YOLO 生态里已经工具化CVAT 可以直接导入模型预测结果作为预标注人工只做删改这就是半监督学习标注 yolo 的标准姿势。伪标签的阈值不能定太低轨道故障误检率高错误标注进训练集会反向污染模型。我的经验是 0.6 起步看验证集表现再往下探同时只挑模型有把握的类别回灌难区分的类留给人工。4. 小样本下的数据增强与过拟合控制380 张怎么练不崩4.1 增强参数怎么调才不破坏钢轨故障特征YOLOv8 默认增强在大规模数据集上表现不错但轨道图上几个默认值要动。钢轨表面是金属质感颜色偏移调太大裂纹和水渍的色差会被抹平马赛克增强把四张图拼一起小目标密度提高对细线裂纹帮助明显但也可能把一条完整裂纹拦腰截断。一组合适的小样本增强参数yolo detect train modelyolov8s.pt datadatasets/rail_fault/data.yaml \ imgsz1280 epochs100 batch8 \ hsv_h0.01 hsv_s0.3 hsv_v0.3 \ degrees15 translate0.1 scale0.4 fliplr0.5 \ mosaic0.8这里的逻辑按参数拆开看hsv_h 收敛到 0.01避免金属本色被过度改动degrees 给到 15因为巡检相机角度随车体振动变化小角度旋转能模拟这种抖动mosaic 保留 0.8 让每个 batch 的小目标数量尽量多。如果显存吃紧退回 imgsz640mosaic 也要相应降一点否则拼接后目标进一步变小超出网络有效感受野。增强不是开得越猛越好判断标准只有一个增强后的图像人眼还能不能认出这是钢轨。4.2 从 loss 曲线和验证指标判断过拟合时机小数据集训练最怕的不是学不会而是学过头。每轮结束看 runs/rail_fault/exp1/ 下的 results.png重点盯三条线train/box_loss、val/box_loss、metrics/mAP50。val 的 box_loss 出现先降后升的拐点而 train/box_loss 还在下行就是典型的过拟合信号模型把巡检车固定机位的背景纹理背下来了换一段新视频立刻失准。判读对照表现象可能原因处理train/box_loss 降、val/box_loss 升模型记忆背景纹理信任 patience 提前停别硬跑满mAP50 震荡、个别类 AP 为 0该类别样本太少该类别过采样或补伪标签增强强度加大后 mAP 反降增强破坏了金属纹理调低 hsv_h、degrees、mosaicval 指标一直不涨train 也跌得慢学习率过低或类别错位检查 lr 与标签 id 映射正确姿势是让 patience 自动切断训练而不是盯着 epoch 数硬等。我在类似规模的病害数据上见过 mAP50 在 40 到 60 轮之间爬升、过 70 轮后 val 指标不再更新patience20 在 90 轮及时停住省下的时间全用来调参。4.3 K 折交叉验证小数据集的真实性能怎么测380 张的随机划分有个隐患某一类别恰好集中在验证集里这一折的 mAP 会跌到没法看。K 折交叉验证能给出更真实的性能区间代价是训练 K 次。轨道图像一般用 5 折from sklearn.model_selection import KFold import os images sorted(os.listdir(datasets/rail_fault/images/train)) kf KFold(n_splits5, shuffleTrue, random_state42) for fold, (train_idx, val_idx) in enumerate(kf.split(images)): # 第 fold 折train_idx 的图像进训练集val_idx 进验证集 print(ffold {fold}: train{len(train_idx)} val{len(val_idx)})K 折的代价是五倍训练时间。380 张、yolov8s、单卡 3090 每折约 20 到 40 分钟可以接受。如果数据来自同一段视频先按视频片段分组再做 GroupKFold防止同一场景的近似帧同时出现在训练和验证里那是评估结果的虚假繁荣。五折的 mAP 方差如果超过 0.15说明数据集本身不稳定这时先别调模型回头补数据或查标注。4.4 类别不均衡、学习率与权值衰减的经验值类别超过 4 类时先跑一遍类别分布统计某个类别样本占比低于 5%就要处理不均衡。两个常用手段一是做少数类过采样把该类图像复制几份再进训练简单直接二是在推理阶段按类别单独调置信度阈值让模型对稀疏类更敏感。直接改分类 loss 权重在 YOLO 里也能做但效果不稳容易出现压制多数类的新问题。学习率方面微调阶段 lr0 我一般取 0.005 到 0.01而不是默认更大的值380 张的小数据集上学习率过大loss 前几十轮剧烈震荡边学边忘。weight_decay 保持默认 0.0005调大对抑制过拟合帮助有限反而推迟小目标收敛。5. 轨道故障识别模型的四步专项验证5.1 在验证集上跑一次完整的评估输出训练结束后跑的验证命令和训练时用的评估逻辑必须一致指标才可比yolo detect val \ modelruns/rail_fault/exp1/weights/best.pt \ datadatasets/rail_fault/data.yaml \ imgsz1280输出里除了 mAP50、mAP50-95 的总体数字重点看每个类别的 AP。裂纹和螺栓缺失的 AP 通常差开两三个档次这不是坏事它指出该往哪个类别补数据。小目标类别 AP50 低于 0.3 时先回头查该类标注框有没有把背景包进去再考虑 imgsz 提到 1280。5.2 混淆矩阵与误检来源的定向排查验证输出的 confusion_matrix.png 里对角线是正确分类最右侧一列是背景误检。轨道项目里有个规律扣件缺失和螺栓缺失经常互相混因为两者在视觉上都是本该有东西的位置空了。这种混淆加数据不如改类别定义两个类别边界模糊时合并成一个紧固件异常类别模型更容易学。对每类误检把置信度阈值从 0.25 提到 0.5看 precision 和 recall 的剪刀差。轨道巡检场景漏检代价远高于误检部署阈值一般往低放宁可多报让下游人工复查也不要让缺陷溜过去。5.3 三个必须人工复查的泛化场景脚本评估之外留一小批刁钻图像做人工抽检三个场景必测逆光或强反光下轨面高光区域、雨后钢轨表面带水渍的反光纹理、道床材质或颜色与训练集差异明显的路段。这三个场景最容易暴露过拟合模型可能把反光当裂纹、把水渍当剥离。做法是把这批图单独放一个目录导出预测可视化结果快速扫一遍比任何指标都直接。另外建议用连续视频帧做一次时序一致性检查同一缺陷在相邻帧的检测框如果跳来跳去、置信度忽高忽低说明模型对背景纹理敏感部署到实时巡检场景会出现报警闪烁需要在后处理里加帧间平滑。5.4 导出前用 onnxruntime 做一次离线推理核对部署端验证有个常被跳过的步骤用和训练框架不同的推理后端做一致性检查。导出命令极简yolo export modelruns/rail_fault/exp1/weights/best.pt formatonnx imgsz1280 opset12导出后用 onnxruntime 加载模型对十张验证图分别用 PyTorch 和 ONNX 做前向对比输出框的坐标与类别。两者坐标偏差超过 1 个像素或类别出现不一致多半是导出时的 imgsz 与训练不一致或 opset 版本引起算子精度差异。这一步做到位再往边缘设备或巡检平台上搬就不容易在现场翻车。无论验证集指标多漂亮轨道故障图像识别的交付标准始终是现场抽检通过率mAP50 只是内部参考把现场抽检通过率放在 mAP50 前面这一个习惯能少踩一半部署坑。本文还有配套的精品资源点击获取