
简介这份数据集面向使用YOLO系列模型进行工业管道缺陷检测的学习者与研究者覆盖裂纹、孔洞、屈曲、碎片四类常见缺陷可用于目标检测模型的训练、验证与效果对比。资源已预先划分训练集、验证集与测试集并附带data.yaml配置文件省去自行切分与整理标注的步骤。压缩包共2000个文件包含1000个XML标注、999个TXT标注与1个YAML配置整体约18.99MB其中TXT采用归一化坐标记录类别编号与目标框中心点、宽高比例XML则遵循VOC坐标规范两种格式按类别特征分目录存放便于按需选用。目前已有151人学习下载适合从YOLOv5到YOLOv11等版本快速接入实验帮助读者把精力集中在模型调参与缺陷识别效果分析上而非数据清洗与格式转换。1. 管道缺陷检测为什么值得用 YOLO 系列啃下来城市地下管网每公里每年新增的缺陷点远超巡检人力能覆盖的速度燃气、供水、排水行业里「查不完、看不准、记不细」是常态。管道缺陷检测数据集1000张图像标注裂纹/孔洞/屈曲/碎片缺陷这个标题说的就是一件很具体的事——用 1000 张带标注的管道内窥图像训练一个能识别裂纹、孔洞、屈曲、碎片四类缺陷的 YOLO 检测器。它解决的不是「有没有缺陷」而是「缺陷在哪、属于哪一类、面积多大」直接对应巡检报告里的定位与分级需求。适合两类人一类是手里已经攒了几百上千张爬行器或内窥镜截图、想跑通训练闭环的工程人员另一类是刚接触 YOLO 训练、想找一个真实工业场景数据集练手的目标检测新手。1000 张这个量级不算大但四类缺陷的类间差异明显、类内差异也大正好能暴露小数据集训练里最典型的坑。2. 数据集拆解与 YOLO 格式转换从原始标注到可训练标签2.1 四类缺陷的视觉特征与标注边界裂纹、孔洞、屈曲、碎片这四类在管道内窥图像里的视觉表现差异很大标注时最容易出问题的不是「标不标」而是「边界画到哪」。裂纹通常是细长、低对比度的暗线走向不规则标注框如果只框住最黑的一段模型学到的就是碎片化的局部特征正确做法是沿裂纹主走向拉一个能覆盖整条裂纹的最小外接矩形宽度可以略宽于裂纹本身。孔洞多为圆形或椭圆形暗区边界相对清晰但要注意区分「真孔洞」和「镜头污渍造成的暗斑」后者不应标注。屈曲是管道截面变形表现为局部轮廓内凹或椭圆度突变标注框往往偏大需要覆盖变形区域整体。碎片是剥落或堆积的块状物边界模糊标注时以可见块状主体为准不要把周围阴影一起框进去。这四类缺陷在 1000 张图像里的分布通常不均衡裂纹和碎片出现频率高屈曲和孔洞偏少。如果直接按原始分布训练模型会偏向多数类。常见做法是在划分训练集时对少数类做适度过采样或者在损失函数里给少数类更高权重。标注格式上原始数据可能是 LabelImg 的 XML、LabelMe 的 JSON也可能是分割掩码。YOLO 检测训练需要的是归一化后的class_id x_center y_center width height文本格式每张图一个.txt类别编号从 0 开始。2.2 从 XML/JSON 转 YOLO txt 的脚本与四个边界坑下面这段脚本处理 LabelImg 风格的 XML转成 YOLO 需要的归一化 txt。逻辑是遍历 XML 里的每个object读取类别名和bndbox坐标按图像宽高归一化后写入同名 txt。import os import xml.etree.ElementTree as ET # 类别映射顺序决定 class_id必须与训练时的 data.yaml 一致 CLASS_MAP {crack: 0, hole: 1, buckling: 2, debris: 3} def convert_xml_to_yolo(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 图像宽高从 XML 的 size 节点读取避免额外打开图片 size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue # 跳过未定义类别防止 class_id 错位 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 边界裁剪防止标注越界导致归一化后超出 [0,1] xmin max(0, min(xmin, w)) xmax max(0, min(xmax, w)) ymin max(0, min(ymin, h)) ymax max(0, min(ymax, h)) if xmax xmin or ymax ymin: continue # 跳过退化框 x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{CLASS_MAP[name]} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) out_path os.path.join(out_dir, xml_file.replace(.xml, .txt)) with open(out_path, w) as f: f.write(\n.join(lines)) convert_xml_to_yolo(annotations_xml, images, labels_yolo)参数说明CLASS_MAP的键必须和 XML 里的name完全一致大小写敏感x_center等归一化值保留 6 位小数足够YOLO 读取时会再解析。四个边界坑分别是第一XML 里size的宽高和实际图像不一致常见于图像被缩放后标注没同步解决方法是转换时用 PIL 重新读一次图像尺寸做校验第二类别名有空格或大小写混用导致CLASS_MAP匹配失败转换后该类样本全部丢失解决方法是先统计所有name取值再建映射第三坐标越界标注框超出图像边界归一化后出现负值或大于 1YOLO 训练时可能直接报错或静默丢弃脚本里已做裁剪第四空标注文件某些图像确实无缺陷生成的 txt 为空文件YOLO 默认会跳过但如果你的数据集里空文件比例高需要确认这些图是否应该保留为负样本。2.3 数据集划分与 data.yaml 配置1000 张图像按 8:1:1 划分训练、验证、测试即 800/100/100。划分时要保证四类缺陷在三个子集里的比例大致一致尤其是屈曲和孔洞这类少数类不能出现验证集里一个都没有的情况。常见做法是先按类别分层抽样再合并。划分完成后目录结构如下dataset/ images/ train/ val/ test/ labels/ train/ val/ test/ data.yamldata.yaml是 YOLO 训练的数据入口内容如下path: /data/pipeline_defect train: images/train val: images/val test: images/test nc: 4 names: [crack, hole, buckling, debris]nc必须等于类别数names顺序必须和转换脚本里的CLASS_MAP一致否则训练出来的模型会把裂纹识别成孔洞。path用绝对路径最稳相对路径在不同 YOLO 版本里解析基准可能不同。如果用的是 YOLOv8 及以上data.yaml直接传给训练命令即可YOLOv5 需要额外确认train和val路径是相对于path还是相对于 yaml 文件本身这个差异在版本迁移时经常导致「找不到图片」的报错。3. 用 YOLOv8 在 1000 张管道缺陷图上跑通训练3.1 环境配置与预训练权重选择管道缺陷检测属于小数据集、四类目标、工业图像选 YOLOv8n 或 YOLOv8s 起步最合适。n 版本参数量小1000 张图训练一轮几十秒适合快速验证标注质量和数据管线s 版本精度更高但需要更多轮次才能收敛。如果显存只有 8GB 以下从 n 开始12GB 以上可以直接上 s。环境用 conda 建一个独立环境Python 3.9 或 3.10 都可以ultralytics 包会自带 PyTorch 依赖。conda create -n pipe_yolo python3.10 -y conda activate pipe_yolo pip install ultralytics预训练权重用 COCO 上训好的yolov8n.pt或yolov8s.pt。管道缺陷和 COCO 的自然图像差异大但底层边缘、纹理特征仍然可迁移从预训练权重起步比从头训收敛快很多尤其是在 1000 张这个量级上。常见做法是先用 n 版本跑 50 轮看 loss 曲线和验证集 mAP确认数据没问题后再换 s 版本跑 100 到 200 轮。3.2 训练命令与关键参数怎么设yolo detect train \ data/data/pipeline_defect/data.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ device0 \ projectruns/pipe \ namev8n_640参数逐个说imgsz640是输入分辨率管道内窥图像如果原始尺寸远大于 640缺陷目标在缩放后会变得很小这时可以考虑imgsz960或1280但显存占用和训练时间会明显上升。batch16在 8GB 显存上跑 640 分辨率通常够用如果 OOM 就降到 8。lr00.01是初始学习率小数据集上这个值偏大时 loss 会震荡可以降到 0.005。lrf0.01是最终学习率相对初始值的比例YOLOv8 默认余弦退火这个值控制退火终点。patience30表示验证集指标 30 轮不提升就早停1000 张图通常 80 到 120 轮就收敛设 30 能省时间。device0指定第一块 GPUCPU 训练会慢到不可接受。训练过程中重点看三个输出train/box_loss是否稳定下降、val/mAP50是否在上升、val/mAP50-95是否同步改善。如果 box_loss 下降但 mAP 不涨通常是过拟合需要加数据增强或减模型容量如果 box_loss 震荡先降学习率如果 mAP 从第一轮就接近零且不涨大概率是标签格式或类别映射错了。3.3 训练结果解读与混淆矩阵排查训练结束后runs/pipe/v8n_640/下会有weights/best.pt、results.csv、confusion_matrix.png等文件。results.csv里每轮的 loss 和 mAP 可以直接用 pandas 读出来画曲线。混淆矩阵是排查类别混淆的第一手材料如果裂纹和碎片之间大量互相误判说明这两类的视觉特征在标注时边界没划清需要回看标注如果某一类整行都是零说明该类在验证集里样本太少或标注全部丢失。import pandas as pd df pd.read_csv(runs/pipe/v8n_640/results.csv) df.columns df.columns.str.strip() # 列名可能带空格 print(df[[epoch, train/box_loss, metrics/mAP50, metrics/mAP50-95]].tail(10))这段代码读取训练日志看最后 10 轮的指标是否已经平稳。如果 mAP50 在最后 10 轮波动小于 0.005说明已经收敛再加轮次意义不大。如果还在明显上升可以调大epochs或减小patience后继续训。4. 小数据集训练管道缺陷的避坑与排查4.1 验证集 mAP 高但实际推理漏检严重现象训练日志里val/mAP50到 0.85 以上但拿现场新图推理时裂纹和碎片大量漏检。原因通常是验证集和训练集来自同一批图像、同一段管道分布几乎一致模型记住了背景纹理而不是缺陷本身。解决方法是划分数据集时按管道段或采集批次分组确保验证集里的管道背景和训练集不重叠同时开启 Mosaic 和 MixUp 增强YOLOv8 默认已开 Mosaic可以额外调mixup0.1。如果现场图亮度、对比度和训练图差异大推理前做一次直方图均衡或 CLAHE 预处理能明显改善。4.2 训练中 box_loss 变成 NaN现象训练几轮后train/box_loss突然变成nan后续所有指标失效。原因常见于标注框归一化后宽或高为 0或者坐标出现负值YOLO 在计算 IoU 时除零。解决方法是训练前跑一遍标签校验脚本检查每个 txt 里是否有width0或height0的行以及坐标是否都在[0,1]区间。另一个诱因是学习率过大导致梯度爆炸把lr0从 0.01 降到 0.001 再试。如果用了混合精度训练某些极端小框在 FP16 下也会产生 NaN可以设ampFalse排除。4.3 屈曲和孔洞两类召回率始终偏低现象裂纹和碎片的 mAP 能到 0.8 以上屈曲和孔洞只有 0.4 到 0.5。原因是这两类在 1000 张里样本数少且屈曲的形态变化大孔洞容易和污渍混淆。解决分三步第一统计每类实例数如果屈曲少于 80 个考虑对含屈曲的图像做旋转、翻转、亮度扰动来扩充第二在data.yaml同级目录下用copy_paste增强把少数类实例粘贴到其他管道背景上YOLOv8 支持copy_paste0.3第三如果孔洞和污渍混淆严重回看标注把明显是污渍的暗斑从孔洞类里剔除宁可少标也不要错标。4.4 推理时同一缺陷被多个框重复检出现象一张图里一条裂纹被 3 到 4 个框分别框住NMS 后仍然重叠。原因是裂纹细长模型在多个位置都激活且默认 NMS 的 IoU 阈值 0.7 对细长目标偏松。解决方法是在推理时调低iou参数到 0.5 或 0.45yolo detect predict modelbest.pt sourcetest.jpg iou0.45。如果仍然重叠说明训练时同类缺陷的标注框本身就有重叠需要回看标注是否把一条裂纹拆成了多个框。另一个技巧是训练时设overlap_maskFalse分割任务或对检测任务直接依赖 NMS不要手动合并框。4.5 换 YOLOv5 或 YOLOv11 后训练报错现象同一份data.yaml和标签在 YOLOv8 上能训换到 YOLOv5 报「No labels found」或换到 YOLOv11 报类别数不匹配。原因是不同版本对data.yaml的路径解析和nc字段处理有差异。YOLOv5 要求data.yaml里train和val是相对于path的路径且nc可以省略由names长度推断YOLOv11 的 ultralytics 接口和 v8 基本一致但旧版yolov5仓库的train.py参数名不同。解决方法是每个版本用对应的官方仓库和对应的data.yaml模板不要跨版本直接复制。标签格式本身在 v5、v8、v11 之间是兼容的问题几乎都出在配置解析上。5. 把 1000 张的模型推到现场可用的几个技巧1000 张训练出来的模型直接上线通常不够稳但通过几个后处理技巧可以明显提升现场可用性。第一个技巧是推理时的多尺度测试TTAYOLOv8 支持augmentTrue推理时对图像做翻转和缩放增强再合并结果mAP 通常能涨 1 到 3 个点代价是推理时间翻倍。对于巡检场景单张图推理从 20ms 涨到 40ms 完全可以接受。yolo detect predict \ modelruns/pipe/v8n_640/weights/best.pt \ source/data/field_images \ imgsz960 \ conf0.35 \ iou0.45 \ augmentTrue \ save_txtTrue \ projectruns/fieldconf0.35比默认 0.25 高是为了压掉管道内窥图像里大量纹理噪声引起的低置信度假阳性iou0.45压重叠框save_txtTrue把检测结果存成 YOLO 格式方便后续和巡检报告系统对接。imgsz960比训练时的 640 大是因为现场图里小缺陷多推理分辨率略高于训练分辨率通常能提升小目标召回但不要高太多否则和训练分布差异过大会掉点。第二个技巧是类别特定的置信度阈值。四类缺陷的误检代价不同孔洞误检可能导致不必要的开挖裂纹漏检可能放过结构性风险。可以在推理后处理阶段对孔洞类设更高的conf对裂纹类设更低的conf。YOLO 原生不支持按类设阈值但save_txt输出的结果里带类别和置信度可以写一个简单的过滤脚本import os # 按类别设置不同置信度阈值 CONF_THRESH {0: 0.30, 1: 0.50, 2: 0.40, 3: 0.35} # crack, hole, buckling, debris def filter_by_class(txt_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for txt_file in os.listdir(txt_dir): if not txt_file.endswith(.txt): continue kept [] with open(os.path.join(txt_dir, txt_file)) as f: for line in f: parts line.strip().split() if len(parts) 6: continue cls_id int(parts[0]) conf float(parts[5]) if conf CONF_THRESH.get(cls_id, 0.35): kept.append(line.strip()) with open(os.path.join(out_dir, txt_file), w) as f: f.write(\n.join(kept)) filter_by_class(runs/field/labels, runs/field/labels_filtered)这段脚本读取 YOLO 推理保存的 txt每行格式是class_id x_center y_center width height conf按类别阈值过滤后写入新目录。CONF_THRESH里的值需要根据现场误检情况调整孔洞设 0.50 是假设误检代价高裂纹设 0.30 是假设漏检代价高。这个策略在巡检报告场景里比统一阈值实用得多。第三个技巧是用验证集上的 PR 曲线反推最佳工作点。YOLO 训练后会生成PR_curve.png横轴是召回纵轴是精确率。现场应用如果要求召回不低于 0.9就在 PR 曲线上找召回 0.9 对应的精确率和置信度把这个置信度作为该类阈值。这比拍脑袋设 0.5 有依据。我自己的习惯是每次换数据集或换模型版本都重新看一遍 PR 曲线把四类的阈值记在一个配置表里推理脚本直接读表不硬编码。最后一个习惯1000 张这个量级不要指望一次训练就定稿。我一般会跑三组对照——n 和 s 各一组、640 和 960 各一组、默认增强和加 copy_paste 各一组用验证集 mAP 和现场抽样 50 张的漏检率一起判断。现场抽样那 50 张一定要包含不同管道材质、不同光照条件否则验证集上的数字会骗人。这套流程跑下来1000 张管道缺陷图训出的模型在巡检辅助场景里能做到可用但离全自动判定还有距离定位和分类可以信分级和风险评估还得靠人复核。希望帮到你。本文还有配套的精品资源点击获取