简介面向目标检测与工业视觉算法开发者提供一套焊接缺陷检测数据集可用于焊接质量监控、工艺异常排查、钢结构与汽车零部件制造质检等场景也适合目标检测学习者进行 YOLO、SSD 等模型的训练、验证与算法对比。压缩包约 153.88MB解压后图片、标注与标签文件共 12411 个按 JPEGImages、Annotations、labels 三个目录组织分别存放 4137 张 JPG 图片、4137 个 XML 标注文件和 4137 个 TXT 标签文件图片、XML 与 TXT 一一对应既保留 VOC 格式又可直接按 YOLO 格式使用另含说明文档便于快速掌握目录结构与标注规范。图像清晰且已经过增强处理有助于提升模型泛化能力标注采用矩形框六类缺陷框数分别为 616、716、674、718、732、758合计 4214 个类别分布较为均衡。该数据集既可作为工业视觉算法的验证基准也能支撑从数据读取、格式转换到模型训练与评估的完整实验流程。已有 200 余人学习。1. 焊接缺陷检测数据集6类4137张YOLOVOC双格式开箱前先想清楚三件事焊接缺陷检测数据集光看文件名就知道它是给目标检测模型喂样本用的6个缺陷类别4137张图YOLO和VOC两套标注格式都齐还预先做过增强。这类资源最典型的场景是焊接工艺质检的自动化改造帮你在不上产线的情况下先把检测模型跑通。它适合刚接触YOLO的工程师快速练手也适合工业视觉项目里缺缺陷样本的团队当预训练基础。我的建议是解压之前先想清楚三件事这6类到底是哪6类标注边界有没有统一增强之后的验证集干不干净。很多翻车不是模型不行而是数据集的这三个前提没先确认。这篇笔记就把这个数据集拆开看给你能直接照做的校验流程和训练流程。2. 焊接缺陷检测的6类定义与标注边界类间相似度比你想的高2.1 六类缺陷的成像特征与检测难点焊接缺陷检测数据集里的“6类”通常围绕焊缝外观和内部质量展开。以最常见的六分类方案来说气孔、夹渣、未熔合、未焊透、裂纹、咬边基本覆盖了焊接质检的绝大部分现场问题。气孔是焊缝表面或内部的小圆孔远看就是一个个深色圆点夹渣是嵌在焊缝里的杂质形状不规则未熔合和未焊透都表现为母材与焊缝金属没结合好一个在层间一个在根部裂纹是线状或树枝状的暗纹咬边是焊缝边缘被烧出的凹槽。这六类放在目标检测里有一个共性类间相似度极高。未熔合和未焊透在灰度图上就是一条深浅不同的暗带夹渣和部分气孔在低分辨率下长得几乎一样。别的检测任务看整体轮廓焊接缺陷恰恰相反边缘细节决定模型能不能分得清。所以看这个数据集先看两件事一是它有没有把容易混淆的类别在说明文件里给出示例图二是各类别数量是否均衡。表格是这类数据集最常见的配套信息我习惯把它整理成下面这样类别典型形态成像难点气孔圆点状、深色、边缘清晰小目标占像素少夹渣不规则块状灰度不均匀形状多变容易与气孔混未熔合层间线状暗带灰度和未焊透接近未焊透根部条状暗带要结合位置上下文判断裂纹线状/树枝状暗纹细长容易被当成噪声咬边焊缝边缘凹槽与背景对比度低2.2 标注边界为什么决定模型上限同一张图上多个缺陷重叠比如一条裂纹尾部带着一串气孔标注时是分开两个框还是合成一个框小缺陷只有十几个像素是只标一个框还是干脆不标边界模糊的缺陷标注是保守还是激进。这些决策直接决定模型学到的边界而焊缺陷恰恰又是边界最模糊的一类目标。拿到数据集后我不会先训练而是先做一次类别分布统计确认各类别真实数量。用一段简单的脚本就能把标注文件里每个框的类别和数量拉出来。假设数据集用的是YOLO格式的txt标注脚本长这样import os import glob from collections import Counter label_dir labels/train # 改成解压后的实际标注目录 class_counts Counter() per_image [] for txt in glob.glob(os.path.join(label_dir, *.txt)): with open(txt, r) as f: lines [line.strip() for line in f if line.strip()] per_image.append(len(lines)) for line in lines: parts line.split() if len(parts) 1: class_counts[int(parts[0])] 1 print(总目标数:, sum(class_counts.values())) print(每张图目标数均值:, round(sum(per_image) / len(per_image), 2)) print(类别分布:) for cls in sorted(class_counts): print(f 类别 {cls}: {class_counts[cls]} 个框)逻辑说明脚本遍历labels/train下所有txt每一行取第一个数作为类别id累加同时记录每张图的目标数。运行后如果发现某个类别只有几十个框另一个类别上千后续训练就要重点补样本或调损失权重。参数说明label_dir要改成你解压后的实际标注路径如果标签是VOC格式的xml把解析逻辑改成读xml的name字段统计逻辑完全一样。这个脚本只用Python标准库不依赖第三方库拿到任何数据集都能先用它摸底。还有一个连带指标要算单张图平均目标数。焊接缺陷数据集的图片往往只有一到两个缺陷平均目标数如果低于1.5模型在小目标上会明显乏力如果高于3要留意密集缺陷堆叠时的标注质量。这两个数字决定了后面的anchor设计和imgsz设置先记录好训练出问题时有据可查。2.3 标注质量抽检把框画回原图统计只能看出数量看不出框贴不贴目标。抽检方法随机抽10到20张训练图把YOLO坐标换算回像素坐标用OpenCV把矩形框画出来一边看图一边核对框是否贴合缺陷边缘、有没有漏标、有没有标错类别。这个步骤花不了十分钟但后面节省的排错时间远大于十分钟。import cv2 import glob import os import random img_dir images/train label_dir labels/train class_names [crack, porosity, slag, lack_fusion, lack_penetration, undercut] # 按数据集的classes文件改 os.makedirs(vis_check, exist_okTrue) img_paths glob.glob(os.path.join(img_dir, *.jpg)) random.shuffle(img_paths) for img_path in img_paths[:10]: img cv2.imread(img_path) h, w img.shape[:2] txt_path os.path.join(label_dir, os.path.basename(img_path).rsplit(., 1)[0] .txt) if not os.path.exists(txt_path): continue with open(txt_path) as f: for line in f: parts line.split() if len(parts) 5: continue cls int(parts[0]) cx, cy, bw, bh map(float, parts[1:5]) x1, y1 int((cx - bw / 2) * w), int((cy - bh / 2) * h) x2, y2 int((cx bw / 2) * w), int((cy bh / 2) * h) color (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1) cv2.imwrite(os.path.join(vis_check, os.path.basename(img_path)), img)逻辑说明代码把YOLO归一化坐标乘回图片宽高转成左上角和右下角画框并写类别名输出到vis_check目录。这里有个细节putText的y坐标用了max(0, y1 - 5)防止框贴顶时文字跑到图像外面报错。参数说明class_names列表的顺序必须和数据集labels文件一致否则画出来的名字张冠李戴如果图片是pngglob通配符要改成*.png随机抽10张不满意可以调大img_paths[:10]里的数字。抽检时重点看三类问题框是不是包住了完整缺陷还是只包了一半有没有把一个裂纹拆成两个短框类别名和缺陷形态对不对得上。如果十张图里超过两张有明显问题这个数据集的标注一致性就要打个问号后面训练出的模型精度上限会受影响。3. YOLO与VOC双格式拆解坐标换算、转换脚本与增强数据的坑3.1 两套标注格式的关键差异YOLO格式每个txt文件对应一张图每行是“class_id cx cy w h”四个坐标都是相对图片宽高的归一化浮点数范围0到1。VOC格式是xml文件size里写图片宽高bndbox里写xmin、ymin、xmax、ymax四个像素绝对坐标。两者互相转换的核心就是一组乘除法换算公式如下YOLO转VOCxmin (cx - w/2) × img_widthymin (cy - h/2) × img_heightxmax (cx w/2) × img_widthymax (cy h/2) × img_height。VOC转YOLOcx (xmin xmax) / 2 / img_widthcy (ymin ymax) / 2 / img_heightw (xmax - xmin) / img_widthh (ymax - ymin) / img_height。对比项YOLO txtVOC xml坐标形式归一化浮点数像素绝对坐标图片尺寸不记录推理时读取记录在size标签里类别名数字索引字符串标签文件粒度一图一txt一图一xml无论往哪个方向转换都必须知道图片真实宽高。很多转换脚本翻车就翻在这里拿不到图片尺寸或者读到了被缩放过后的尺寸坐标全错。这也是标题里“YOLOVOC格式”两个格式的意义所在——你不用自己写转换但你必须理解两套坐标之间的关系否则校验标注、排查问题都无从下手。3.2 格式转换脚本YOLO转VOC的完整实现虽然数据集已经给了双格式但实际项目里经常要做反向操作比如自己补标了一批图是txt格式要合回流进VOC训练管线。我一般保留一套自己的转换脚本避免每次现写。下面是YOLO转VOC的常用实现import os import glob import xml.etree.ElementTree as ET from PIL import Image label_dir labels/train image_dir images/train out_dir voc_labels/train os.makedirs(out_dir, exist_okTrue) for txt in glob.glob(os.path.join(label_dir, *.txt)): img_path os.path.join(image_dir, os.path.basename(txt).rsplit(., 1)[0] .jpg) if not os.path.exists(img_path): img_path img_path.replace(.jpg, .png) # 兼容png命名 with Image.open(img_path) as img: w_img, h_img img.size annotation ET.Element(annotation) size ET.SubElement(annotation, size) ET.SubElement(size, width).text str(w_img) ET.SubElement(size, height).text str(h_img) with open(txt) as f: for line in f: parts line.split() if len(parts) 5: continue cls_id int(parts[0]) cx, cy, bw, bh map(float, parts[1:5]) xmin int((cx - bw / 2) * w_img) ymin int((cy - bh / 2) * h_img) xmax int((cx bw / 2) * w_img) ymax int((cy bh / 2) * h_img) obj ET.SubElement(annotation, object) ET.SubElement(obj, name).text str(cls_id) # 可换成类名字符串 bndbox ET.SubElement(obj, bndbox) ET.SubElement(bndbox, xmin).text str(xmin) ET.SubElement(bndbox, ymin).text str(ymin) ET.SubElement(bndbox, xmax).text str(xmax) ET.SubElement(bndbox, ymax).text str(ymax) tree ET.ElementTree(annotation) tree.write(os.path.join(out_dir, os.path.basename(txt).rsplit(., 1)[0] .xml))逻辑说明脚本读每个txt对应的图片尺寸把归一化坐标转成像素坐标写进xml树最后保存成VOC格式文件。注意代码里对图片命名的处理先找jpg找不到就尝试png这样不会因为图片后缀不一致中断。参数说明cls_id默认写成数字如果下游训练要求字符串类名把str(cls_id)改成从类名列表里取值w_img, h_img来自PIL读取的原始尺寸不要用缩放后的图像尺寸这是坐标不出错的前提。转换完必须做一致性校验随机挑几个xml把xmin、ymin、xmax、ymax画回原图确认框的位置和原txt一致。这个校验步骤不能省因为转换脚本最常见的错误是坐标方向写反或者读错图片尺寸导致整体偏移一个固定值。校验通过的xml才能放心用。3.3 已增强数据的正确打开方式标题里“已增强”三个字意味着这份数据集的训练图有一部分是原图做了数据增广得到的。常见的增强手段无非这几类增强手段作用风险亮度/对比度扰动模拟不同光照条件过度扰动会导致纹理失真高斯噪声/模糊提升抗噪能力小目标被噪声吞掉水平翻转加倍样本量焊缝方向性被破坏裂纹方向语义失效小角度旋转丰富几何形态旋转后标注框不准HSV色域扰动适应不同材质反光颜色偏到异常区间Mosaic拼接增加单图目标数小目标被压缩得更小增强本身不是坏事但有两个坑必须提前排掉。第一增强图不能混进验证集。验证集的意义是模拟真实推理分布如果用增强图做验证模型的指标会虚高部署到现场立刻现原形。第二翻转和旋转类增强对焊接缺陷有方向语义。裂纹如果只在一个方向出现水平翻转后裂纹方向变了模型学到的是“翻转后的纹理”而不是“裂纹的纹理”这个语义错位很难通过加数据修正。拿到zip后先看文件命名规律。常见的数据集会以_bright、_flip、_noise这类后缀标记增强图也有的直接用独立子目录区分。按命名规则把增强图只放进训练集验证集只保留原始图。如果数据集没有明确区分我建议自己写个脚本按文件名去重划分确保同一张原图的增强版本和原图不在验证集里同时出现。4. 用YOLOv8跑通4137张焊接缺陷数据集的完整流程解压到出模型4.1 目录组织与data.yaml解压后第一件事不是训练而是把目录结构理顺。YOLOv8读取数据集靠data.yaml里边只要配置好图像路径、标签路径、类别列表就行。常见做法是把数据组织成下面这种结构datasets/ └── weld/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── weld.yaml如果zip里本身是images和labels两个平级目录你可以用软链接组织出上面结构不需要实际复制文件再占一份磁盘空间mkdir -p datasets/weld ln -s /path/to/unzipped/images datasets/weld/images ln -s /path/to/unzipped/labels datasets/weld/labels对应的data.yaml这样写path: datasets/weld train: images/train val: images/val names: 0: crack 1: porosity 2: slag 3: lack_fusion 4: lack_penetration 5: undercut注意names的顺序必须和标签txt里第一列的类别索引完全一致类别索引从0开始。很多报错“class index out of range”就是这里对不上。如果你不确定类别名先打开数据集自带的classes.txt对照别凭文件名猜。path建议写绝对路径避免不同工作目录下相对路径解析出错。4.2 最小训练命令与关键超参数目录和配置文件就绪后直接跑训练命令。我习惯用YOLOv8的s模型先跑通再看资源换m或l。最小命令如下yolo detect train \ datadatasets/weld/weld.yaml \ modelyolov8s.pt \ epochs80 \ imgsz640 \ batch16 \ projectweld_exp \ namebaseline逻辑说明命令会加载yolov8s预训练权重按data.yaml读取训练集和验证集训练80个epoch并输出到weld_exp/baseline目录。跑完会在该目录下生成weights/best.pt和weights/last.ptbest按验证集mAP自动保存。参数说明epochs先从80起步焊接缺陷数据量不大80个epoch足够看到收敛趋势imgsz默认640如果显存够且缺陷偏小改成960或1280batch根据显卡显存调显存不够就减半。这里有个容易被忽略的参数patience默认100意思是连续这么多轮验证集mAP不涨就早停。80个epoch下patience默认值是够的但如果你把epochs调到200建议把patience显式设成30或50省得训练后半段干等。训练中断也不慌YOLOv8会保存last.pt可以加resumeTrue从断点继续。4.3 训练日志里必须盯的三个指标训练启动后屏幕上刷一堆进度条不需要全看盯三个地方就够。第一看loss曲线。box_loss和cls_loss曲线如果在前10个epoch稳定下降说明模型在正常学如果中间出现平台期后突然跳高多半是学习率策略在起作用或者数据里有坏样本先不动继续看后续走势。第二看验证集的mAP50这个指标代表框和类别都判对的综合水平。焊接缺陷检测如果mAP50能到0.7以上说明数据集质量基本过关卡在0.5上下优先怀疑标注问题而不是模型问题。第三看PR曲线。训练结束后打开results.png或跑一遍验证脚本观察PR曲线右下角有没有被“拽”下来。焊接缺陷里小目标多PR曲线的尾巴往往会因为小裂纹漏检而下坠这属于正常现象关键看曲线主体是不是饱满。如果曲线整体贴着右下角说明学习率设高了或者训练样本太少先别调模型回去看数据集划分。5. 焊接缺陷检测数据集训练的避坑笔记四类常见的翻车现场5.1 边界框越界与归一化错误训练中途loss不降反升现象训练到十几个epoch时box_loss突然波动甚至升高验证集mAP一直没动静。原因标签txt里的坐标不是归一化值或者w、h写成了像素值也可能是VOC转YOLO时除错了图片尺寸导致坐标超出0到1范围。YOLOv8对越界框不是直接报错而是做了裁切裁切后目标框位置已变模型学到的自然是不对的。解决训练前先跑一遍校验脚本把所有txt的坐标范围检查一遍。import glob for txt in glob.glob(datasets/weld/labels/train/*.txt): with open(txt) as f: for line in f: parts line.split() if len(parts) 5: print(格式错误:, txt, line) break cx, cy, w, h map(float, parts[1:5]) if not (0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1): print(坐标越界:, txt, line)逻辑说明逐行解析只要cx、cy、w、h任一超出0到1就打印出来。这样能快速定位是某个文件坏了还是整批转换出了问题。参数说明如果数据集用的是VOC格式先用第三章的转换脚本统一成YOLO格式再校验校验结果为空才能开始训练。这是整套流程里最便宜的一道保险千万别跳。5.2 增强数据泄漏进验证集val指标虚高但实测很差现象训练时验证集mAP非常高0.8以上但把模型拿到没有增强的新图上推理漏检明显变多。原因划分训练集和验证集时随机打乱同一张原图的增强版本和原图分别进了训练集和验证集。增强图和原图共享大部分纹理内容模型记住了这个“近亲”关系验证指标等于开卷考试。解决按文件名前缀划分保证同一原始图像的所有增强版本只落在训练集。先提取文件名里属于同一原始图的前缀再按前缀分组划分。例如原图叫weld_0001.jpg增强图叫weld_0001_bright.jpg按weld_0001分组即可。验证集只用完全没做过增强的原始图数量少一点没关系真实度优先。5.3 六类样本数量悬殊尾部类别漏检、mAP被多数类带歪现象训练完成后看看各类别AP气孔、夹渣这类多的类别AP到了0.8未焊透、裂纹却只有0.2甚至更低。整体mAP看起来还行一细化就露馅。原因类别不平衡时损失被样本量大的类别主导。焊接缺陷数据集里气孔和夹渣最容易收集裂纹和未焊透本来就少见如果增强只做了亮度扰动而没有针对少数类做样本扩充类别差距会越拉越大。解决先跑一次默认训练拿到各类AP作为不平衡的定量依据不要拍脑袋调参。针对少数类做两条路一是加样本把少数类的原图再做几组针对性增强比如对裂纹图做对比度增强让细线纹理更清楚二是调损失权重YOLOv8里可以设置cls_loss或按类别调权重把多数类权重降一点让少数类在loss里占更大比重。最土但有效的办法是对少数类做复制粘贴级过采样把少数类图片在训练集里多放几份这招在数量差10倍以内时比调参管用。5.4 小缺陷目标在深层特征图里消失细小裂纹检测不到现象带细裂纹的图模型大概率漏检即使检出了框也不贴合裂纹走向AP50和AP50-95差一大截。原因焊接缺陷里裂纹和气孔很多只有十几像素宽imgsz640下经过多次下采样小目标在深层特征图里只剩一两个像素特征基本被池化抹掉。这不是模型笨是分辨率喂不进去。解决三招可以组合用。第一招最直接把imgsz提到960甚至1280小目标像素数量翻倍代价是显存和训练时间上升第二招换用带P2检测头的模型结构P2层保留更高的空间分辨率专门缓解小目标丢失第三招是推理阶段做切图把大图切成若干重叠patch分别检测再合并结果这招在工业场景里很常用因为现场相机拍的是整块焊缝不是模型训练时的裁切图。先试第一招性价比最高。6. 验证这个数据集的三个技巧先看基线再决定要不要换增强6.1 第一次训练后只做两件事看mAP0.5和PR曲线训练结束后别急着部署先打开results.csv看两个数metrics/mAP50(B)和metrics/mAP50-95(B)。mAP50代表框和类别判对的整体水平焊接缺陷能做到0.7以上算及格mAP50-95代表框和真实目标重叠度要求更严的分数这个数低于0.4说明框不够贴目标后续要在回归精度上下功夫。PR曲线在results.png里看曲线主体是否饱满、尾巴有没有大幅下坠。这两样看完才谈得上后面调什么。6.2 用图像级误报反查标注质量问题验证集里那些预测错了的图我习惯按错误类型摊开分三类数据漏标模型检出了缺陷但标签没标、类间混淆把气孔判成夹渣、背景误报把飞溅、反光当缺陷。漏标优先回补标签类间混淆要看两类样本是否长得太像必要时合并类别背景误报说明负样本不够去现场多拍没有缺陷的焊缝图加进训练集。这一步做完你对这个数据集的底细就彻底摸清了。6.3 增强策略回退最少改动拿回性能加过增强的数据集训练不升反降时最有效的排查办法是把增强全部关掉只用原图训练一次。如果原图训练表现反而更好说明增强参数过猛或增强方案不符合焊接缺陷纹理规律一项一项往回加每次只加一种增强手段看验证集指标变化再决定留不留。我自己的血泪经验是一开始图省事直接上了全套增强结果模型学到的全是增强痕迹换成原图基线后mAP反而涨了几个点。现在的流程永远是先原图跑通再逐步加增强翻车了也知道是哪一步造成的。这个习惯在焊接缺陷这种小样本、高相似度数据集上尤其重要希望帮到你。本文还有配套的精品资源点击获取