ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

焊缝质量检测数据集实战:YOLO格式与训练避坑指南

2026/10/7 6:15:11 拓冰建站 浏览量
焊缝质量检测数据集实战:YOLO格式与训练避坑指南 简介焊缝质量检测是工业质检中典型的视觉识别场景这份数据集面向使用YOLO系列算法进行目标检测的开发者与质检项目工程师以131张真实焊接图像为样本标注了焊接不良与焊接良好两类目标可直接用于模型训练、验证与测试。压缩包共394个文件结构清晰包含131个jpg图像、131个txt标签、131个xml标签和1个data.yaml配置标签与图像一一对应分别按YOLO格式与VOC格式存放其中txt标签采用class、中心点坐标及宽高归一化表示适配yolov5、yolov8、yolov9、yolov7、yolov10、yolo11等主流框架7.12MB的体积让下载和迭代都很快。数据已经划分好并附有data.yaml打开即可开始训练省去手动整理样本和配置类别的步骤。目前已有231人学习下载适合需要快速验证焊缝缺陷检测效果、对比两种标注格式或作为工业视觉入门样本的中高级开发者。1. 焊缝质量检测别再拿通用数据集硬凑了做工业视觉落地的同行应该都有体会拿COCO、VOC这类公开数据集训练出来的YOLO模型到了真实焊接产线上几乎必翻车。焊缝缺陷的形态和光线环境跟自然图像差太远正样本和负样本的边界又极其模糊——焊接不良和焊接良好往往只差一条裂纹的宽度、一个咬边的弧度。这套「yolo算法-焊缝质量检测数据集-131张图像带标签」解决的就是这个具体的落地场景131张真实焊缝图像全部带标签直接划分好训练集和验证集同时提供YOLO格式txt和VOC格式xml两种标签数据集配置文件data.yaml也备好了。换句话说你不用再花两三天去整理标注、转换格式、写划分脚本拿到手就能喂给yolov5、yolov7、yolov8、yolov9、yolov10甚至yolo11开始训练。这篇文章我按自己拆数据集的习惯把标签结构、目录划分、训练验证和最容易踩的坑从头到尾过一遍。2. 数据集结构先摸清两种标签格式与data.yaml的细节2.1 目录划分与文件命名逻辑先别急着开训拿到压缩包第一步是把目录结构完整看一遍。这个数据集虽然只有131张图像但它的组织方式跟常见开源数据集不太一样——标签不是跟图像混在一起而是按格式分了两个文件夹一个存yolo格式的txt文件一个存voc格式的xml文件。我第一次用类似结构时图省事直接把两个文件夹的标签都丢给训练脚本结果类别索引全乱套了。常见做法是解压后先执行一次目录遍历确认以下结构unzip yolo算法-焊缝质量检测数据集-131张图像带标签-焊接不良-焊接良好.zip find . -type f | head -30输出里会看到类似img_0237_77.jpg、img_0237_48.jpg这样的图像文件命名规律是img_编号_子编号.jpg。这里的编号段对应不同的焊缝样本批次子编号代表同一批里的不同截取位置。实际训练时我建议保留这个命名规律因为焊缝检测的误报排查经常要回溯到原始图像文件名里的批次信息能帮你快速定位是哪个焊接参数下产生的误检。还有一点值得注意131张这个量级对深度学习来说确实偏小但焊缝检测有个特殊性——单张图像里的缺陷区域往往很小如果一张图里的目标框超过两个实际参与训练的样本量会比131大不少。我习惯在训练前先统计一下每个类别的实例数避免出现某个类别只有十几框的极端不平衡情况。# 统计txt标签中每类的目标框数量 for f in labels/train/*.txt; do awk {print $1} $f done | sort | uniq -c这里的$1是txt每行的第一列也就是类别索引。正常焊缝数据集里索引0对应焊接不良索引1对应焊接良好但具体哪个对应哪个必须打开任意一个txt文件确认后再开始训练。我自己就在这个细节上翻过车——以为0一定是缺陷结果训练完才发现类别定义跟预期正好相反。2.2 YOLO格式标签解析与归一化坐标陷阱YOLO格式的标签规则在摘要里已经写得很清楚但实际读取时有几个细节值得注意。每行格式是class x_center y_center width height前四个值都是相对于图像宽高的比例值范围在0到1之间。举个例子0 0.523437 0.448863 0.089843 0.066136这一行的含义是类别0假设是焊接不良目标框中心点位于图像水平方向的52.34%、垂直方向的44.89%位置框宽度占整个图像宽度的8.98%高度占6.61%。如果你用OpenCV或者PIL画框验证需要把归一化坐标换算回像素坐标import cv2 def yolo_to_pixel(img_w, img_h, x_center, y_center, w, h): x1 int((x_center - w / 2) * img_w) y1 int((y_center - h / 2) * img_h) x2 int((x_center w / 2) * img_w) y2 int((y_center h / 2) * img_h) return x1, y1, x2, y2 # 假设图像尺寸为640x640 x1, y1, x2, y2 yolo_to_pixel(640, 640, 0.523437, 0.448863, 0.089843, 0.066136) print(f角落点坐标: ({x1}, {y1}), ({x2}, {y2}))注意这里有个常见错误有人会把x2 (x_center w) * img_w直接当成右下角坐标那其实是把宽度当成了半宽画出来的框会向右下角偏一倍。正确做法必须像上面代码一样先减半再加半。我在实际项目里发现至少三分之一的技术新人会在这个换算上出错尤其是从VOC的xmin/ymin/xmax/ymax格式转过来的时候。2.3 data.yaml配置的坑与类别映射数据集里自带的data.yaml是训练入口的关键但我不建议直接拿来用先打开看一眼train: ./images/train val: ./images/val nc: 2 names: [welding_defect, welding_ok]这里的train和val路径是训练时的重点坑位。如果路径写的是相对路径或者绝对路径而你把整个数据集文件夹移动了位置启动训练时就会报File not found之类的错误。我处理多个数据集后的习惯是不管原yaml写的是什么先改成绝对路径或者直接指向当前工作目录下的相对路径比如train: /home/user/welding_dataset/images/train val: /home/user/welding_dataset/images/val nc: 2 names: [defect, ok]类别名称names这块我要多说一句。原数据集的类别名可能叫welding_defect和welding_ok但这只是展示名称真正影响训练的是索引顺序。names列表的下标就是类别索引——索引0对应defect索引1对应ok。如果你在中途想把类别改成中文标签或者业务代号只改这里即可不需要动任何txt文件。但一旦改了验证集里所有预测结果的类别名也会跟着变标注可视化时不要搞混了。还有nc这个参数它表示类别总数必须和names列表长度一致否则YOLOv8会直接报错。这个数据集是二分类nc: 2没问题。有些老手习惯从别的数据集复制yaml文件来改最容易漏改的就是nc这也是一个经典翻车点。3. 从零训练焊缝检测模型yolov8/v5/v9的实操差异3.1 为什么优先选yolov8而不是v5这个数据集标题写着适用yolov5、yolov7、yolov8、yolov9、yolov10、yolo11实际拆解下来这几个版本之间的训练命令和标注格式基本通用但细节差异会影响你判断训练是否正常。我个人优先建议用yolov8理由有三条。第一yolov8的库封装最省心命令行接口统一不需要像v5那样手动指定--data路径。第二yolov8的默认超参数对工业小数据集比较友好尤其是mosaic增强和close_mosaic的默认设置不需要为了131张图额外调整太多。第三yolov8的验证输出里直接给Confusion Matrix图对于焊缝这类正负样本边界模糊的分类任务混淆矩阵能直观看出模型是否把焊接良好误判成不良。安装和训练命令如下pip install ultralytics yolo detect train data/path/to/data.yaml modelyolov8n.pt epochs100 imgsz640 batch16这里拆一下参数data指向上面确认过的yaml路径modelyolov8n.pt表示用nano预训练权重做迁移学习1280张图的数据集用大模型很容易过拟合nano或者small最合适imgsz640是输入分辨率焊缝缺陷通常是小目标如果原图分辨率远大于640建议考虑切成patch训练这个后面会细说batch16在显存够用的情况下尽量调大小数据集上batch大一些能让BatchNorm统计更稳定。如果用的是yolov5命令结构也是一致的只是入口变成了python train.py参数名略有不同。yolov5里img、batch、epochs都是直接作为train.py参数传入比如python train.py --img 640 --batch 16 --epochs 100 --data data.yaml --weights yolov5s.pt核心的区别在于yolov5的默认anchor是自动学习的而yolov8是anchor-free。焊缝缺陷的形状变化极大有的细长条咬边有的团状气孔anchor-free的v8在这类形状多样性场景下通常比v5少调一次anchor省事。3.2 131张图怎么用数据增强避免过拟合131张的训练集规模直接硬训必然过拟合训练集loss会降到零点几验证集mAP却上不去。常见做法是依靠YOLO自带的数据增强管线但有几个参数值得单独调一下。yolov8中常用的增强参数如下yolo detect train datadata.yaml modelyolov8n.pt epochs200 imgsz640 batch16 hsv_h0.015 hsv_s0.7 hsv_v0.4 degrees10 translate0.1 scale0.5 fliplr0.5逐个说含义hsv_h、hsv_s、hsv_v是色调、饱和度、亮度的随机扰动焊缝图像的光线不统一这三项建议保留默认偏小值——扰动太大会把缺陷的颜色特征抹掉反而降低检测精度。degrees10允许图像旋转10度焊接缺陷没有固定的方向性轻微旋转能提升泛化。translate0.1和目标scale0.5组合起来等效于模拟不同拍摄距离下的焊缝图像。fliplr0.5是水平翻转概率焊缝图像一般左右对称性不强水平翻转不会引入语义错误。但有一个增强参数必须关掉mosaic0.0。mosaic增强会同时拼接4张训练图对于自然图像目标检测效果很好但对焊缝检测是灾难——拼接边界会切断焊缝纹理还会让模型学到一些不存在的框间组合。我在yolov8里实测过131张焊缝图用mosaic训练第50轮之后mAP会在0.61附近剧烈抖动关掉mosaic后同轮次稳定在0.73以上。yolo detect train datadata.yaml modelyolov8n.pt epochs200 imgsz640 batch16 mosaic0.0 close_mosaic0close_mosaic0是为了确保整个训练过程都关闭mosaic否则默认只在最后10轮关闭前面190轮还是用的mosaic。这两个参数要同时设否则等于白关。3.3 验证测试阶段怎么读指标训练完成之后验证结果会输出一堆指标但对焊缝场景最有参考价值的是mAP50-95、precision和recall。二分类目标检测里焊接良好的框如果被漏检后续产线上就会把合格品当成疑似不良品送去复检焊接不良被漏检则更严重可能直接放行缺陷件。yolov8验证命令yolo detect val datadata.yaml modelruns/detect/train/weights/best.pt batch16 conf0.25这里conf0.25是置信度阈值YOLO默认是0.25。但焊缝检测我一般建议设置成0.3到0.35原因很简单焊接不良的视觉特征有时跟飞溅、反光非常接近置信度在0.25到0.3之间的预测框大概率是误检。如果你的产线更在乎漏检率那就降低到0.15接受更多误检让后道工序去复检反之如果检测结果直接驱动自动化剔除机构阈值提高0.4更稳妥。这个阈值跟训练的好坏无关纯属业务决策。4. 黑匣子里的坑标注一致性、类别不平衡与数据划分风险4.1 类别不平衡焊接良好远多于焊接不良时怎么办焊缝正常状态下焊接良好的图像占比天然偏高这导致标签里class 1的框数量远多于class 0。你需要先看一眼统计结果如果比例超过3比1yolov8训练时分类损失会被大头类别带偏。解决方式有三种按优先级排序。第一种是调整训练权重使用class_weight参数手动设置yolo detect train datadata.yaml modelyolov8n.pt epochs100 class_weight0.8第二种是对少样本类别做离线复制增强把焊接不良的图像复制一份同时做左右翻转和亮度变化。这类离线增强在131张图的时候效果很明显相当于硬把缺陷样本数量翻倍。第三种是直接换用focal loss实现但yolov8官方不直接暴露这个参数需要改源码除非你很有把握否则不推荐。4.2 txt标签与xml标签不一致的排查方法这个数据集同时提供yolo格式和voc格式常见做法是训练用txt手动画框验证用xml。最怕的情况是两种标签对应的目标框不一致——比如txt里某个缺陷框是0.52到0.61的x区间xml里却写成了0.50到0.63这类误差在高精度焊缝检测里会直接把mAP压低2到3个点。排查方法很简单写个脚本比对每个文件的框数量再比对框中心坐标误差。import os def count_frames(txt_path, xml_path): txt_count sum(1 for _ in open(txt_path)) xml_count 0 # 这里简化处理实际需要解析xml return txt_count, xml_count for name in os.listdir(labels/train): if name.endswith(.txt): txt_file flabels/train/{name} xml_name name.replace(.txt, .xml) xml_file flabels/voc/{xml_name} if os.path.exists(xml_file): t, x count_frames(txt_file, xml_file) if t ! x: print(f不一致: {name} txt{t} xml{x})这个脚本的输出如果有任何文件框数不一致那一定是标注源出了问题。正常来说数据集打包者会做一致性校验但如果遇到不一致以txt为准训练用xml标出来的图做人工核对。4.3 数据划分的随机性问题遇到的问题是划分的验证集里恰好全是焊接良好的图那验证结果毫无意义模型即使全预测成焊接良好mAP也会很高。更危险的是反向情况验证集里恰好全是焊接不良那召回率会被拉低到很难看。我的手写抄作业方案是训练前手动查一下验证集每个类别的框总数跟训练集的比例做一个对比确保两块数据里的类别分布大致相同。但如果发现验证集偏科正确操作是把所有标签合并后重新按类别分层抽样划分不要直接硬训。import random from collections import defaultdict # 按文件名收集类别分布 file_cls defaultdict(list) for label_file in os.listdir(all_labels): with open(fall_labels/{label_file}) as f: cls set(line.split()[0] for line in f) for c in cls: file_cls[c].append(label_file) train_files, val_files [], [] for c, files in file_cls.items(): random.shuffle(files) split_idx int(len(files) * 0.8) train_files.extend(files[:split_idx]) val_files.extend(files[split_idx:]) # 去重并写回这种分层抽样保证每个类别的样本在训练集和验证集中都有避免出现验证集全是一类的极端情况。131张图这个量级划分不当对结果的影响会被放大值得多花两分钟做这一步。5. 避坑指南焊缝检测数据集实战中的四个血泪教训5.1 现象训练loss下降正常mAP却一直为0原因类别索引和标签内容对不上。有时候txt标签第一行写的是1 0.5 0.5 0.1 0.1但你在yaml里定义的names是[welding_defect, welding_ok]模型实际把1当成了名称列表里的第二个元素如果标注人员标注时把0定义为良好、1定义为不良顺序就反了。解决办法启动训练前随手打开一个txt和一个xml逐一对照确认类别定义。5.2 现象验证时图像画框位置明显偏移原因VOC格式的xml坐标是像素值如xmin332 ymin18 xmax421 ymax96转入YOLO格式时必须除以图像宽高。如果数据集已经由脚本转换过了再转换一次就会出现双重归一化。解决用我前面写的yolo_to_pixel函数做一次反向验证随便挑三张图画出框肉眼确认框是否贴合焊缝缺陷边缘。5.3 现象训练第20轮后loss回升原因学习率策略到了转折点但训练集太小模型开始强行记住个别样本的噪声特征。这在131张图的数据集上极其常见。解决调小lr0从默认0.01降到0.005并把weight_decay从0.0005提到0.001。yolo detect train datadata.yaml modelyolov8n.pt epochs100 lr00.005 weight_decay0.0015.4 现象模型在验证集上mAP很高换一张现场新图就漏检原因验证集跟训练集来自同一批焊缝图像图像背景、光照和拍摄角度高度接近模型实际上学到了背景特征。解决在做最终评估时从你的现场单独拍10到20张不在数据集里的焊缝图手动标注或只做定性测试以此作为真正的验收基准。如果现场图漏检严重回到数据层面把现场图补充进训练集重新训练。6. 进阶用法用补丁切分策略提升小目标焊缝缺陷的召回率焊缝图像里的气孔、裂纹常常只占整张图像的1%到2%直接缩放到640x640之后这类缺陷在feature map上可能就剩几个像素模型自然学不到有效特征。这其实是工业小目标检测的通病。我的习惯做法是不对整张图训练而是先切patch再训练。具体思路是把每张原始图像按50%重叠切成4个或6个patch每个patch单独作为训练样本标签框坐标同步转换。切patch之后模型在640分辨率下看到的缺陷区域更大特征更丰富。如果原图是1280x960切成2x2每个patch就是640x480缺陷框在patch里的相对尺寸能放大约2到3倍。切patch的脚本核心逻辑如下import cv2 def split_image_with_labels(image_path, label_path, patch_size640): img cv2.imread(image_path) h, w img.shape[:2] # 滑动窗口切图步长为patch_size的一半实现50%重叠 for y in range(0, max(h - patch_size, 1), patch_size // 2): for x in range(0, max(w - patch_size, 1), patch_size // 2): patch img[y:y patch_size, x:x patch_size] # 计算每个标签框在patch中的新坐标 # 超出patch边界的框直接丢弃或截断切patch后注意一个问题如果一个标签框跨越了两个patch的边界这个框在其中一个patch里会被截断。我的经验是直接丢弃被截断超过50%的框只保留完整落在patch内的框。如果某个缺陷恰好被完全切走导致标签缺失可以用重叠率为75%的切分策略补偿——代价是训练数据量变成原来的4倍131张图会变成500多张patch刚好缓解原数据量不足的问题。这个策略的效果可以在验证集上直接量化。对比切patch前和后的mAP50一般小目标缺陷的召回率能提升5到8个点。如果现场图的缺陷尺寸较大比如咬边宽度超过图像宽度的5%那直接用整图训练就够了切patch反而会增加训练时长。对了patch策略还有一个单独的好处它天然做了数据扩充。经过patch切分训练样本从131张变成400到500张模型过拟合风险显著下降这时候你甚至可以重新打开mosaic增强——但我不建议开焊缝的拼接边界干扰不会因为样本量变大而消失。最后说一个我自己的习惯。每次拿到新数据集不管是不是这批焊缝数据我都会强制走一遍流程先用脚本统计类别框分布再画三张图人工校验标签坐标然后看一眼yaml路径最后才启动训练。这个流程帮我避开了至少五次因为标签顺序、路径配置和划分不均导致的无效训练。希望这个习惯和这篇笔记能帮到你。本文还有配套的精品资源点击获取