ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

下水道缺陷检测数据集实战:YOLO训练与避坑指南

下水道缺陷检测数据集实战:YOLO训练与避坑指南 简介面向YOLO系列目标检测算法的下水道缺陷数据集覆盖关节偏移、障碍物、裂纹、带扣、洞、公用设施入侵、碎片等典型缺陷类别并已划分训练集、验证集与测试集可直接用于模型训练、验证与测试适合市政管网检测研发人员及目标检测算法初学者。压缩包共2000个文件其中1636个XML文件为VOC格式标签、364个TXT文件为YOLO格式标签两种格式分目录存放同时提供data.yaml配置文件能够不经额外转换直接对接YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10及YOLO11等主流版本整个包体仅7.43MB已有66人学习下载。标签文件名末尾带有类别名称方便按缺陷类型筛选样本YOLO标签采用从0开始的类别索引目标框中心坐标与宽高均按图像尺寸归一化格式规范符合训练脚本默认读取要求。若需了解具体类别标签可在资源详情页核对。这套数据既适合快速搭建下水道缺陷检测模型也适合标签格式转换练习、不同YOLO版本对比实验以及数据增强策略验证等场景。1. 下水道缺陷检测的数据底子2364张标注图先解决「有没有」的问题做市政管网缺陷检测的工程师多半经历过这种尴尬项目立项时甲方要求识别裂纹、障碍物、带扣、洞真到了训练阶段才发现内部资料库里全是没标注的原始巡检视频掏钱买公开数据集又买不到细分类的下水管道场景。这份2364张带标签的下水道缺陷数据集解决的就是这个「有没有数据」的冷启动问题。它把关节偏移、障碍物、裂纹、带扣、洞、公用设施入侵、碎片七类常见缺陷做成了一套YOLO可直接训练的工程包训练集、验证集、测试集已经划分完毕data.yaml配置齐全适用于yolov5到yolo11全系版本。适合正在做YOLO系列目标检测算法验证、需要快速跑通管道缺陷识别流程的算法工程师和研究生也适合刚上手YOLO的开发者拿它当第一个完整训练范例。2. 标签格式先看懂yolo归一化坐标与voc双轨并存拿到数据集先别急着训练第一步要搞清楚它的标注组织方式。这套数据最值得肯定的一点是同时提供了 yolo 格式txt和 voc 格式xml分别存放在两个文件夹里。YOLO系训练直接读txt而xml可以用于mAP评测时的voc指标计算或者转成coco格式做横向对比。两种格式并存不是冗余而是让同一批图在不同框架和评测体系里都能复用。2.1 txt与xml双轨并存文件组织与类别索引文件名形如img_0319_1048.txt对应同一批图像文件的标注信息。每个txt文件里可能有一行或多行标注每行代表一个目标框格式如下class x_center y_center width height前面提到文件名末尾是部分类别名称但文件内容才是真正的标注依据。读取时不能只看文件名判断类别要以txt第一列的class索引为准。YOLO格式的类别索引从0开始和voc格式xml里的对象名称一一对应。下面这段脚本可以快速扫描整个标签目录统计出当前一共标注了多少目标、每个类别占多少比例import os from collections import Counter label_dir labels/train # 按你的实际解压路径修改 counter Counter() total_boxes 0 for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname), r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) 5: cls int(parts[0]) counter[cls] 1 total_boxes 1 else: print(f格式异常: {fname} - {line.strip()}) print(总目标框数:, total_boxes) for cls, cnt in sorted(counter.items()): print(fclass {cls}: {cnt})这段脚本做了两件事统计每个类别的目标数量同时标记出格式异常的行。跑完你会对类别不平衡程度有个直观认识。如果某个类别的框数远低于其他类说明后续训练时要考虑类别权重或者数据增强策略。注意label_dir路径要改成你本机实际解压出来的标签目录如果你把train和val的标签分开存放就分别统计。结合摘要里给出的类别清单实际类别索引映射大致是0代表关节偏移1代表障碍物2代表裂纹3代表带扣4代表洞5代表公用设施入侵6代表碎片。具体索引值可能因打包顺序不同而有差异保险做法是打开任何一个xml文件确认对象名称和索引的对应关系再决定data.yaml里怎么配置names列表。2.2 归一化坐标的数学含义与标注质量检查txt里存的x_center、y_center、width、height都是相对图像宽度和高度的比例值范围在0到1之间。实际像素坐标需要乘以图像的宽高才能还原框左上角x像素 (x_center - width/2) × 图像宽度框左上角y像素 (y_center - height/2) × 图像高度这个转换逻辑是后续做标注可视化和数据增强验证的基础。很多初学者直接拿归一化坐标去画图结果框的位置完全错位就是忘了乘回图像尺寸。更隐蔽的坑是有些标注框的中心点坐标或宽高虽然都在0~1之间但组合起来框已经超出图像边界比如x_center0.95, width0.2左边越界了。这类问题不会报错但会影响训练时的anchor匹配和NMS表现。我习惯在训练前跑一遍边界校验脚本import os from PIL import Image img_dir images/train label_dir labels/train img_w, img_h 640, 640 # 先给默认值遇到真实图片会覆盖 for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue img_name fname.replace(.txt, .jpg) img_path os.path.join(img_dir, img_name) if os.path.exists(img_path): with Image.open(img_path) as im: img_w, img_h im.size with open(os.path.join(label_dir, fname), r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls, xc, yc, w, h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) # 还原像素坐标 x1 (xc - w / 2) * img_w y1 (yc - h / 2) * img_h x2 (xc w / 2) * img_w y2 (yc h / 2) * img_h if x1 0 or y1 0 or x2 img_w or y2 img_h: print(f越界框: {fname} - cls{cls}, box({x1:.1f},{y1:.1f},{x2:.1f},{y2:.1f}), 图像尺寸({img_w},{img_h}))参数说明img_w和img_h在循环里动态更新避免硬编码错误。还原计算时用xc - w/2计算左边界、xc w/2计算右边界比较是否小于0或大于图像宽高。如果某个框越界打印出来的信息里包含文件名、类别和还原后的像素坐标方便你回去核对原始标注。这类越界框通常来自标注工具的边缘误操作数量多的话建议过滤掉而不是直接拿来训练。3. 配置data.yaml与训练启动yolov8到yolo11都能跑理解了标签格式接下来就是把数据组织成YOLO训练工程的标准目录结构然后启动训练。这一步决定了你后面所有实验是否可复现建议把train、val、test的图片和标签都放进固定目录不要散落在桌面或临时文件夹里。3.1 目录整理与data.yaml配置理想的项目目录结构应该是sewer_defect_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── xml_labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml如果下载解压后的目录结构和上面不完全一致先手动整理成这个形态再配置yaml。data.yaml是YOLO训练时唯一必须改对的文件它的路径字段决定了数据加载器去哪里找图。下面是这份数据配套的data.yaml典型配置path: D:/sewer_defect_dataset # 数据集根目录绝对路径更稳妥 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 test: images/test # 测试集图片相对路径可选 nc: 7 # 类别总数 names: 0: joint_offset 1: obstacle 2: crack 3: buckle 4: hole 5: utility_intrusion 6: debrispath字段是根目录train、val、test写的是相对路径两者拼接后就是完整的图片目录。nc必须和names列表长度一致这是训练程序校验类别数用的。特别提醒如果你在Windows上训练path建议用绝对路径避免相对路径拼接时因为盘符问题找不到文件如果在Linux服务器上训练绝对路径同样最省事省得每次换机器都要改配置。3.2 yolov8训练命令与关键参数选择数据目录整理好之后训练命令本身不长但几个关键参数直接决定训练结果。拿yolov8来举例我的习惯是关闭预训练权重对应的数据集假设用coco预训练模型做迁移学习同时选择适合小数据量的增强策略。yolov8官方仓库训练入口是yolo命令行工具yolo detect train \ modelyolov8m.pt \ datasewer_defect_dataset/data.yaml \ epochs150 \ imgsz640 \ batch16 \ lr00.005 \ optimizerAdamW \ patience30 \ projectsewer_runs \ nameexp_sewer_v8m \ cacheTrue参数说明modelyolov8m.pt加载COCO预训练权重m版本在精度和速度之间比较平衡epochs150对于2364张图的中等规模数据集够用imgsz640和训练时推理尺寸保持一致batch16根据显存调整8G显存建议降到8lr00.005是从经验值里选的小学习率避免预训练权重被大步长破坏patience30表示连续30轮验证集指标不提升就早停。cacheTrue可以把数据缓存进内存第二次训练时加载速度明显加快。训练完成后在sewer_runs/exp_sewer_v8m/weights/目录下会有best.pt和last.pt验证和预测都用best.pt不用last.pt这是防止过拟合导致的验证集指标虚高。3.3 yolov5与yolo11的兼容差异如果你的环境是yolov5训练命令几乎一样区别在于yolov5的data.yaml里不需要额外的test字段也能跑而且yolov5默认用hyp.scratch-low.yaml超参数学习率策略偏保守。yolov5训练命令参考python train.py \ --data sewer_defect_dataset/data.yaml \ --weights yolov5m.pt \ --img 640 \ --batch 16 \ --epochs 150 \ --name sewer_v5m \ --project sewer_runsyolov5和yolov8的主要差别在数据增强策略yolov5默认开启mosaic和mixupyolov8的augment参数控制力度。yolo11回归了更简洁的配置方式训练命令可以直接用yolo detect train接modelyolo11m.pt。无论用哪个版本data.yaml这个文件是通用的这也是一份数据集同时声明支持多版本的原因。实际使用中yolov8和yolo11的NMS策略略有差异但在这种类别较集中的缺陷检测场景下肉眼可见的差距不大优先选你环境里依赖最少的版本即可。4. 训练避坑记录五条实测踩坑与排查数据集的标签质量整体不错但在实际训练和复现过程中有几个坑是大概率会踩到的我把排查过程和解决方式记录下来。每条都按现象、原因、解决的顺序写清楚方便你对号入座。4.1 训练到一半loss飞升检查mosaic增强是否越界现象训练到20~30轮时train loss突然从零点几跳到几十val loss同步飙升之后再也降不回来。原因这类数据里有不少缺陷目标紧贴图像边缘比如裂纹从图边缘开始延伸。YOLO默认开启mosaic增强把四张图随机拼接缩放边缘目标在拼接过程中被裁掉或者框的坐标计算出现偏差导致训练梯度异常。加上下水道图像本身光照不均mosaic拼接后对比度差异大模型学到的是伪特征。解决训练命令里加mosaic0.0关闭mosaic或者用close_mosaic10让最后10轮关闭mosaic做微调。yolov8可以用mosaic0.2保留低概率的mosaicyolov5则在hyp.scratch-low.yaml里把mosaic参数直接改为0。关闭后loss曲线会明显稳定下来。4.2 验证集mAP不低但检测视频时漏检碎片现象验证集mAP0.5达到了0.75以上但跑实际巡检视频时小碎片目标大量漏检尤其是尺寸小于32×32像素的碎片。原因2364张图里碎片类别的标注框数量虽然不少但很多碎片目标框边长占整个图片的比例不到5%。模型在640×640输入下经过多次下采样小目标的特征图分辨率不足以保留足够信息再加上默认anchor尺寸偏大小目标匹配不上。解决把imgsz从640提高到768或896小目标检测率会显著提升代价是训练和推理时间变长。如果显存不够可以加augmentTrue配合scale0.5做多尺度训练。另一个有效手段是单独增大小目标对应的anchor但yolov8自动anchor机制下通常不需要手动调优先改imgsz。4.3 重新划分数据集后结果无法复现检查随机种子现象有人重新划分了train和val用同样的参数训练得到的结果和配套实验记录对不上mAP差了5个点以上。原因数据划分本身是随机的每次划分后训练集和验证集的内容不一样。如果这份数据集已经被划分为固定版本你重新划分就相当于换了一组数据结果自然不同。另一个隐藏因素是多卡训练时每张卡的batch分配不同BN层的统计量会有细微差别。解决使用压缩包内已有的划分不重新划分。训练命令里固定seed42如果使用yolov5还需要在启动训练前设置torch.manual_seed(0)。多卡训练时尽量保持batch设置一致不要随意改batch导致复现困难。4.4 同时改txt和xml导致标注漂移现象发现某个标注框位置不对手动修改了txt文件但验证时xml格式的标注还是旧的导致评测结果为0。原因同时维护两套标注格式时修改只做了一半。这类双格式数据集最忌讳只更新一边因为后续的v0评测脚本可能读txt而voc指标计算读xml两边不一致时结果互相矛盾。解决修改标注时以xml为准改完用脚本重新生成对应的txt不要手写txt。可以用Ultralytics仓库里的xml2yolo.py脚本批量转换转换时确认类别索引映射表的顺序和原包一致。每次修改完标注文件跑一遍前面2.2节里的边界校验脚本确认两套格式都同步更新。4.5 中文路径导致dataloader找不到图片现象训练启动后立刻报错提示找不到图片文件但路径明明存在。仔细看报错信息路径里的中文目录名变成了乱码。原因Windows系统下代码默认编码是GBK而数据集目录如果包含中文Ultralytics的dataloader在拼接路径时可能编码不兼容。这种情况在Linux服务器上很少见主要在Windows本机训练时出现。解决把数据集放在纯英文路径下比如D:/sewer_defect_dataset不要放在D:/数据集/这种目录下。如果已经放在中文路径里复制到英文目录重新配置data.yaml的绝对路径即可不需要改代码。这是最省钱的处理方式。5. 进阶验证技巧类别合并、混淆矩阵与迁移微调训练跑通只是第一步这类缺陷检测数据集真正的价值在于帮你在真实场景里做决策「模型能跑」和「模型能用」之间还差几个验证技巧。第一个技巧是看混淆矩阵找「分不清的类别对」。训练完成后yolov8会在runs/目录下生成confusion_matrix.png重点关注关节偏移和带扣这一类形态相似的缺陷。下水道管壁的环形结构和破损处的纹理非常接近模型很容易把关节偏移错判成带扣。如果你的混淆矩阵里这两个类别互相误检率超过20%建议直接做类别合并——把这两类合成一个「结构破损」类。缺陷检测项目的核心指标是「不漏检」合并后mAP会上升漏检率下降甲方现场验收反而更容易通过。第二个技巧是用小学习率做迁移微调。如果你手头有自己项目里的少量标注数据这份数据集可以当预训练语料。做法是先用2364张图训出best.pt然后加载这个权重在自己的小数据集上继续训练epochs改成50lr0从0.005降到0.0005用freeze10冻结前10层只微调检测头。第三个技巧是验证集做硬负样本补充。把测试集里模型漏检或误检严重的图找出来单独建一个hard_test目录每次迭代模型后优先跑这批图观察改进幅度。这个习惯能快速定位模型在小碎片、低光照场景下的瓶颈比只看mAP数值有效得多。这套数据我前后跑了四个版本的YOLO最大的收获不是精度数字而是养成了一个习惯每次拿到新的标注数据集先花半小时跑一遍标签格式校验和越界检查再进训练流程。从那以后我每次启动训练前都强制走一遍2.2节里的边界校验脚本数据本身的坑少了后面调参的玄学也就少了。希望帮到你。本文还有配套的精品资源点击获取
返回列表