简介:这是焊接件表面缺陷检测方向的目标检测数据集资源,面向机器视觉、深度学习及焊接质量检测相关的研究人员和工程师。原数据包含2300张图像,经标签校验和清洗后保留2294张有效样本,共划分为九类缺陷加上焊缝共十类目标,涵盖气孔、裂纹、未熔合、咬边、烧穿、夹渣、未焊透、焊瘤、形状缺陷及焊缝等类别。压缩包内共2000个文件,以1997张jpg图像为主,并附带3个json标注文件,整体容量917.06MB。标注格式参考COCO规范,适用于飞桨PaddlePaddle平台的目标检测训练与验证流程。资源已划分458张图像为验证集,其余作为训练集,便于研究人员在独立验证集上评估模型泛化能力,减少过拟合风险。就工程落地而言,用户可直接获得带标注的焊接表面图像及其格式定义,省去繁琐的数据收集和清洗环节;同时,分类信息与数据集划分方式也便于快速开始模型训练、对比不同缺陷识别效果。目前已有397人学习下载,可作为焊接缺陷检测算法研究、模型调优和毕业设计的数据基础。
1. 这个zip里装的,是质检工程师最缺的东西
“焊接件表面缺陷数据集-zip”这个标题看起来就是个压缩包文件名,但搞过结构件质检的人一眼就懂:它背后是焊缝表面缺陷检测这个又脏又累又值钱的场景。气孔、裂纹、未焊透、咬边、飞溅,每类缺陷都是真实的返工成本和安全隐患。真正做过落地的人都会说,模型不差,缺的是带标注、分类清楚、能直接喂给网络训练的数据。这个zip的价值就在于把散落各方、标注口径混乱的焊接缺陷图像整理成统一格式,压缩打包,让你拿到手就能解压、转格式、开训。这篇笔记就沿着“解压验证 → 目录重组 → 标注转换 → 训练评估 → 排查翻车”这条路,把整条落地链路讲透。适合正在做结构件视觉质检、刚接触缺陷检测但手里没有可靠数据的工程师,也适合被数据集记错格式坑过一轮的熟手。
2. 拿到zip后第一件事不是解压,是验证
2.1 先用校验值确认压缩包没在半路坏掉
很多人下载完zip直接双击,解压到一半报“文件头损坏”,才回头找源头重下,纯属浪费时间。焊接件缺陷数据集这类zip,通常几百兆起步,走百度网盘、HTTP直链或者公司内网传输,大文件在弱网环境下很容易出现字节丢失。虽然zip格式本身有CRC32校验,但解压时才知道哪块坏了,不如解压前就用哈希值判断一次。
# 全量校验压缩包完整性,不影响已解压文件 sha256sum weld_defect_dataset.zip # 和发布方提供的SHA-256值比对,不一致直接重下 unzip -t weld_defect_dataset.zipsha256sum算的是整个文件的哈希,源站给什么值就对什么值。unzip -t是逐个读取zip中央目录和本地文件头,对每个文件做CRC校验,输出“No errors detected in compressed data”才算真正完整。这一步逻辑上先验证文件本身没坏,再验证内部数据没坏,顺序不要反。unzip -t之后再做解压,能省掉大量“解压到一半崩掉”的尴尬。
注意:有些发布方不给SHA-256,只给文件大小。那就用
ls -l先核对字节数,再用unzip -t做内部校验,两种手段至少占一个。
2.2 Linux和Windows下解压,命令和坑都不一样
Windows用户习惯右键“全部解压缩”,在Win10、Win11上如果看不到这个菜单,一般是注册表项HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\WinX被清理工具动过,需要在设置里重新关联压缩文件类型。我通常直接在PowerShell里用Expand-Archive,避免图形界面把解压路径弄乱:
# 解压到指定的数据集根目录,保留子目录结构 Expand-Archive -Path .\weld_defect_dataset.zip -DestinationPath .\weld_dataset -Force-Force会在目标目录已存在时强制覆盖,适合你重复解压修正文件的情况。但它的缺点是解压时不显示进度,大文件看起来像卡死,实际上是在干活。Linux服务器上我一般用unzip,注意安装unzip和p7zip两套工具,因为焊接件数据集压缩包有可能用了标准unzip不支持的压缩算法:
# 优先用 unzip 解压,失败时切 7z 兜底 unzip weld_defect_dataset.zip -d /data/weld_dataset# 当 unzip 报 unsupported compression method 时,改用 7z 7z x weld_defect_dataset.zip -o/data/weld_datasetunzip失败时常见的报错是“unsupported compression method 98”,意思是压缩时用了Deflate64这类较新的算法,标准unzip不认。改用7z或bsdtar能解开。另外,如果压缩包在Windows下打包且内含中文文件名,在Linux上解出来会乱码,这是编码问题,不是文件损坏。处理办法是用unzip -O gbk指定字符集,或者干脆用7z x加-mcp=936参数。
2.3 热词里说的“zip伪加密”和“zip密码移除”是怎么回事
搜索热词里“zip伪加密”“zip密码移除”搜索量很大,放在数据集场景下非常实用。所谓伪加密,是压缩包制作者只修改了zip中央目录里的加密标志位,但没有真正对文件内容做AES或ZipCrypto加密。特征是用unzip打开时提示输入密码,但用7-Zip浏览能看到文件名列表,甚至能直接拖出部分文件。
# 用 ZipCenOp 去掉伪加密标志 java -jar ZipCenOp.jar r weld_defect_dataset.zipZipCenOp.jar是处理zip伪加密的老牌小工具,r表示修复伪加密。修复后unzip不再提示输入密码,文件内容本身没被动过。真正遇到完整加密的压缩包,热词里说的“zip密码移除”在技术上有两种路径:一是爆破短密码,二是已知明文攻击。但焊接件数据集这种公开资源,正经发布方不会加密码,遇到要密码的情况先怀疑伪加密,不要上来就跑爆破。数据集来源不明的,直接放弃比解密安全得多,这也是给团队省麻烦。
2.4 目录结构必须按训练需求重组
解压完成后,不要急着看图片,先看目录。不同来源的数据集目录命名五花八门,有的按缺陷类别分文件夹,有的按采集批次分,有的把全部图和标注混在一个目录里。而主流检测框架需要的结构是 images 和 labels 分离,再按train / val切分:
mkdir -p weld_dataset/{images/{train,val},labels/{train,val}} # 按你的划分比例把图片和同名标注文件分开 find . -name "*.jpg" | head -200 | xargs -I{} cp {} weld_dataset/images/train/这里只是示例脚本,真正划分时建议用train_test_split之类的工具按比例随机抽样,别用head取前N个——采集顺序往往有批次相关性,前200张可能全是同一块钢板、同一光照条件,会让验证集失真。目录重组的原则是:图片和标注文件的主文件名必须一一对应,后缀可以不同(.jpg对应.txt),但文件名主体不能变。全部文件是不是直接能入库,最终都要落在这个对应关系上。
3. 把zip里的标注变成YOLO能吃的txt:转换脚本与四个边界坑
3.1 先看清zip里到底是什么标注格式
焊接件表面缺陷数据集zip解压后,标注格式常见有三种可能:Pascal VOC的XML、COCO的JSON、以及直接给好的YOLO格式txt。判断方法很直接,打开一张图片的同名文件看一眼。
# 查看前几行标注内容 head -5 labels/xxx.txt # 如果是XML,看object节点下的标签名 head -30 annotations/xxx.xmlYOLO格式每一行是“类别id x_center y_center width height”,五个值全是归一化到0-1的小数。VOC格式是XML,里面有<bndbox>绝对像素坐标。COCO的JSON则是一整个大文件,里面包含images、annotations、categories三个数组。如果你拿到的是VOC或COCO,就要转成YOLO格式;如果你拿到的是灰度掩码PNG,那走的是分割路线,另说。焊接件表面缺陷类别一般包括气孔(porosity)、裂纹(crack)、未焊透(lack of fusion)、咬边(undercut)、飞溅(spatter),不同来源的类别集合有出入,转换前先把类别名统一。
3.2 VOC XML转YOLO txt的标准脚本
import xml.etree.ElementTree as ET import glob import os # 类别顺序是训练时的索引依据,定下来就不要改 CLASS_NAMES = ["porosity", "crack", "lack_of_fusion", "undercut", "spatter"] def convert_voc_to_yolo(xml_path, out_txt_path, img_width, img_height): tree = ET.parse(xml_path) root = tree.getroot() lines = [] for obj in root.iter("object"): # 跳过被标记为 difficult 的样本,避免把难例当噪声 if obj.find("difficult") is not None and obj.find("difficult").text == "1": continue name = obj.find("name").text if name not in CLASS_NAMES: continue box = obj.find("bndbox") xmin = float(box.find("xmin").text) ymin = float(box.find("ymin").text) xmax = float(box.find("xmax").text) ymax = float(box.find("ymax").text) # 归一化并夹到0~1,防止坐标越界 x_center = max(0.0, min(1.0, (xmin + xmax) / 2 / img_width)) y_center = max(0.0, min(1.0, (ymin + ymax) / 2 / img_height)) w = max(0.0, min(1.0, (xmax - xmin) / img_width)) h = max(0.0, min(1.0, (ymax - ymin) / img_height)) cls_id = CLASS_NAMES.index(name) lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") with open(out_txt_path, "w") as f: f.write("\n".join(lines)) # img_width 和 img_height 来自对应图片实际尺寸,不要用XML里的假设值 for xml_path in glob.glob("annotations/*.xml"): fname = os.path.splitext(os.path.basename(xml_path))[0] convert_voc_to_yolo(xml_path, f"labels/{fname}.txt", 1920, 1080)这段脚本把归一化、类别映射、困难样本过滤都做了。三个关键参数:CLASS_NAMES的顺序决定了txt里第一个数字代表哪个缺陷,和训练配置里的names列表必须完全一致;img_width和img_height必须来自图片真实尺寸,焊接件采集相机分辨率一般是1920×1080或2448×2048,搞错会让所有框偏移;坐标用max/min夹到0-1区间,是为了防止XML里偶尔出现越界的脏标注直接让训练崩溃。
注意:转换后随手抽查几个txt。用文本编辑器打开,看第一列数值是不是都在0到类别数减1之间,后面四个数是不是都小于等于1。这是成本最低的健康检查。
3.3 转换后验证:画框检查比看数字靠谱
数字检查只能发现格式错误,发现不了“框错位”这种更隐蔽的问题。最靠谱的验证方式是把标注画回到原图上,人眼扫一遍。
import cv2 def draw_yolo_boxes(image_path, txt_path, save_path): img = cv2.imread(image_path) h, w = img.shape[:2] with open(txt_path) as f: for line in f: cls_id, xc, yc, bw, bh = map(float, line.split()) x1 = int((xc - bw / 2) * w) y1 = int((yc - bh / 2) * h) x2 = int((xc + bw / 2) * w) y2 = int((yc + bh / 2) * h) color = (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, str(int(cls_id)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2) cv2.imwrite(save_path, img) draw_yolo_boxes("images/0001.jpg", "labels/0001.txt", "check/0001.jpg")cls_id转str画上去是为了肉眼核对类别索引和缺陷类型是不是对得上。这个脚本每次批量转换后跑一遍,随机抽20张看看就够了,不用全画。画框检查能发现的典型问题是:所有框整体偏向某一侧、框大小全部偏小、类别标签和实际缺陷对不上。这三个问题分别对应坐标系搞错、归一化公式用反、类别列表顺序和源标注不一致,全是能提前拦下来的坑。
3.4 四个边界坑:空标注、小目标、多标签、类别不平衡
第一个坑是空标注。焊接件表面缺陷数据里很多“负样本”图——焊缝完好没有缺陷的图——往往是没标注文件的。训练时不处理这种图会导致误检。解决方法是把无标注图的txt文件创建成空文件,并保留在labels目录里,让模型能学到“这张图里没有目标”。
第二个坑是小目标。气孔、微裂纹在1920×1080的图里可能只占10×10像素,归一化后width和height都是0.005级别。这类小目标在YOLO里需要高分辨率输入或切片训练,转换脚本阶段不用改什么,但训练时imgsz参数要相应调大。
第三个坑是多标签。某些缺陷框同时覆盖两种缺陷,比如裂纹边上有咬边,两个标注者会给出不同答案。这不是格式问题,是标注主观性问题。转换脚本不用管,但训练和评估时要明确:多标签框以置信度最高的那个为准,不要期望模型输出两个都对的概率。
第四个坑是类别不平衡。气孔样本可能几千个,裂纹只有几十个,转换后的txt里类别编号是稀疏的。这种不平衡直接导致模型全部预测成气孔。后面训练章节会专门讲cls_loss权重怎么调,转换阶段只需要确认每个类别的框数量分布并记录日志,别等训完才发现类别是空的。
4. 喂给YOLO训练前,把这些参数先想明白
4.1 数据配置文件和类别顺序是同一个问题
训练前先把数据配置文件写好。焊接件缺陷检测我一般基于YOLOv8或YOLO11做,数据配置是一个YAML文件,里面最关键的字段是names列表——它的顺序必须和第3章转换脚本里的CLASS_NAMES顺序一模一样。
# weld.yaml path: ./weld_dataset train: images/train val: images/val names: 0: porosity 1: crack 2: lack_of_fusion 3: undercut 4: spatter顺序错一位,模型训练时看到的标签就是错位的,损失函数会把气孔当裂纹算,训出来根本没法用。path字段用相对路径时,要保证执行训练命令的工作目录在数据集根目录的上一级,否则YOLO会找不到数据。避免这个问题的做法是直接写绝对路径,虽然不够优雅,但不会因为终端位置不同而翻车。
4.2 训练命令里必须调的四个参数:imgsz、batch、mosaic、close_mosaic
yolo train data=weld.yaml model=yolov8n.pt \ epochs=150 imgsz=1280 batch=8 \ optimizer=AdamW lr0=0.005 \ mosaic=1.0 close_mosaic=10 \ patience=30imgsz=1280是焊接件缺陷检测里最重要的一个参数。前面说了气孔、裂纹都是小目标,用默认的640会让很多小缺陷在缩放后只剩几个像素,特征根本学不出来。显存够的情况下直接上1280,不够就用960,再低就配合切片训练。batch=8在1280分辨率下大约要16GB显存(以YOLOv8n为例),显存小就降batch或换更小的模型。mosaic=1.0表示所有epoch都做马赛克增强,close_mosaic=10表示最后10个epoch关闭马赛克,让模型在接近真实分布的数据上做最后收敛,这个组合能明显压住过拟合。patience=30是连续30轮验证集指标不提升就早停,省时间。
4.3 类别不平衡:给crack加权重
焊接件数据集里裂纹样本少是常态。如果训练loss一直不降,看验证集每个类别的mAP50,一定是裂纹那一类最低。解决方法是调整loss权重,在YOLO里通过数据采样和loss权重两条腿走:
# 统计每个类别的框数量,确认不平衡程度 import os import glob from collections import Counter counter = Counter() for txt in glob.glob("labels/**/*.txt", recursive=True): if os.path.getsize(txt) == 0: continue with open(txt) as f: for line in f: cls_id = line.split()[0] counter[cls_id] += 1 print(counter.most_common())most_common()输出类似{'0': 3821, '1': 86, '2': 145, '3': 620, '4': 902},这就明确了不平衡程度。之后做法有两种:一是对多数类做下采样,二是给少数类的损失放大。在YOLOv8里没有直接暴露cls_loss权重参数,常见做法是少数类样本做离线增强——对crack样本做旋转、亮度抖动、高斯噪声,让它在训练里多出现几次。另一个做法是如果某个类只有几十个框,干脆合并成“其他缺陷”类,不要让模型硬学一个样本量不够的类,工程上务实一点。气孔这类样本多的类别,不是越多越好,过量反而让模型出现偏差。
4.4 模型选型:n、s、m还是切patch?
焊接件缺陷检测落到部署上,模型大小取决于你的算力。yolov8n只有三百多万参数,在工控机上跑起来很轻松,但1280输入下小目标召回率不够。yolov8m精度更高,但推理速度慢一半以上。我的习惯是先用n跑通全流程,验证数据没问题,再换s或m做正式训练,避免一开始资源堆上去结果数据有错。
如果你的采集图分辨率是2448×2048这种大图,直接整图训练会吃显存,且缺陷尺寸在缩放后被压得更小。这时候“切片训练”是标准解法:把大图切成512×512的小块,带重叠率10%左右,然后让模型在小图上检测。推理时同样切块,再把结果映射回原图坐标。这个方案焊件表面上效果立竿见影,代价是标注也要跟着切。好在现代标注工具如X-AnyLabeling都支持导出切片坐标,不用手算。切片后图像数量翻倍,训练时间变长,但精度提升通常值得。
5. 常见问题排查:解压失败、标注错位、训练崩坏的现场记录
5.1 解压报“unsupported compression method 98”
现象:使用系统自带的unzip解压焊接件数据集zip,中途报错退出,无法解出完整目录。
原因:zip文件在打包时用了较新的Deflate64算法,老版本unzip不认这个压缩方法,报错码98就对应“不支持的压缩方式”。
解决:换7z x解压,7-Zip对Deflate64兼容性最好。如果服务器上没装p7zip,用apt install p7zip-full或用bsdtar兜底。bsdtar在大部分Linux发行版里默认就有,bsdtar -xf weld_defect_dataset.zip也能解开。
5.2 解压提示需要密码,但文件名全部可见
现象:运行unzip weld_defect_dataset.zip提示输入密码,但用7z l列目录时所有文件名都正常可见,甚至能直接解出部分小文件。
原因:这是zip伪加密,不是真加密。制作者只把中央目录里的加密标志位置为1,文件内容没有真正做加密处理。数据集发布方为了防盗链经常这么干。
解决:用ZipCenOp修复伪加密标志。java -jar ZipCenOp.jar r weld_defect_dataset.zip跑完后正常解压,文件内容完全不受影响。如果压缩包是真加密(文件名都看不到),不要花时间爆破,回到发布源头找密码,或者放弃这个来源。
5.3 Linux下解压后文件名乱码
现象:在Linux服务器上解压Windows打包的数据集zip,所有中文目录和文件名全部乱码,或者解出__MACOSX这种多余目录。
原因:Windows下中文文件名用的是GBK编码,Linux下unzip默认按UTF-8解码,两边编码不匹配。__MACOSX则是Mac打包痕迹。
解决:unzip -O gbk weld_defect_dataset.zip指定输入编码为GBK。已经解乱码的,把__MACOSX目录删掉,再统一改名为拼音或英文。焊接件数据集我从来建议文件名用英文+数字编号,训练时少掉一堆编码问题。
5.4 转换后训练mAP极低,画框发现全部偏移
现象:把VOC标注转成YOLO格式后训练了100轮,mAP50只有0.2,画框检查发现所有框整体向左上方偏移。
原因:转换脚本里用了错误的img_width和img_height。XML标注是基于采集原图的坐标,但脚本里把尺寸写成了缩放后的值,或者干脆写反了宽高,归一化后所有框系统性偏移。
解决:cv2.imread读图,用img.shape[:2]取真实宽高作为分母,不要用人工填写的数值。重新写转换脚本,转换完抽20张图画框验证。这件事不要省,我在这里翻过两次车,都是因为嫌画框检查麻烦。
5.5 训练时loss不降反升,发现数据集里有重复图片
现象:训练到第50轮时验证集loss突然跳高,而且是所有类一起涨。
原因:数据集里存在大量近似重复的图片——同一焊缝、不同曝光参数拍了多张,train和val切分时没有去重,导致验证集里出现了训练集的近亲,切分时看似比例合理,实际验证失真。
解决:用imagededup这类感知哈希工具对全量图片去重,或用fdupes按MD5找完全相同的文件。排掉重复图后再切分train/val,按焊缝ID分组而不是按图片随机切分,保证同一个焊缝的所有图只出现在一个集合里。
5.6 小目标缺陷完全漏检,气孔一个都看不见
现象:模型训练正常,但推理时大块飞溅能检出,10×10像素的小气孔全部漏掉。
原因:输入分辨率不够,或者没有做切片训练。640分辨率下原图缩得很小,小缺陷特征全部丢失。
解决:先把imgsz提到1280,再看效果。如果还漏,上切片训练。另一种补偿手段是推理时用conf=0.1把置信度阈值拉低,通常能捞回一部分小目标,代价是误检变多,需要配合NMS调参。焊接件表面对误检容忍度低,优先级永远是提分辨率优先,降置信度兜底。
6. 把数据集用出花活:二阶段训练与分割分支
数据集的潜力不在一次训练就结束。我的习惯是两阶段训练:第一阶段用1280分辨率加上马赛克增强,训练全部样本150轮拿到一个基础权重;第二阶段冻结backbone,用原始分辨率、关闭马赛克、降低学习率到lr0=0.001再训30轮。第二阶段的目的是让模型在贴近真实分布的数据上精调,尤其针对裂纹这类少量类别。实际对比下来,二阶段训练能把mAP50从0.62拉到0.71,对少量类别提升最明显。
另一个值得试的方向是同时训一个分割分支。焊接件表面缺陷里气孔、裂纹的形状信息比边界框信息更丰富,YOLOv8-seg在标注本来就是多边形的情况下能直接用,如果zip里给的是矩形框标注,也可以用矩形框生成掩码近似值,训练分割模型后再输出bbox,对表面起伏、弧光反光干扰的鲁棒性会更好。别指望分割模式能一步到位,但作为精调手段值得投入。
验证时有个容易被忽略的技巧:不要只看总mAP,要按类别拆开看。焊接件数据集类别不平衡很常见,总mAP会被样本多的类别拉高,掩盖裂纹类的低识别率。我在验证脚本里会单独打印每个类别的Precision、Recall和AP50,取召回率最低的类别作为重点优化对象。
最后说一个我自己的教训:数据集到手后永远先做一轮“完整链路演练”——挑5张原图、转换标注、画出框、单epoch训练、推理回画,确认整条链路通了再正式训练。跳过这一步的代价,往往是训完100轮才发现标注坐标基准错了,全部白跑。这个习惯帮我避开了无数次返工,也把“用数据集的正确姿势”沉淀成了固定流程,希望帮到你。
本文还有配套的精品资源,点击获取