2026/10/11 0:43:44

焊接缺陷检测数据集6类2684张YOLO+VOC双格式使用指南

焊接缺陷检测数据集6类2684张YOLO+VOC双格式使用指南 简介这份资源面向从事焊接质量检测、工业视觉与目标检测算法开发的工程师及学生提供一套可直接用于模型训练的焊接缺陷数据集帮助解决缺陷样本采集难、标注成本高的问题。压缩包共约2000个文件以1999个xml标注文件和1个说明txt为主整体约48.35MB图片、VOC格式xml与YOLO格式txt一一对应方便在两种主流框架间切换使用。数据集覆盖烧穿、污染、良好焊缝、未完全融合、渗透不足、错位共6类目标总计2685个矩形标注框各类别框数分布较为均衡图片分辨率清晰且未做数据增强适合直接用于训练与验证。目前已有314人学习下载读者可借此快速搭建焊接缺陷检测基线模型省去从零标注的时间并对照VOC与YOLO双格式理解标注转换流程为后续调参与部署提供可靠数据基础。1. 焊接缺陷检测数据集6类2684张的YOLOVOC双格式到底怎么用拿到一个标注好的焊接缺陷数据集最怕的不是数据量不够而是格式对不上、类别对不齐、训练时才发现标注有问题。标题里这个「目标检测焊接缺陷检测数据集6类2684张YOLOVOC格式.zip」核心价值就在于它同时提供了YOLO和VOC两套标注格式覆盖6类焊接缺陷总量2684张。这意味着你不需要自己从零标注也不用写格式转换脚本直接就能接入YOLOv5/v8或Faster R-CNN这类主流框架。适合谁做工业质检的算法工程师、想快速验证焊接缺陷检测方案的学生、以及需要baseline对比的研究者。但数据集拿到手只是第一步真正决定模型能不能落地的是类别定义是否清晰、标注框是否贴合、训练参数是否匹配。下面按「先搞清楚数据长什么样再跑通训练最后避开那些让人返工的坑」这条线展开。2. 拆开压缩包先看什么6类缺陷的目录结构与标注质量核查2.1 VOC与YOLO双格式的目录长什么样一个规范的焊接缺陷数据集解压后通常能看到两套并行的目录结构。VOC格式走的是AnnotationsJPEGImagesImageSets三件套YOLO格式则是imageslabels加一个data.yaml。先别急着训练用几条命令把结构摸清楚。# 查看解压后的顶层目录 unzip 焊接缺陷数据集.zip -d weld_defect cd weld_defect find . -maxdepth 2 -type d | sort # 统计图片数量和标注文件数量是否一致 find . -name *.jpg -o -name *.png | wc -l find . -name *.xml | wc -l find . -name *.txt -path */labels/* | wc -l逻辑说明第一条命令解压并进入目录find列出两层内的所有子目录快速判断是VOC为主还是YOLO为主。第二条统计图片总数第三条统计VOC的XML标注数第四条统计YOLO的txt标注数。正常情况下图片数、XML数、txt数三者应该一致都是2684。如果txt数量明显偏少说明部分图片没有对应的YOLO标注需要检查转换是否完整。参数说明-maxdepth 2控制目录深度避免输出太乱-path */labels/*限定只统计labels目录下的txt防止把其他txt文件算进来。如果发现数量对不上先别改数据去查ImageSets/Main里的train/val划分文件看看是不是划分时漏了。2.2 6类缺陷的类别名与样本分布怎么查类别不均衡是焊接缺陷检测里最常见的翻车点。2684张分6类平均每类447张但实际分布往往差很多——气孔、裂纹可能占大头未熔合、咬边可能只有几十张。用一段Python脚本把分布拉出来。import os import xml.etree.ElementTree as ET from collections import Counter # 指向VOC格式的Annotations目录 anno_dir weld_defect/VOC/Annotations counter Counter() for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(anno_dir, xml_file)) root tree.getroot() for obj in root.findall(object): name obj.find(name).text.strip() counter[name] 1 # 打印每类标注框数量按从多到少排序 for cls_name, cnt in counter.most_common(): print(f{cls_name}: {cnt}) print(f总标注框数: {sum(counter.values())})逻辑说明遍历Annotations下所有XML用ElementTree解析找到每个object下的name字段累加计数。输出按数量降序排列一眼就能看出哪类多哪类少。总标注框数可能大于2684因为一张图可能有多个缺陷。参数说明name.text.strip()去掉前后空格防止类别名带空格导致后续训练时类别对不上。如果发现某类少于100个框训练时就要考虑过采样或focal loss。类别名要和data.yaml里的names列表逐字一致大小写、下划线都不能差。2.3 标注框质量的三步快速核查标注框画得歪、框太大或太小直接拉低mAP。不用逐张看抽检三步就能判断质量。第一步随机抽20张图用OpenCV把VOC的XML框画出来肉眼看是否贴合缺陷边缘。第二步统计所有框的宽高比如果某类框的宽高比方差极大说明标注标准不统一。第三步检查是否有宽或高为0的无效框。import xml.etree.ElementTree as ET import os anno_dir weld_defect/VOC/Annotations invalid [] aspect_ratios [] for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue root ET.parse(os.path.join(anno_dir, xml_file)).getroot() for obj in root.findall(object): bbox obj.find(bndbox) w float(bbox.find(xmax).text) - float(bbox.find(xmin).text) h float(bbox.find(ymax).text) - float(bbox.find(ymin).text) if w 1 or h 1: invalid.append((xml_file, obj.find(name).text)) else: aspect_ratios.append(w / h) print(f无效框数量: {len(invalid)}) print(f宽高比范围: {min(aspect_ratios):.2f} ~ {max(aspect_ratios):.2f})逻辑说明宽或高小于等于1像素的框基本是标注失误直接列出来。宽高比范围能反映标注习惯如果从0.1到10都有说明有的框是细长条、有的是方块需要确认是否符合缺陷的真实形态。参数说明阈值设为1像素是保守做法实际可以放宽到2像素。如果无效框超过10个建议回到标注工具里修正而不是在训练脚本里过滤——过滤会导致图片和标注不匹配。3. 从VOC转到YOLO再训练格式转换与YOLOv8跑通全流程3.1 VOC转YOLO的转换脚本与四个边界坑虽然数据集号称双格式但实际拿到的YOLO标注有时是半成品或者你想统一用YOLO格式训练。自己写一遍转换脚本比盲目信任现成文件更可靠。VOC的坐标是绝对像素值(xmin, ymin, xmax, ymax)YOLO要的是归一化中心点(x_center, y_center, w, h)且都除以图片宽高。import os import xml.etree.ElementTree as ET from PIL import Image voc_anno_dir weld_defect/VOC/Annotations voc_img_dir weld_defect/VOC/JPEGImages yolo_label_dir weld_defect/YOLO/labels os.makedirs(yolo_label_dir, exist_okTrue) # 类别名到索引的映射必须与data.yaml一致 classes [气孔, 裂纹, 未熔合, 咬边, 焊瘤, 夹渣] class_to_id {name: i for i, name in enumerate(classes)} for xml_file in os.listdir(voc_anno_dir): if not xml_file.endswith(.xml): continue xml_path os.path.join(voc_anno_dir, xml_file) tree ET.parse(xml_path) root tree.getroot() # 用图片实际尺寸做归一化不要用XML里的size img_name root.find(filename).text img_path os.path.join(voc_img_dir, img_name) img_w, img_h Image.open(img_path).size lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in class_to_id: continue cls_id class_to_id[cls_name] 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) # 边界裁剪防止坐标超出图片范围 xmin max(0, min(xmin, img_w - 1)) xmax max(0, min(xmax, img_w - 1)) ymin max(0, min(ymin, img_h - 1)) ymax max(0, min(ymax, img_h - 1)) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h if w 0 or h 0: continue lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) txt_name os.path.splitext(xml_file)[0] .txt with open(os.path.join(yolo_label_dir, txt_name), w) as f: f.write(\n.join(lines))逻辑说明先建立类别名到索引的映射遍历XML对每个object取类别和坐标。用PIL读取图片实际宽高做归一化而不是用XML里可能不准的size字段。坐标先裁剪到图片范围内再算中心点和宽高。最后写入同名txt。参数说明classes列表的顺序决定了类别索引必须和训练时的data.yaml完全一致。:.6f保留6位小数YOLO默认精度够用。四个边界坑分别是XML的size和实际图片尺寸不一致、坐标超出图片边界、类别名有空格或大小写差异、宽高算出来为0。转换完用wc -l对比txt数量和图片数量再用head抽查几个txt内容。3.2 data.yaml的写法与YOLOv8训练命令YOLO格式准备好后写一个data.yaml指向图片和标注目录。YOLOv8的目录结构要求images/train、images/val、labels/train、labels/val分开。# data.yaml path: /home/user/weld_defect/YOLO train: images/train val: images/val nc: 6 names: 0: 气孔 1: 裂纹 2: 未熔合 3: 咬边 4: 焊瘤 5: 夹渣逻辑说明path是数据集根目录train和val是相对路径。nc是类别数names是索引到类别名的映射。YOLOv8会自动根据train路径找对应的labels目录前提是目录名从images换成labels后路径存在。参数说明如果图片和标注不在同一级可以用绝对路径。names的索引必须从0开始连续不能跳号。写完后用python -c import yaml; print(yaml.safe_load(open(data.yaml)))验证YAML语法。训练命令用YOLOv8的CLI先装环境再跑。pip install ultralytics yolo detect train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16 device0逻辑说明yolov8n.pt是nano模型适合快速验证。epochs100对2684张图偏多可以先跑50轮看收敛。imgsz640是默认输入尺寸焊接缺陷目标通常不大可以试imgsz1024提升小目标召回。参数说明batch16在8GB显存上比较稳显存不够降到8。device0指定第一块GPUCPU训练去掉这个参数但会很慢。训练完看runs/detect/train/下的results.csv重点看mAP50和mAP50-95是否还在涨。3.3 训练中必须盯住的三个指标第一个是train/box_loss如果它一直不降说明学习率太大或标注有问题。第二个是metrics/mAP50焊接缺陷检测里mAP50到0.7以上才算可用。第三个是val/box_loss如果它先降后升说明过拟合要加数据增强或早停。# 训练结束后用验证集跑一次评估 yolo detect val modelruns/detect/train/weights/best.pt datadata.yaml imgsz640逻辑说明val命令加载训练好的best.pt在验证集上输出每类的precision、recall、mAP。重点看哪一类的recall特别低那类就是短板。参数说明imgsz要和训练时一致否则评估结果不可比。如果某类mAP为0先检查data.yaml里的类别名和标注里的类别名是否完全一致。4. 焊接缺陷检测的避坑清单从标注到部署的5个翻车现场4.1 类别名带空格导致训练时类别数为0现象训练启动后报AssertionError: nc6 but names length0或者所有标注都被忽略。原因VOC的XML里类别名写了「气孔 」末尾带空格而data.yaml里写的是「气孔」匹配不上。解决在转换脚本里统一用.strip()并在生成data.yaml前用set()打印所有唯一类别名人工核对一遍。4.2 图片和标注文件名不对应现象训练时提示No labels found但labels目录里明明有txt。原因图片是001.jpg标注是001.txt但YOLO要求图片和标注除了扩展名外完全同名。如果图片是001.JPG大写标注是001.txt在某些系统上会匹配失败。解决用脚本批量把图片扩展名统一成小写.jpg标注统一成.txt并确保主文件名一致。4.3 验证集里混入了训练集图片现象验证集mAP异常高但测试新图片时效果很差。原因划分train/val时用了随机划分但没固定随机种子或者同一张图的增强版本同时出现在train和val。解决用sklearn.model_selection.train_test_split固定random_state42并且按图片划分而不是按标注框划分。焊接缺陷数据集里同一张图可能有多个缺陷按框划分会导致数据泄漏。4.4 小目标缺陷被过度下采样现象气孔、裂纹这类小缺陷的recall很低mAP50只有0.3左右。原因YOLOv8默认的imgsz640会把原图缩小小缺陷变成几个像素特征丢失。解决把imgsz提到1024或1280同时把batch降到8或4。如果显存不够用yolov8s代替yolov8n小模型对大输入更友好。另外可以在data.yaml里加rectTrue做矩形训练减少padding。4.5 部署时预处理和训练时不一致现象训练时mAP50到0.85部署到产线相机上检测率不到50%。原因训练时图片是RGB部署时相机输出BGR或者训练时做了归一化而部署时忘了。解决把训练时的预处理步骤写成独立函数部署时直接调用同一个函数。YOLOv8的predict模式默认会做letterbox和归一化但如果自己写推理脚本必须手动对齐。5. 把2684张用到极致类别均衡与难例挖掘的两个进阶技巧数据集只有2684张6类一分有的类可能不到200张。直接训练模型会偏向多数类。我一般会做两件事第一用copy-paste增强少数类。把少数类缺陷的标注框抠出来随机贴到无缺陷的焊接背景图上同时生成对应的YOLO标注。第二用训练好的模型在训练集上跑推理把置信度在0.3到0.6之间的预测框挑出来人工复核后加入训练集。这两步做完少数类的recall通常能涨10到15个百分点。# 难例挖掘用训练好的模型找低置信度预测 from ultralytics import YOLO import os model YOLO(runs/detect/train/weights/best.pt) img_dir weld_defect/YOLO/images/train hard_examples [] for img_name in os.listdir(img_dir): img_path os.path.join(img_dir, img_name) results model(img_path, conf0.3, iou0.5, verboseFalse) for r in results: if r.boxes is None: continue for conf in r.boxes.conf.tolist(): if 0.3 conf 0.6: hard_examples.append((img_name, conf)) break print(f难例数量: {len(hard_examples)}) for name, conf in hard_examples[:10]: print(f{name}: {conf:.3f})逻辑说明加载训练好的best.pt对训练集每张图推理置信度阈值设0.3把置信度在0.3到0.6之间的图片记为难例。这些图片模型「拿不准」人工复核后重新标注加入下一轮训练。参数说明conf0.3是下限低于0.3的可能是背景误检不值得花时间。iou0.5控制NMS焊接缺陷重叠少可以设0.5。难例数量控制在总数据的10%到20%太多会拖慢迭代。验证方法上我习惯在每轮训练后固定抽50张验证集图片用同一个随机种子做可视化对比。看三样东西漏检的缺陷在哪、误检的框长什么样、框的贴合度有没有变好。这比只看mAP数字更直观。有一次mAP涨了3个点但可视化发现模型把一条划痕误检成了裂纹这种「涨点但不可用」的情况只有看图才能发现。最后说个习惯每次改完数据或参数先把data.yaml和转换脚本一起提交到git训练命令写在README里。焊接缺陷数据集不大但实验次数一多很容易忘了哪次改了什么。我吃过这个亏回头复现最佳结果时发现少记了一个imgsz参数白白多跑了两天。希望帮到你。本文还有配套的精品资源点击获取