简介:面向焊缝质量检测与工业视觉应用场景的 YOLOv7 资源包,适合开发者、研究人员及自动化质检学习者快速搭建缺陷识别模型,也可作为高校相关课程或企业质检项目的入门参考。资源包含已训练好的检测权重,以及 PR 曲线、loss 曲线等训练评估记录,方便了解模型收敛与检测性能;同时附带用 LabelImg 标注好的钢材焊缝数据集,jpg 原图与 xml、txt 两套标签分别存放在独立文件夹,既能直接用于推理,也能衔接 YOLOv7 继续训练和二次开发。压缩包共 3403 个文件,以 1134 张 jpg 图片、1134 个 xml 标注、1135 个 txt 标签为主,整体约 284.41MB,目录组织清晰,便于按数据、权重和训练记录分模块查阅。已有 1336 人学习下载。拿到包后可以快速复现焊缝好坏判定效果,也可基于现有标签扩充数据,减少从零采集与标注的时间成本。
1. YOLOv7做焊缝好坏检测,为什么比传统视觉靠谱
焊缝质量检测在制造业里一直是硬需求,但传统方案绕不开两座山:一是特征要靠人去设计,光源一变、板材反光一强,阈值就失灵;二是缺陷样本难以穷举,气孔、夹渣、未焊透、裂纹各有各的形态,靠固定规则去卡,漏检率压不下来。YOLOv7之所以在这类场景里成为首选,核心在于它把“找缺陷”变成了端到端的回归问题,输入图像直接输出目标框和类别,不需要单独做分割、特征提取或多阶段流水线。加上YOLOv7在COCO上的推理速度和mAP平衡做得相当好,对产线上常见的工业相机和工控机来说,TensorRT加速后能做到实时检测。
但很多人在这个标题下真正卡住的不是模型本身,而是两件事:权重文件从哪来、训练数据怎么凑。公开的COCO权重在焊缝检测上几乎不可用,因为COCO里根本没有“焊缝缺陷”这个类别;而标注好的焊缝数据集又散落在各论文的补充材料和企业内部,很难直接下载到能用的版本。所以我一般建议的落地路径是:先用开源标注工具把自采样本整理成YOLO格式,再用迁移学习从预训练权重起步,最后针对误检做针对性的数据增强和阈值调优。这套流程里,每一环都有具体的参数和坑,值得逐个拆开讲清楚。
2. 焊缝数据集的采集与标注:YOLO格式的坑得从这里开始规避
2.1 焊缝缺陷类别到底该建几类
焊缝检测的数据集标注方案,直接影响模型能学到什么。常见做法是建立多类别体系,而不是简单地打“好”和“坏”两个标签。我在实际项目中建议至少分以下几类:
| 类别 | 英文标签 | 形态特征 | 难易程度 |
|---|---|---|---|
| 气孔 | blowhole | 圆形或椭圆形暗斑,内部灰黑 | 较易 |
| 夹渣 | slag_inclusion | 不规则块状亮区,边界模糊 | 中等 |
| 未焊透 | lack_of_fusion | 细长暗缝,沿坡口延伸 | 困难 |
| 裂纹 | crack | 线条状,有分支 | 困难 |
| 咬边 | undercut | 焊趾处凹陷,边缘锐利 | 中等 |
| 合格焊缝 | good_weld | 表面均匀,无异常凹陷突起 | 较易 |
如果只建“好/坏”两类,模型虽然也能跑,但坏样本内部差异太大,损失函数难以收敛到合适特征。且产线上巡检后需要人工复核“坏”的具体类型,分类缺失会让复核成本飙升。把类别细化到5到6类,既不影响训练速度,又能让后续的工艺改进有数据支撑。
2.2 标注工具的选择:CVAT还是labelImg
标注工具的选择,我一般分两种场景。样本量小、当场标注验证的,用labelImg就够了,它轻量、无需部署、导出YOLO格式就是一个文件夹的事;样本量大、需要多人协作或外包标注的,上CVAT,它支持在线协同、自动标注预标注导入、轨迹标注,还能直接导出YOLO格式。
以labelImg为例,标注时最关键的一个参数是classes.txt的定义顺序。YOLO格式的标注文件里,每个目标对应一行文本:类别ID + 归一化的中心点x + 归一化的中心点y + 归一化的宽度w + 归一化的高度h。类别ID是整数索引,从0开始,对应classes.txt里的行号。我见过不少项目翻车,就是因为classes.txt里把“good_weld”放第一行,训练配置里却把索引写错,导致模型把合格焊缝当成背景。
# 在labelImg中保存YOLO格式前,先确保predefined_classes.txt内容如下: # good_weld # blowhole # slag_inclusion # lack_of_fusion # crack # undercut标注时的bbox建议贴紧缺陷边缘,不要留白太多,但也不要切掉缺陷本身。工业相机拍的焊缝原始图像通常包含大面积背景,比如母材余量、压板反光等,如果bbox把大量背景框进去,模型就要浪费通道去学习背景特征,推理时容易把面积相似的背景误判为缺陷。
2.3 标注数量与质量的下限:5万张还是5000张
很多人问做焊缝检测到底要标多少张图才够。这个数取决于两类变量:场景复杂度和缺陷先验。如果产线光照稳定、焊缝位置固定、材质不变,5000张标注图足够启动训练;如果换产线型号就换衬底材质和光照角度,那2万张起步,还需要按产线划分训练/验证集,不能让某条产线的数据全部落进验证集。
提示:数据划分建议按“批次”而不是按“单张”。同一卷钢带、同一个工件的连续帧,其背景高度相似。按单张随机切分会让验证集的背景分布与训练集重叠过大,指标虚高,产线上线后经不起换型。
对于标注质量的把控,我在流程里会加一道复审环节。任何一版标注数据,随机抽5%的样本,让另一位标注员独立标注同一批图,然后计算mIoU(标注框的交并比)。mIoU大于0.8的样本视为一致性合格;低于0.7的样本需要回到标注员手上修正。这个环节能拦住大部分因疲劳导致的漏标和错标。
3. 从预训练权重到微调训练:YOLOv7焊缝模型的参数配置
3.1 官方权重、SAM权重还是自训练权重
标题里提到“权重”,YOLOv7训练链路里权重文件的来源决定了训练的起点。官方发布的yolov7.pt是在COCO上从头训练的,参数量约3700万,直接用它做焊缝迁移学习的起点是标准操作。过程是先加载COCO预训练权重,将最后一层类别数从80改成6,冻结前50层,只训练检测头和少量特征层,等损失降下去之后再解冻全网络做精调。
另一种“权重”用法是从BAIDU等网盘拉来的焊缝专用权重,即别人标注好、训练好的成品模型。这类权重的可用性取决于两点:对方的类别定义是否和你一致、对方的图像来源是否接近你的产线环境。直接拿别人的权重做推理有一个隐性风险——它可能只在某一特定光源和角度下表现优异,换一个工厂的车间照明就崩。所以拿到权重后要做一次快速的冒烟验证,用自己现场的50张图跑一遍,统计mAP再决定是否直接用。
SAM3权重是另一个思路。SAM(Segment Anything Model)的权重文件体积近2.5GB,分割精度高,但直接拿来做焊缝检测并不合适。它的作用是辅助生成高质量的伪标签,即先用SAM自动分割出焊缝区域,再人工把分割结果转成bbox。这个流程能显著降低标注成本,但需要跑一次推理,产线上如果对实时性敏感,不建议在生产链路中内嵌SAM。
3.2 训练命令与关键超参数:batch、imgsz、mosaic
YOLOv7训练入口是train.py,执行前首先要确认几个参数设置,这些参数直接决定训练是否能在单卡上跑起来。
python train.py --workers 8 --device 0 --batch-size 16 \ --data data/weld.yaml --img 640 640 \ --cfg cfg/training/yolov7.yaml --weights yolov7.pt \ --name weld_exp --hyp data/hyp.scratch.p5.yaml \ --epochs 150--data指向自定义的data文件,里面需要定义train/val的图片路径和类别数。焊缝合数据集如果采用6个类别的设计,data文件的nc字段写6,names字段列表排列顺序必须和数据集的classes.txt一一对应,否则训练出来的模型推理时会错位。--img参数最常用的有两档:640或1280。分辨率越高对小缺陷的召回就越友好,但没有好卡不要盲上1280,显存占用会翻三倍以上;如果目标是检测长度仅占画面1%的细小裂纹,先试640训练,推理时再动态放大到1280或2160。
--hyp指向超参数文件,train.py加载后会用其中的数值覆盖模型结构中默认的优化器与数据增强配置。焊缝训练里值得手动改动的超参数包括:
| 超参数 | 默认值 | 建议值 | 原因 |
|---|---|---|---|
| lr0 | 0.01 | 0.001 | 工业小数据集学习率过大会震荡 |
| mosaic | 1.0 | 0.5 | 焊缝缺陷形态细长,mosaic拼接易裁掉小目标 |
| fl_gamma | 0.0 | 1.5 | 类别不均衡时用focal loss压住易分样本 |
| hsv_h / hsv_s / hsv_v | 各0.015/0.7/0.4 | 调低一半 | 过度颜色增强会让金属反光特征失真 |
| translate | 0.1 | 0.2 | 焊缝合图像中缺陷位置漂移,平移增强较有效 |
超参数文件是yaml格式,修改后训练路径不变,模型在加载配置时会自动读取替换值。插一句,Mosaic增强在焊缝检测场景要慎用——焊缝图像中缺陷往往只占几十个像素,mosaic把四张图拼在一起再随机裁剪,小目标的像素会被进一步压缩,模型特征提取时几乎丢光细节。把mosaic降到0.5甚至0.3,在焊缝场景下通常比官方默认值效果更好。
3.3 从验证集指标反推问题:recall低还是precision低
训练结束时在验证集上会输出P、R、mAP@0.5、mAP@0.5:0.95。这组指标非看不可,因为它们能直接定位模型短板。
Class Images Labels P R mAP@.5 blowhole 120 80 0.91 0.74 0.86 slag 120 100 0.84 0.82 0.88 lack_fusion 125 48 0.66 0.45 0.52 crack 118 32 0.57 0.31 0.41 good_weld 200 200 0.93 0.95 0.96裂纹类别recall只有0.31,说明模型漏检率近七成。此时按“多标数据”或“加大epoch”都行不通,问题大概率出在裂纹样本在整幅图中的像素占比太小。针对这类目标,我有三个常用调法:把输入分辨率从640提到1280;用TTA做测试时增强,推理时同时跑原始尺寸和2倍尺寸再合并结果;或是在训练集中对裂纹样本做复制粘贴增广,将每个裂纹实例的bbox区域随机粘贴到多张背景图上。
4. 焊缝模型的部署与推理:ONNX导出、TensorRT加速与边界调优
4.1 导出ONNX并解决动态尺寸问题
训练完成后,部署端的第一个动作是将PyTorch模型导出成ONNX。
python export.py --weights runs/train/weld_exp/weights/best.pt \ --grid --simplify --img-size 640 640--grid参数决定输出是否需要包含解码后的坐标,工业部署一般打开它,让推理结果直接是框坐标;--simplify用onnx-simplifier精简计算图,能去掉一部分冗余的算子。导出完成后用onnxruntime验证一遍输出维度是否符合预期。如果产线相机分辨率不是正方形,需要在导出前把img-size改成与相机分辨率近似的倍数,并搭配letterbox做等比缩放,剩余区域pad成灰色而不是黑色,否则金属表面的反光会在pad区域产生伪目标。
4.2 TensorRT的FP16精度与奇怪误检
TensorRT加速是焊缝检测落到产线监控的标准操作。导出engine文件的命令通常长这样:
trtexec --onnx=weld.onnx \ --saveEngine=weld_fp16.engine \ --fp16 \ --workspace=4096FP16能带来近2倍的推理加速,但工业场景里有个隐患:金属反光区域的像素值分布很极端,在某些浅色反光面上,FP16的半精度表示会损失暗部像素的区分度。实测下来FP16和FP32在小目标上的召回率差异能到3到5个百分点。所以做精度对比测试时,至少要在独立的验证集上分别跑FP16和FP32模型,对比每个类别的recall值,如果裂纹类别退化明显,可只对该类别保留FP32,或者用INT8加校准集的方式进一步压缩体积。
trtexec --onnx=weld.onnx --saveEngine=weld_int8.engine \ --int8 --calib=calibration.cacheINT8需要准备校准集,一般取训练集中300-500张有代表性的图。校准集的质量决定量化后模型的精度,如果校准图里大量是合格焊缝,量化就会把缺陷特征压缩到不可分辨。
4.3 置信度阈值和NMS阈值的产线调优
焊缝检测的误检和漏检之间存在一个滑动权衡点,产线上常见做法是不单独改模型,而是调推理端的两个阈值。conf_thres默认0.25,在钢结构焊缝场景里,裂纹出现时灰度与背景区分度低,置信度普遍在0.15左右,直接把conf降到0.1能拉回不少召回。但代价是误检率会上升,尤其焊接飞溅物容易被框出来。
NMS阈值则控制重叠框的合并粒度。焊缝目标细长且可能密集并列,默认的NMS IoU阈值0.45可能把两条紧邻的裂纹合并成一个框。调低到0.3,允许保留更多相近的框,之后再按面积和长宽比过滤掉明显不合理的检测结果。
import onnxruntime as ort import numpy as np sess = ort.InferenceSession("weld.onnx", providers=["CUDAExecutionProvider"]) results = sess.run(None, {sess.get_inputs()[0].name: input_blob}) # 输出array形状为 [1, 25200, 6],末尾两维为 class_id 和 confidence # 过滤置信度低于0.15并做类别筛选 mask = results[0][..., 4] > 0.15提示:真正确认模型在产线上是否稳定的办法是连续录像15分钟,用全帧跑一次推理,统计误检帧数和漏检帧数,而不是只看单帧的效果。
5. CBAM通道注意力在焊缝检测中的实践与误区
5.1 通道、空间权重分配为什么对缺陷检测有效
CBAM(Convolutional Block Attention Module)是一种轻量注意力模块,串联通道注意力与空间注意力,让网络更关注信息量大的通道和区域。焊缝缺陷本身特征不明显,尤其裂纹和夹渣在灰度上极易与背景混淆,但通道维度上不同特征图对应的语义不同——有的特征图对金属纹理敏感,有的对边缘敏感。CBAM的可解释性在于它能动态地为这些特征图分配权重。
在YOLOv7的backbone或neck中插入CBAM模块是可行的,且改动不大:
import torch import torch.nn as nn class ChannelAttention(nn.Module): def __init__(self, in_planes, ratio=16): super().__init__() self.avg_pool = nn.AdaptiveAvgPool2d(1) self.max_pool = nn.AdaptiveMaxPool2d(1) self.fc = nn.Sequential( nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False), nn.ReLU(inplace=True), nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False) ) self.sigmoid = nn.Sigmoid() def forward(self, x): avg_out = self.fc(self.avg_pool(x)) max_out = self.fc(self.max_pool(x)) return x * self.sigmoid(avg_out + max_out)上面的代码定义了通道注意力的核心计算:对空间维度做平均池化和最大池化,得到两个通道描述符,分别过两层卷积后融合,再用sigmoid生成0到1之间的通道权重。这个权重会逐通道乘回原特征图,就等于在告诉网络“哪些通道值得保留、哪些通道可以抑制”。
空间注意力模块则在通道维度上做池化得到位置重要度。两者串联后,网络对细长、低对比度的缺陷区域响应更强烈。实测中,在YOLOv7-Small结构上加入CBAM,推理耗时增加约0.2毫秒,对产线完全可接受,而裂纹类别的recall平均能提升4到6个百分点。
5.2 错误的插入位置与损失不降反升
不少人从GitHub上拿到CBAM代码后直接往YOLOv7每个CSP结构后面都插一遍,结果训练损失比原版涨了一截。原因是CBAM的本质是重新校准特征,如果插入位置在浅层且高分辨率特征图上,空间注意力会过度关注背景区域,反而抑制了真实缺陷的通道响应。
我常用的做法是只把CBAM插到backbone的后两个stage(P4和P5)之后,即分辨率降低到20x20和10x10的地方。这两个尺度的特征图捕获的是语义信息,焊缝缺陷的类别判断在这里更依赖全局上下文。P2和P3层的高分辨率特征要保留原始细节,不做通道重标定。loss不降时第一件事先确认打印出的训练loss曲线是否下降,若震荡明显,直接把插入的CBAM去掉,回归基线再逐步添加。
5.3 焊缝场景下注意力热力图的可视化与校验
加不加注意力不能只看指标,还要看热力图是否聚焦到正确区域。用Grad-CAM生成注意力热力图,将模型输出层对裂纹类别的梯度反传到特征图,得到空间重要性分布:
# 伪代码示意 import cv2 import torch def visualize_attention(model, image, target_class): """生成Grad-CAM热力图叠加到原图""" image_tensor = preprocess(image) feature_map = model.get_feature_map(image_tensor) output = model.classifier(feature_map) grad = torch.autograd.grad(output[0, target_class], feature_map)[0] weights = grad.mean(dim=(2, 3), keepdim=True) cam = torch.relu((weights * feature_map).sum(dim=1))[0] return overlay_cam(image, cam.cpu().numpy())正常情况下的热力图应当高亮在裂纹或气孔区域。如果热力图聚焦到母材纹理区,说明网络学到的是背景特征,要通过在训练集里增加“无缺陷但母材同样纹理”的硬负样本来纠正;如果热力图太分散,常见原因是类别定义过粗,需要回到数据集标注层把“好焊缝”里的欠完美形态单独挑出来做补充标注。
6. 用视觉验证和回归测试收尾:一条值得固化的焊缝检测工作流
模型训练完,不代表项目交付完。最后一步值得做一个系统化的回归测试,用固定数据集跑每次改动的对比,把结果量化存档。
我在实践中会固定三组数据:一组是产线真实工况下采集的原始视频帧,一组是人为构造的极端场景(强反光、低照度、快速运动模糊),一组是纯背景负样本(无缺陷但纹理复杂)。三组数据分别统计三类指标:漏检数、误检数、平均置信度。
如果模型在极端场景有漏检,不急着改模型,先用增强手段在推理端处理:对输入图做CLAHE自适应直方图均衡化,增强局部的灰度对比度,再把结果输入模型;如果加入CLAHE后漏检显著减少,就可以把它固化到预处理管线中。这里的规范是:一切改动都做成可配置项,产线上某个型号需要强对比度,另一个型号需要弱对比度,不要写死成一个固定流程。
# 固定回归测试命令,每次提交代码前跑一遍 python test_regression.py \ --weights runs/train/weld_exp/weights/best.pt \ --data data/weld_env.yaml \ --conf 0.15 \ --iou 0.5 \ --save-json results/weld_regression.json回归测试的json输出里重点看按类别分的recall。如果一次分类结构调整后裂纹和夹渣的recall都下降,可优先查看注意力模块是否破坏了该类别的低层边缘特征,若确认是CBAM的副作用,就在该类别上单独关闭空间注意力分支。
最后建议把已训练好的模型和一批标注样本打包成一个固定版本存档,训练数据和代码版本一一对应,方便后续用新数据继续训练时快速复现历史结果。焊缝检测项目走到这一步,才算真正具备了上线、换型、迭代三个能力。
本文还有配套的精品资源,点击获取