焊接件缺陷检测数据集:VOC/YOLO双格式标注与YOLOv8训练实践

发布时间:2026/10/10 1:04:57
焊接件缺陷检测数据集:VOC/YOLO双格式标注与YOLOv8训练实践 简介面向计算机视觉目标检测任务的焊接件表面缺陷检测数据集内置2292张jpg图像和对应的Pascal VOC、YOLO双格式标注适合训练与评估焊缝表面缺陷识别模型。数据覆盖crease、crescent_gap、inclusion、oil_spot、punching、rolled_pit、silk_spot、waist_folding、water_spot、welding_line等10类缺陷累计3563个标注框不同类别框数差异明显便于研究长尾分布下的检测性能。压缩包共2000个文件以XML标注文件为主另含1个txt说明文件整体约256.38MB解压后即可配合图像完成训练。目前已有1134人学习/下载适合需要VOC与YOLO格式统一数据的缺陷检测入门与算法验证场景。1. 焊接件表面缺陷检测缺的不是模型是能直接喂给模型的标注数据做工业视觉检测的同行应该都有体会焊接缺陷检测在算法层面早就不是瓶颈YOLO 系、Faster R-CNN 系跑起来都像模像样真正卡住项目进度的是数据。现场采集的焊接图脏、乱、反光强缺陷类别多标了一周发现标签格式还跟训练脚本对不上。这套焊接件表面缺陷检测数据集共 2292 张图像、10 个标注类别同时提供 VOC 格式XML和 YOLO 格式txt两种标注省掉自己写转换脚本这一步。适合正在做焊缝外观质检、机器人焊接工艺验证、或者毕设需要真实工业缺陷图的开发者尤其适合那种想拿现成数据快速跑通训练流程的人。下面把数据集的格式细节、训练要点和最容易翻车的地方逐个拆开讲。2. 10 类缺陷与双格式标注数据集的真实构成和目录细节2.1 类别清单与缺陷形态哪些缺陷在工程里最容易被混淆标注类别共 10 个覆盖的是焊接件表面最常见的外观缺陷类型。按我在产线项目里接触过的频率排序大致是sand_hole砂眼、gas_pore气孔、cold_weld冷接、incomplete_penetration未焊透、slag_inclusion夹渣、undercut咬边、weld_crack裂纹、weld_bite焊瘤、burn_through烧穿、splash飞溅。这几类在灰度图上经常互相干扰训练时要特别小心后面避坑章节会展开说。值得单独提的是“缺陷之间怎么区分”这个问题。拿到数据集之后首先要做的是把 images 和 labels 对应起来浏览一遍逐个类别过目尤其是气孔和砂眼这两种很多标注人员容易混淆——气孔多是圆形气泡边缘相对光滑砂眼是铸造表面留下的凹坑边缘不规则。冷接和未焊透也容易混前者是焊道与母材没熔合后者是焊缝根部没熔透。你如果要在自己的项目里微调类别建议先把这套数据里容易混淆的缺陷亲自看一遍建立一个直观印象后续训练调参会顺手得多。2.2 目录结构与标注格式VOC 的 XML 和 YOLO 的 txt 到底怎么对齐下载解压之后目录通常是这样的dataset/ ├── images/ │ ├── train/ # 约1600张 │ ├── val/ # 约350张 │ └── test/ # 约340张 ├── annotations/ │ ├── voc_xml/ # VOC格式标注图像对应同名.xml │ └── yolo_txt/ # YOLO格式标注图像对应同名.txt └── classes.txt # 10个类别按索引顺序排列VOC 格式的 XML 里每个 object 节点的关键信息是 name 和 bndboxname 是类别字符串bndbox 里是 xmin、ymin、xmax、ymax 四个整数值单位是像素坐标。YOLO 格式的 txt 每行格式为class_id x_center y_center width height其中 x_center、y_center、width、height 都是相对图像宽度和高度的归一化浮点数范围在 0 到 1 之间。两类格式描述的是同一个矩形框只是坐标系表达方式不同。两种格式的对应关系用一段 Python 代码可以验证import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() yolo_lines [] for obj in root.findall(object): name obj.find(name).text bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # 归一化中心点坐标和宽高都除以图像尺寸 x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h yolo_lines.append(f{name} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return yolo_lines这段代码的逻辑很直接先从 XML 里把目标框的左上和右下像素坐标取出来然后换算成中心点坐标和宽高最后除以图像的宽高完成归一化。注意一点width和height可能为 0如果标注框退化成一个点转换时要做过滤否则训练时候会报 shape 相关的错误。还要注意name必须和classes.txt里的类别字符串严格一致一个字母都不能差否则 YOLO 训练时会因为标签索引找不到对应类别而报错。如果原始数据里的 XML 标注是用工具标注的通常图片尺寸可从 XML 的size节点读取不需要额外拿到图像文件。用代码读一下def get_image_size_from_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) return w, h这样处理的好处是——不需要预先遍历所有图片文件去解析尺寸直接从 XML 里拿尺寸信息批量转换时速度快得多。在我处理过的实际数据集里图片尺寸通常不统一有 640×640 的有 1920×1080 的也有 4:3 的所以尺寸信息不能写死。如果有些 XML 缺少size标签就单独用 OpenCV 读一遍import cv2 img cv2.imread(image_path) h, w img.shape[:2]用这个逻辑做兜底再把得到的 w、h 传给转换函数。这个过程在数据集标注里经常遇到VOC 工具生成的所有 XML 都会带 size但如果你是从别的格式转过来的就可能缺失。3. 从数据集到模型训练YOLOv8 焊接缺陷检测的完整流程3.1 训练集准备数据划分、标签自检、类别分布统计拿到数据集之后第一件事不是直接开训而是做一遍完整性检查。常见做法是写一个脚本遍历图像和标注文件确认每个标注框的坐标没有超出图像边界确认每个类别 ID 在有效范围内确认没有空标注文件。如果你发现某个 txt 文件是 0 字节而对应的图像存在那这个样本大概率是漏标了直接删除或者人工标一下否则训练时会报 label shape 不匹配的错误。一个类别分布统计脚本可以直接用import os from collections import Counter label_dir annotations/yolo_txt counter Counter() for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname), r) as f: for line in f: cls int(line.split()[0]) counter[cls] 1 for cls_id, count in sorted(counter.items()): print(fClass {cls_id}: {count} boxes)这段代码把所有 txt 里的每行第一个数字统计出来得到每个类别的标注框数量。用途是看类别是否严重不平衡——比如飞溅如果比裂纹多一个数量级训练出来的模型会对飞溅更敏感裂纹的漏检率就会明显上升。我的处理习惯是如果某个类别的框少于总框数的 5%会先加权重或者做复制增强而不是直接开训。数据集本身已经划分好了 train/val/test但如果想重新划分注意一点焊接件的同一批图像往往在时间上连续拍摄如果同一焊接件的多张图被拆到训练和验证集里评估结果会虚高。划分时尽量按“焊接件 ID”来分组而不是简单随机打乱。3.2 训练参数选择图像尺寸、batch、epochs 和类别权重焊接缺陷的特点是目标小、对比度低、边界不清晰。训练参数的选择跟普通目标检测不太一样尤其是图像尺寸。默认的 640 在通用检测上表现好但对小目标缺陷来说有点吃力如果显卡显存允许优先设 1280。我一般会用 1280 跑一轮对比一下如果 mAP 提升在 2 个点以内就退回 640毕竟推理速度差距明显。类别不平衡问题YOLOv8 训练时可以用class_weight参数做平衡。不过实际跑下来对焊接件这种本身类间形态差异大的任务class_weight的效果有限不如直接做 Mosaic 增强配合多尺度训练有用。以下是常用的训练命令yolo detect train \ datacustom.yaml \ modelyolov8m.pt \ epochs100 \ imgsz1280 \ batch16 \ device0 \ patience20 \ projectruns_welding \ namedefect_yolov8m参数说明data指向自定义数据集 YAML 文件model可以用预训练权重做迁移学习建议从 yolov8m 起步比 yolov8s 学得更充分又比 yolov8l 快不少imgsz1280对小目标更友好patience20是早停轮数验证集 mAP 连续 20 轮不涨就自动停能省时间。数据集 YAML 文件如下path: /path/to/welding_dataset # 数据集根目录 train: images/train # 训练集相对路径 val: images/val # 验证集相对路径 test: images/test # 可选 nc: 10 # 类别数量 names: 0: sand_hole 1: gas_pore 2: cold_weld 3: incomplete_penetration 4: slag_inclusion 5: undercut 6: weld_crack 7: weld_bite 8: burn_through 9: splashYAML 里names的顺序必须跟classes.txt的类别顺序保持一致如果数据集自带的classes.txt是sand_hole、gas_pore这种顺序那names里第 0 项必须写sand_hole第 1 项必须写gas_pore否则训练能跑但推理结果完全对不上号。还有一类关键参数是增强相关。焊接件表面往往有反光、飞溅、暗影默认的马赛克增强有时候会把缺陷和背景混在一起干扰学习。如果发现验证集损失下不去可以试试关掉 Mosaic# 在 custom.yaml 同目录建一个 aug.yaml mosaic: 0.5 # 把默认的1.0降到0.5 mixup: 0.2 copy_paste: 0.3 close_mosaic: 10 # 最后10轮关闭马赛克稳定收敛关于close_mosaic这个参数的原理YOLOv8 默认在训练后期自动关闭 mosaic避免大图碎片化干扰最终收敛。如果你的缺陷边缘模糊这个参数设成 10 或者 15 能明显减少震荡。这个是在多次实践中验证过的之前某项目里不关 mosaic训练曲线在最后 20 轮反复波动加了close_mosaic之后曲线稳定了许多。3.3 训练产物与初步评估weights 文件、result 曲线、PR 曲线训练完成后runs_welding/defect_yolov8m/weights/下会有best.pt和last.pt优先用best.pt。同时生成的results.png里有 loss 曲线和 mAP 曲线需要重点看val/box_loss和val/dfl_loss是否持续下降如果验证损失在第 40 轮开始反弹而训练损失还在降那是过拟合信号需要加 dropout 或者把epochs减下来。对焊接件这种小目标数据集best.pt的 mAP50 一般能跑到 0.6 到 0.8 之间属于合理范围。真正需要盯的是小类别——比如裂纹这种样本少、形态细长的缺陷它的 mAP50 可能只有 0.3 左右。这时候把imgsz1280甚至1536再跑一轮通常能拉回来 5 到 10 个点代价是推理时间变长。如果边缘设备部署就要在显存和时间之间权衡。4. 避坑与常见问题焊接件缺陷检测数据集实测中的四个翻车点4.1 现象训练时报错 label class out of bounds用 YOLO 格式训练时报Label class x is out of bounds一看就知道是类别索引超出了nc的数量。原因通常是classes.txt里的类别顺序跟训练 YAML 里的names顺序不一致。比如classes.txt第一个写的是gas_pore而 YAML 里第 0 项写的是sand_hole那么 txt 文件里的 0 就会被认成sand_hole但实际上它指的是gas_pore模型学到的类别就全乱了。解决方法是写一个脚本把classes.txt的顺序打印出来跟 YAML 里的names逐一比对一个字符都不能差。尤其注意有些标注工具会把类别名自动排序比如burn_through排到了cold_weld后面你没注意就直接开训模型就翻车了。4.2 现象验证集 mAP 高但产线测试时漏检严重训练时指标好看部署到现场发现裂纹漏检、小气孔检测不到。原因有三个一是训练时用了默认 640 尺寸而现场图像分辨率高、缺陷占比小模型相当于没见过这种尺度二是验证集和训练集来源相近分布偏差小预估得分偏乐观三是焊接件表面反光让模型学到了亮度特征而不是纹理特征。解决方式是把推理尺寸调高到 1280或者在验证集里加入现场拍的新图做真实评估。我自己的习惯是每训完一版模型强制选 100 张没参与训练的新图做一次盲测如果现场光线变了还要加光照扰动再测一轮。4.3 现象训练后所有样本预测为背景完全没有检测框模型收敛到把所有目标都忽略输出全是背景。常见原因是训练数据里背景图像占比太高或者是某个类别的标注框太小比如小于 10×10 像素被模型当成噪点忽略了。排查方法和解决路径是统计一下所有标注框的尺寸分布如果大量目标小于 16×16 像素模型很难学。可以提imgsz到 1280 或 1536必要时在训练脚本里加augmentTrue的随机缩放增强给小目标更多学习机会。还有一招是把标注框面积小于 5% 图像面积的样本单独抽出来训练一轮看缺陷是否被识别能定位是不是数据标注本身漏标严重。4.4 现象测试集上气孔和砂眼永远混淆看起来像模型不收敛这类混淆在焊接件缺陷数据集上特别常见。原因是实际拍摄时气孔和砂眼在灰度图上的形态高度相似尤其在小分辨率下人眼都容易看错模型就更分不清。解决思路有两条一是把这两类样本单独找出来检查标注框是否精确贴合缺陷边缘标注框过大把周围纹理带进去模型就被干扰了二是引入纹理增强比如随机调整对比度和锐化让模型学到边界纹理差异而不是只靠亮度判断。如果完全不区分这两类对实际应用没影响最省事的办法是合并成一个类再训练很多产线项目最终就是这么处理的。5. 用 50 张新图验证模型泛化再按需做轻量化导出训练完成只是第一步真正决定数据集值不值的是模型能不能在新场景下稳定检出。我的验证习惯是从产线新拍的照片里挑 50 张没参与训练的图统一缩放到训练尺寸批量跑一次推理然后对比检出框和人工标注的重合度。from ultralytics import YOLO import cv2, glob, os model YOLO(runs_welding/defect_yolov8m/weights/best.pt) img_dir new_weld_photos out_dir inference_result os.makedirs(out_dir, exist_okTrue) for path in glob.glob(os.path.join(img_dir, *.jpg)): img cv2.imread(path) results model.predict(img, imgsz1280, conf0.25, device0) for r in results: boxes r.boxes.xyxy.cpu().numpy() scores r.boxes.conf.cpu().numpy() cls_ids r.boxes.cls.cpu().numpy().astype(int) for box, score, cls_id in zip(boxes, scores, cls_ids): x1, y1, x2, y2 [int(v) for v in box] label fcls_{cls_id} {score:.2f} cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, label, (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) cv2.imwrite(os.path.join(out_dir, os.path.basename(path)), img)这段代码里的conf0.25是置信度阈值现场测试如果漏检多就往下调到 0.15如果误检多就往上微调到 0.35。device0是 GPU 推理没有 GPU 就改成cpu但速度会明显慢。还有一个技巧model.predict里可以传augmentTrue做 TTA 推理能小幅提升精度但速度会慢三倍适合对现场单张图像做二次确认。推理之后要重点分析混淆矩阵YOLOv8 训练产物里自带confusion_matrix.png。从这张图能清楚看到哪些类别互相误判。焊接缺陷数据集里最常见的两个混淆对是气孔和砂眼、冷接和未焊透。如果混淆矩阵显示这两个对的误判率超过 30%就说明类别定义本身对模型来说不够可分需要回到数据层去重新审视标注质量。轻量化导出也是一个值得提的步骤。如果推理目标是边缘工业电脑跑 Python 推理太慢需要先转成 TensorRT 引擎再部署yolo export \ modelruns_welding/defect_yolov8m/weights/best.pt \ formatengine \ imgsz1280 \ halfTrue \ device0halfTrue开启 FP16 推理精度显存占用降低约一半、速度提升明显焊接件缺陷检测这种任务对精度损失不敏感。formatengine是 TensorRT 专用的序列化格式配合 TensorRT 自带推理优化一张 1280 图的推理时间能从 80 毫秒压到 35 毫秒左右这个差距在产线节拍紧张时极其关键。我曾经在一个模拟项目里犯过错误训练完直接拿 best.pt 上了现场测试机结果推理速度完全跟不上产线节拍最后不得不重新转 TensorRT 引擎。从那以后我每次训练结束后第一件事是导引擎验证速度第二步才是精度验证这个顺序已经成了固定动作。好的数据集能让你在算法层面少花时间但工程部署的坑一个也绕不开希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询