简介面向目标检测与焊接质量检测场景这份YOLOV5目录格式的管道焊接缝缺陷检测数据集包含good、bad两个类别图片分辨率统一为800×800的RGB图像可直接用于YOLOV5系列模型训练。压缩包共1995个文件约93.27MB主体为996张jpg图片和997个txt标注文件另有1个可直接运行的py可视化脚本与1张png说明图数据集已划分训练集和验证集训练集908张图片及对应标签验证集206张图片及对应标签无需额外格式转换。目前已有196人学习下载。配合附带的可视化脚本随机传入一张图片即可自动绘制边界框并保存到当前目录可用于快速检查标注质量整份资源适合需要开展管道焊缝缺陷检测、目标检测入门练习或YOLOV5数据准备的开发者使用。1. 管道焊缝缺陷检测数据集为什么 2 类 YOLOv5 格式就够用拿到一批管道焊接缝的现场照片想做缺陷检测第一件事不是找模型而是先确认数据集长什么样。这里说的「目标检测数据集YOLOV5目录格式」并不是某个特定项目而是一种通用的数据组织方式图片放在 images 目录对应的标注文件按同名规则放在 labels 目录每行一个目标的类别和边界框坐标。管道焊缝的缺陷场景通常只关心两类目标——比如气孔和裂纹或者缺陷和正常焊道所以类别数不需要多2 类足够把模型训起来。这个格式最大的价值在于它和 YOLOv5 的 data.yaml 配置、训练脚本、评估脚本完全打通。你从现场采集的几百张焊缝照片只要按这个目录结构整理好就能直接用 YOLOv5 训练自己的数据集不需要改一行源码配合标注工具导出成 txt再写几行脚本划分训练集和验证集整个流程半天内能跑通第一版。这套方案适合手里有现场图像但还没建立标注规范的团队也适合刚接触目标检测的工程师快速验证缺陷检测的可行性。2. YOLOv5 目录格式拆解images 与 labels 的对应关系及标注规范2.1 两个核心目录的命名规则与对应关系YOLOv5 对数据集目录的要求非常固定。常见做法是在一个根目录下放 images 和 labels 两个子目录每个子目录再按训练集、验证集拆分。结构如下pipe_weld_dataset/ ├── images/ │ ├── train/ │ │ ├── weld_001.jpg │ │ ├── weld_002.jpg │ │ └── ... │ └── val/ │ ├── weld_010.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── weld_001.txt │ │ ├── weld_002.txt │ │ └── ... │ └── val/ │ ├── weld_010.txt │ └── ... └── data.yaml图片和标注文件靠「同名前缀」对应weld_001.jpg对应的标注文件必须是labels/train/weld_001.txt。YOLOv5 训练时通过图片路径去推导 label 路径规则是把 images 替换成 labels把图片扩展名替换成 .txt。所以只要保持 basename 完全一致路径层级可以灵活调整。每个 txt 文件里的内容格式是class_id x_center y_center width height比如一行0 0.532 0.447 0.214 0.132代表 class_id 为 0 的目标框。四个坐标值都是相对图片宽高的归一化比例取值范围 0~1。注意这里不是左上角和右下角坐标而是中心点坐标加宽高。初次转换标注时最容易在这摔倒后面会单独讲。2.2 类别定义与 data.yaml 配置2 类数据集在 data.yaml 里只需要指定两个路径和两个名字。常见做法是这样写path: pipe_weld_dataset # 数据集根目录 train: images/train # 训练图片目录 val: images/val # 验证图片目录 nc: 2 # 类别数量 names: [porosity, crack] # 类别名顺序必须和标注txt里的class_id一致names的顺序很关键它决定了 class_id 0 是气孔还是裂纹。一旦训练中途改了顺序之前所有标注文件里的 id 含义就全变了。我一般会在项目开始时先把类别名固定下来用中文名也可以但建议用英文避免编码问题。path可以用绝对路径也可以写相对路径相对路径是相对于执行训练命令的工作目录。还有一个容易忽略的细节如果检测目标只有「缺陷」和「正常焊道」那「正常焊道」这个类别意义不大——因为背景本身就是负样本单独标正常焊道反而会让模型困惑。2 类的更合理切分是气孔与裂纹或者表面缺陷与内部缺陷具体取决于你的焊缝工艺类型。实际做管道焊缝检测时气孔、夹渣、未熔合、裂纹是常见缺陷如果现场数据里只有两类出现频率高就只标这两类类别数少对收敛速度和稳定性都是好事。3. 标注到训练把现场焊缝照片变成可训练数据集的过程3.1 标注工具的选型与导出标注是数据集制作里最耗时的一步。YOLOv5 目录格式要求 txt 文件但标注工具原生导出的格式往往是 JSON 或 XML所以需要经历「标注 - 导出 - 转换」三个环节。常用标注工具里LabelImg 可以直接导出 YOLO 格式操作路径是画框后选择 YOLO 保存格式保存后在同目录生成同名 txt。但 LabelImg 维护较早遇到大图或视频帧序列时体验一般。X-AnyLabeling 是更现代的选择支持矩形框、多边形、自动标注辅助导出时选 YOLO 格式即可。无论用哪个工具最终产物必须是上面提到的五列 txt。如果手头已有 VOC 格式的 XML 标注转换脚本是绕不开的。下面这个脚本可以把单张图片的 XML 转成 YOLO txtimport xml.etree.ElementTree as ET import os def convert_voc_to_yolo(xml_path, out_path, class_list): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size).find(width).text) img_h int(root.find(size).find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_list: continue class_id class_list.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) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h # 边界裁剪防止归一化后越界 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) width min(width, 1.0) height min(height, 1.0) lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) # 使用示例class_list 必须和 data.yaml 里的 names 顺序一致 class_list [porosity, crack] convert_voc_to_yolo(weld_001.xml, weld_001.txt, class_list)脚本逻辑分三段解析 XML 拿到图片尺寸和目标框绝对坐标将绝对坐标换算成归一化中心点与宽高做一次边界裁剪防止越界。最后一步看着多余实际很有用——标注时手滑把框画到图片边缘外生成的坐标可能大于 1训练时会导致 loss 异常甚至程序报错。裁剪能把这类脏数据挡在训练之前。3.2 训练集与验证集的划分策略标注完所有图片后不能直接把全部数据丢进训练。YOLOv5 训练脚本会自动读取 images/train 和 images/val 两个目录所以要提前按比例分配图片。常见做法是 8:2 或 9:1管道焊缝这种缺陷样本分布不均匀的场景我更推荐按缺陷类别做分层抽样而不是简单随机划分。import random import shutil import os random.seed(42) src_images all_images/ src_labels all_labels/ train_ratio 0.8 images [f for f in os.listdir(src_images) if f.endswith(.jpg)] random.shuffle(images) train_files images[:int(len(images) * train_ratio)] val_files images[int(len(images) * train_ratio):] for split, file_list in [(train, train_files), (val, val_files)]: os.makedirs(fdataset/images/{split}, exist_okTrue) os.makedirs(fdataset/labels/{split}, exist_okTrue) for img in file_list: base os.path.splitext(img)[0] shutil.copy(f{src_images}/{img}, fdataset/images/{split}/{img}) label_path f{src_labels}/{base}.txt if os.path.exists(label_path): shutil.copy(label_path, fdataset/labels/{split}/{base}.txt)这段脚本值得一提的是随机种子固定保证每次运行划分结果一致方便复现实验。另一个点是把 txt 对应关系也一起拷贝避免图片过去了标注没跟上。划分完可以顺手数一下两个 split 的文件数量比确认没有极端失衡。3.3 训练命令与超参数设置YOLOv5 训练入口是 train.py官方仓库里直接跑下面的命令即可python train.py \ --data pipe_weld_dataset/data.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --imgsz 640 \ --device 0 \ --name weld_exp1几个参数按实际情况调batch-size看显存8G 显存跑 yolov5s 用 16 通常没问题用 10G 以上显卡可以尝试 32imgsz默认 640如果焊缝缺陷是小目标比如气孔直径只有十几个像素建议先用 640 跑通流程之后再用 1280 做对比实验weights用官方预训练权重做迁移学习比随机初始化收敛快很多对几百张的小数据集尤其重要。训练过程中重点看两个日志指标box_loss 和 cls_loss。如果 cls_loss 在某个 epoch 后不再下降说明类别区分度不够可能原因包括标注框太粗糙或两类样本数量悬殊。训练结束后会生成 runs/train/weld_exp1 目录里面的 weights/best.pt 和 weights/last.pt 分别是最优权重和最后一轮权重后续推理用 best.pt。4. 训练与评估阶段的避坑常见问题与排查记录4.1 loss 直接变成 nan坐标越界和空标注文件现象训练刚跑几个 iterationbox_loss 输出 nan程序随后崩掉。原因最常见的是标注 txt 里出现负数坐标或者大于 1 的坐标值YOLOv5 在计算框损失时遇到非法值直接溢出。另一种情况是某些 txt 文件是空的即图片存在但没有任何标注这类图片在 mosaic 增强时会让标签矩阵出现空行触发 nan。解决在训练前写一个检查脚本逐行读取所有 label 文件过滤掉空文件和越界行。更简单的方法是直接用下面这个命令扫一遍find labels -name *.txt -size 0 -delete这条命令把 0 字节的标注文件删掉但图片还在模型会把它们当纯背景样本处理。如果空标注文件对应的图片本来就有缺陷那说明是标注遗漏需要补标如果没有缺陷删掉 label 文件反而对了。4.2 mAP0.5 很高但实际检测漏检验证集图片与训练集重叠现象训练结束打印出的 mAP0.5 到 0.95 都很漂亮但把模型部署到现场采集的新图片上漏检率明显偏高。原因训练前划分数据集时同一根管道不同角度的照片可能被同时分进了训练集和验证集。这些图片背景高度相似模型在验证集上的表现其实是「背答案」不是真正的泛化。我遇到过最夸张的一次是 mAP0.5 达到 0.97换了一台管口的照片直接掉到 0.4。解决重新划分数据集时按「管道编号」作为分组单位而不是按单张图片。保证同一根管道的所有图片都进同一个 split。操作上先对文件名做前缀分组再按组随机分配。另外现场验证时至少留 20 张完全没参与训练的照片做 final test这组数据不进任何训练逻辑。4.3 小目标气孔完全检不出输入分辨率与锚框问题现象模型能检测裂纹这类长条缺陷但气孔直径十几个像素几乎全漏。原因640 输入下小目标在特征图上的尺寸只有几个像素YOLOv5s 的 P3 特征图对这类目标表达能力不足。而且气孔样本量少锚框尺寸分布偏向了裂纹这类大目标。解决先统计标注框的宽高分布。写一个小脚本读取所有 label 文件统计 width 和 height 的中位数与分位数如果大量框的宽度小于 0.05即小于 32 像素说明小目标占比高。这时有两个改动方向第一把 imgsz 提高到 1280相当于让小目标在特征图上的像素翻倍第二关闭自动锚框的默认行为在 data.yaml 里手动传入自适应锚框参数YOLOv5 训练时会根据你的标注数据重新聚类锚框只要不是用--noautoanchor显式关闭默认会重新计算。多数场景下只调 imgsz 就能改善代价是训练和推理速度下降显存占用翻倍。4.4 训练过程中验证集 loss 震荡剧烈学习率与 mosaic 关闭时机现象前 50 个 epoch 验证集 loss 稳定下降50 之后开始大幅波动但训练集 loss 还在降。原因YOLOv5 默认训练轮次为 300如果只设 100 轮cosine LR 调度器在训练后期学习率降得太快加上 mosaic 增强在最后 10 轮才关闭两个因素叠加导致验证集表现不稳定。解决显式设置--cos关闭余弦退火改用线性衰减同时把 mosaic 关闭轮次提前可以在训练到总轮次的 70% 时手动停掉增强。具体做法是改 train.py 里的close_mosaic参数YOLOv5 新版支持在命令行传--close-mosaic 10表示最后 10 轮关闭 mosaic。如果数据量只有几百张建议总轮次设 150 而不是 100给学习率衰减留足空间。4.5 类别严重不均衡气孔 2000 个框裂纹只有 80 个框现象训练出的模型几乎只输出气孔裂纹偶尔能测到但置信度很低。原因目标检测的类别不均衡不像分类任务那么容易通过 class weight 解决。YOLOv5 的 cls loss 默认对每个类别一视同仁少样本类别在正负样本对撞中容易被淹没。解决两个手段配合。第一样本少的类别做离线复制增强用旋转、亮度抖动、加噪声生成额外样本注意别把裂纹的形态学特征破坏掉第二把少样本类别的图片重复多份放进训练集让每个 epoch 里这个类别出现次数增多。数据层面比改 loss 更可控因为改 loss 权重容易让模型对多类别的误检率上升。5. 提升焊缝缺陷检出率的实用技巧数据增强与后处理调优数据增强配置藏在 YOLOv5 的超参数文件 hyp.scratch.yaml 里。小数据集上我一般调整三个值hsv_h、hsv_s和hsv_v控制色相、饱和度和明度的随机扰动幅度。焊缝图像在不同光照条件下色温差异大把hsv_v从默认 0.4 调到 0.5能明显增强模型对明暗变化的鲁棒性。degrees和translate按需小幅度放开旋转超过 30 度会让焊缝缺陷形态失真不建议拉太高。推理阶段的后处理同样值得调。YOLOv5 的 detect.py 支持--conf-thres和--iou-thres两个参数。管道焊缝场景我习惯把置信度阈值降到 0.15~0.2因为漏检缺陷的代价远高于误检多框出来几个可疑区域让质检员人工确认比直接漏掉更安全。NMS 的 IoU 阈值默认 0.45如果现场缺陷密集、互相靠近把 IoU 阈值调到 0.3 可以减少重叠框的合并损失。同时开启--agnostic-nms让不同类别的框之间也做抑制防止气孔旁边紧贴裂纹时多出重复框。最后分享一个我自己的处理习惯训练结束后别急着部署先用 best.pt 跑一遍验证集的全部图片把预测结果可视化保存下来逐张看漏检和误检的分布。漏检集中在哪种缺陷、哪种光照条件比对后回到数据处理环节补样本而不是盲目堆训练轮次。这套「数据 - 训练 - 后处理 - 人工复核」的闭环是我做管道焊缝检测项目时最稳定的流程。希望帮到你。本文还有配套的精品资源点击获取