
简介焊接质量检测是工业制造中的关键环节传统人工目检效率低且容易漏检。随着深度学习与机器视觉技术的融合发展基于目标检测的自动化缺陷识别已逐步成为智能质检的核心方向。YOLOv11作为新一代实时目标检测算法通过C3k2模块与C2PSA注意力机制增强全局上下文感知在裂纹、气孔、夹渣、未熔合、咬边和焊瘤六类焊接缺陷的识别上表现出高精度与高速度。本文聚焦工程实践系统阐述焊接缺陷数据采集与标注规范、环境配置与源码目录组织、训练调参与评估指标、推理结果保存及产线部署落地方式并结合裂纹标注、小目标气孔和反光干扰等典型踩坑记录帮助质量工程师与算法开发者在实际产线中快速构建稳定可靠的焊接质量智能检测系统。 我第一次认真琢磨焊接质检这件事是在一条结构件焊接线上。老师傅戴着老花镜手电筒侧着光扫焊缝一只工件要看三四十秒旁边待检的箱子越堆越高。焊接质量智能检测这个说法听着大其实落到产线上就是两件事能不能看得准能不能跑得快。后来我把方案收敛到了YOLOv11上做了一套支持裂纹、气孔、夹渣、未熔合、咬边、焊瘤六类缺陷识别的检测系统配套源代码、权重文件和使用说明工程真正跑通了才敢拿出来分享。这篇文章不打算讲太多论文式理论就讲这套系统从数据、训练、推理到部署踩过的所有坑以及你在自己的产线上重新搭一遍需要的东西。1. 焊接质检的痛点与YOLOv11替代传统方案的逻辑1.1 六类缺陷的形成原因与视觉特征先明确这六类缺陷到底长什么样。我直接说我在标注和训练过程中总结出的视觉特征比教科书上的定义更贴近模型视角。缺陷类别形成原因图像特征对检测模型的影响裂纹焊接应力集中或冷却速度过快细长线状、方向随机宽度常只有几个像素尺度太小极易漏检气孔熔池中气体来不及逸出圆形或近圆形暗斑常有亮边可单个或成群出现目标小且密集定位难夹渣焊剂或氧化物未浮出熔池形状不规则的暗色或亮色团块与正常焊纹相似容易混淆未熔合热输入不足或坡口角度不对焊缝根部或边缘的细长暗线边缘区域对比度低咬边焊接电流过大烧损母材焊缝边缘的沟槽状凹陷常见亮边与阴影相似容易误检焊瘤熔敷金属流淌到母材表面焊缝旁突起的金属堆积形态变化大边界难定这六类缺陷在模型看来其实是不同的任务。裂纹是细长目标气孔是典型小目标夹渣和咬边是区域纹理异常焊瘤则是形态明显的外来物。处理思路不能一套打天下。我特别想说裂纹这个老大难。目标检测的框是矩形而裂纹是细长曲线一个矩形框里真正的裂纹像素可能不到10%模型很容易学到框里大部分是正常焊纹也没关系。气孔恰好相反小目标对标注框的位置误差极其敏感框稍微偏几个像素定位精度就掉一大截。这也是为什么气孔多的数据集首要任务是保证标注质量而不是拼命堆数量。1.2 传统视觉方案为什么走不通不引入深度学习之前很多人第一反应是用灰度阈值加Canny边缘检测再做形态学闭运算把缺陷连成区域。这套路在实验室固定光照下能看拿到产线就露馅。焊缝表面有规则的鱼鳞纹电弧纹路的边缘响应不一定比缺陷弱。反光区域更是直接烧穿阈值一个高光点会被当成一片缺陷。我试过在固定打光条件下调一版传统方案换个工件角度误检率马上翻倍。规则方法的本质是用人的逻辑去枚举所有可能可焊接缺陷的形态变化实在太多——同样一条裂纹位置、宽度、走向稍微变一下阈值参数就要重调。深度学习模型在这里真正解决的问题是让算法从数据里自己总结缺陷的特征边界而不是靠人去写无穷无尽的规则。一旦训练集覆盖了足够多的形态变化模型的泛化能力远好于手工特征。1.3 为什么最终落在YOLOv11上当时我拿了同一份焊接缺陷数据对比YOLOv8s和YOLOv11s同样训练300轮v11在焊接数据上mAP50大概高2到3个点单张640x640推理时间在同一张卡上几乎持平。这个差距对精度敏感的工业场景挺关键所以最终选了v11。YOLOv11在结构上换了C3k2模块和C2PSA注意力机制C2PSA尤其有用——它让模型对全局上下文的感知更强。焊接缺陷里像咬边、未熔合这类区域性强、局部信息不够的任务有没有全局上下文差别很大。模型需要知道这段沟槽是焊缝边缘的正常阴影还是焊穿母材形成的缺陷单看局部像素根本分不出来。另外ultralytics的生态对我这种要做部署的人来说太省事了。训练完直接model.export()导ONNX再转TensorRT同一套API从训练走到推理不需要在框架切换上浪费时间。2. 从零到一构建焊接缺陷数据集采集、标注与样本规划2.1 图像采集环境与工件多样性数据是这套系统的真正护城河。模型结构再先进喂进去的图像质量不行训练结果一定拉胯。采集设备方面不建议用手机随手拍来堆训练集。手机拍摄的分辨率、白平衡、对焦不稳定角度和距离也控制不住模型会学到一堆跟缺陷无关的噪声。我这边用的是500万像素工业相机加8mm定焦镜头工作距离300到500毫米保证焊缝区域大约占画面三分之一。焊接缺陷本身尺寸不大焊缝不占主体的话气孔裂纹在整幅图里就变成几个像素了后面再怎么调参都救不回来。打光是比相机更关键的环节。我用低角度环形光比同轴光更合适——低角度光会让表面缺陷形成阴影本来对比度很低的咬边、裂纹在阴影作用下会变得清晰。不锈钢这类高反光工件建议在镜头前加偏振片前期把这个做了能省掉后面模型层面的一大堆麻烦。采集时不要只拍完美工件要刻意覆盖多样性不同母材材质、不同焊工手法、不同打磨状态、不同光线条件甚至同一个工件拍反光和不反光两个版本。我在项目中途加拍过一次反光样本直接让验证集的误检率降了三分之一。2.2 六类缺陷的标注规范与关键纠结点标注工具我用labelImg为主YOLO格式。也可以用X-AnyLabeling带SAM辅助分割但焊接缺陷这种小目标用分割再转框反而容易出错我更推荐直接画框。标注规范里最重要的原则就是一致性。我踩过最大的坑是不同批次标注员的框法不统一有的人把长裂纹标成一个大框有的人拆成三四段模型直接学糊涂了。整理一下我最终定下来的标注规范裂纹能拆则拆。一条长裂纹按形态拆成多段每段框的长度控制在120像素以内框要紧贴缺陷本身不要包进大量正常焊纹。气孔抓大放小。直径小于10像素的气孔不单独标否则模型会被噪声带偏。气孔密集时可以合并成大框。夹渣框住最暗或最亮的团块核心不要连周围过渡区一起标进去。未熔合沿着焊缝根部细长暗线标宁可窄一点也不要宽。咬边紧贴焊缝边缘的沟槽区域标不要顺手把焊缝阴影拉进框。焊瘤框住整个凸起外观边界可以适当外扩模型需要上下文来区分焊瘤和正常焊缝过渡。最好找熟悉焊接工艺的质检人员参与前两批标注审核把标准统一了再交给标注团队批量做。我后期统计过标注规范化前后模型mAP50差了将近10个点全是在数据环节丢掉的。2.3 样本数量规划与增强策略数量建议上每类缺陷至少300到500个标注实例。但现实中很多项目拿不到这么多缺陷样本尤其裂纹这类严重缺陷出现频率很低。如果达不到数量线优先保证类别均衡然后做过采样把少数类的图像在训练集里多复制几份而不是指望模型自己在不均衡数据里学会。数据增强方面除了YOLO默认的mosaic和随机翻转焊接图像要慎用HSV增强里的饱和度和色相抖动。焊接图像本身偏灰颜色信息本来就少饱和度抖动过强会把正常焊缝颜色扭曲成奇怪的样子模型学到的就是错误的颜色关联。我会把饱和度抖动调到0.1以下只保留少量亮度抖动。裂纹这种方向性强的缺陷增强时用小角度旋转比大角度旋转好。现实工件里裂纹不会出现90度翻转的形态你硬让它学模型就会在完全不可能的角度也检出裂纹反而增加误判。气孔多的小目标场景除了整体图训练我建议把密集气孔区域裁成512x512的patch单独训练一个模型最后和整图模型做结果融合。这个方法对密集小目标的召回提升非常明显。3. 环境配置与源码目录的避坑指南3.1 Anaconda里创建专用环境很多人在环境这步卡住其实是安装顺序的问题。用一个干净的conda环境装YOLOv11最稳的顺序是这样的conda create -n weld python3.11 -y conda activate weld pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install ultralytics先说为什么用Python 3.11新版PyTorch和ultralytics对3.11支持最稳没必要用老版本给自己找麻烦。cu121指的是CUDA 12.1版本如果本机驱动只支持CUDA 11.8把链接里的cu121换成cu118。这里有个关键点先装PyTorch再装ultralytics。如果你先装ultralyticspip会把CPU版的torch拉下来等你想用GPU的时候才发现白装了一遍。装完跑一条命令验证python -c import torch; print(torch.cuda.is_available())输出True再继续否则后面训练时会莫名卡在CPU上。3.2 项目源码的结构设计与权重文件放哪源代码拿到手后不要所有文件堆在一个目录里。我建议按这样组织weld-detect/ ├── data/ │ └── weld.yaml ├── datasets/weld/ │ ├── images/train/ │ ├── images/val/ │ ├── labels/train/ │ └── labels/val/ ├── weights/ │ ├── yolo11s.pt │ └── best.pt ├── train.py ├── predict.py └── export.py数据集的根目录和标注目录必须严格对应YOLO格式images和labels分别放train/val目录结构错了训练时一条数据都读不进来。data/weld.yaml里的路径建议用相对path字段不要写死绝对路径。这样换机器训练时不需要改配置path: datasets/weld train: images/train val: images/val nc: 6 names: [crack, porosity, slag_inclusion, incomplete_fusion, undercut, weld_overflow]权重文件统一放在weights目录。训练结束后的best.pt是从runs/detect/里复制过来的后面推理、导出、部署都引用这个固定路径避免每次翻目录找权重。项目从第一天起就纳入git管理。数据集的标注文件变更很频繁有版本控制才能回滚到某个效果好坏的标注版本。别问我为什么强调这个——我因为标注标准反复调整没有版本控制后来想找回第一次训练时用的标注版本花了整整一个下午。3.3 选哪个预训练权重n/s/m的取舍YOLOv11提供了n、s、m、l、x几个不同规模的权重文件焊接场景不是越大的模型越好要结合显存和部署目标来选。权重参数规模显存占用(640输入)推荐场景yolo11n约2.6M约2GB边缘设备、实时检测yolo11s约9.4M约4GB推荐性价比最高yolo11m约20M约7GB离线检测、精度优先我从yolo11s起步气孔这类小目标多且有更高精度要求时再上yolo11m。yolo11n在焊接缺陷上精度掉得比较多除非你要部署到Jetson这类低功耗设备否则不建议用。训练时直接拿yolo11s.pt当预训练权重加载这是迁移学习COCO数据集上学到的边缘、纹理、形状特征可以迁移到焊接缺陷上。千万别说数据集小就从随机权重开始训那样300轮根本收敛不了效果会差一大截。4. 训练调参、评估指标与缺陷漏检的修正4.1 训练命令与关键超参数的含义环境配好、数据目录准备好之后训练命令并不复杂yolo train modelweights/yolo11s.pt datadata/weld.yaml \ epochs300 imgsz640 batch16 device0 cos_lrTrue逐条解释每个参数的选择逻辑modelweights/yolo11s.pt加载预训练权重做迁移学习不是从零开始。epochs300工业小数据集300轮足够再多容易过拟合。我后来做过一组实验600轮相比300轮mAP50几乎没有提升只是把训练时间翻倍。imgsz640速度和精度的平衡点。气孔密集可以试960显存占用会翻倍小目标召回有提升但速度会降。batch16取决于显卡显存。至少8以上batch太小BN层的统计不稳定模型收敛会很难看。cos_lrTrue余弦退火学习率后期收敛更稳能避免在最优解附近震荡。device0指定第一块GPU多卡可以写device0,1。训练过程中可以盯着loss曲线判断方向。如果loss下降后突然反弹大概率是学习率过大或数据里有脏标注先检查这两点不要盲目调结构的钱。4.2 评估阶段应该盯住哪些指标训练完不要只看一个mAP就下结论。焊接质检场景我更关注recall而不是precision——漏检一个缺陷到产线上就是质量事故误检顶多多花几秒钟人工复核。所以评估阶段重点看三个东西首先是results.png里的mAP50曲线和recall曲线如果recall偏低说明模型把缺陷漏掉了需要回到数据层面解决。其次是混淆矩阵重点看裂纹有没有被漏到背景气孔有没有被错分成夹渣。这两类在视觉特征上确实有重叠但如果混淆严重说明训练样本里两者的区分度不够。最后是PR曲线。PR曲线右下角面积越大越好如果曲线在低recall区域就开始掉说明模型对某类缺陷的置信度普遍偏低部署时得把conf阈值调低来照顾召回。4.3 缺陷漏检的常见修正手段漏检最直接的干预是调整训练集构成。我之前遇到裂纹recall特别低的情况裂纹样本只有50个实例气孔有2000个模型天然倾向于学数量多的类别。解决方式是把裂纹样本在训练集里重复几份让模型在每次epoch里看到裂纹的频率大幅提升。不用改loss不用改网络就是过采样简单有效。另一种做法是课程学习。先用imgsz640训练到loss收敛再用imgsz960微调50轮。这个对气孔和裂纹这种小目标缺陷的提升非常明显因为更大的输入尺寸让小目标在特征图上的响应更清晰。如果验证集里反复出现同一类误检比如总把某个反光误判为夹渣先别急着加训练轮数把它当作数据采集问题来看。把误检图像收集回来看是光照问题还是标注问题回到采集端解决比在模型层面死磕有效得多。5. 推理输出、结果保存与产线部署三种落地方式5.1 推理脚本与结果保存的几种用法训练完成拿到best.pt推理就简单了。先给一个最常用的完整脚本from ultralytics import YOLO model YOLO(weights/best.pt) results model.predict( sourcetest_images, conf0.25, iou0.5, saveTrue, save_txtTrue, save_confTrue, line_width2 ) for r in results: print(r.path, len(r.boxes))几个参数说明conf0.25是置信度阈值工业场景要保证召回可以调到0.1saveTrue会把画了框的结果图存到runs/detect/predict/save_txtTrue会额外输出YOLO格式的标签文件save_confTrue让标签文件里带上置信度。保存的txt文件在runs/detect/predict/labels/每行格式是class_id x_center y_center width height conf。注意这里的坐标是归一化坐标转成绝对像素时乘图像的宽和高。如果要做质量追溯系统需要把这些txt解析后整理成CSV我的做法是单独写一个解析脚本直接读取labels目录下的所有txt按图像名关联。5.2 导出ONNX后的跨平台部署如果检测服务要脱离Python环境跑第一步就导出ONNXyolo export modelweights/best.pt formatonnx dynamicTrue imgsz640dynamicTrue导出动态输入尺寸方便接收不同大小的图像。导出后用onnxruntime做一个快速验证确认输出shape是[1, N, 6]或[1, N, 4类别数]的格式再决定是否往TensorRT转。TensorRT的engine文件绑定显卡型号和驱动版本换一台机器必须重新生成没有一劳永逸的engine文件。工程上线时我会写一个启动脚本第一次运行自动生成engine后面直接加载省得每次手动处理。这个细节看着小实际部署时能省掉不少运维沟通成本。5.3 用FastAPI做一个简单检测服务产线集成时通常需要一个HTTP接口。我分享一个用FastAPI封装的最简版本from fastapi import FastAPI, UploadFile from ultralytics import YOLO import cv2 import numpy as np app FastAPI() model YOLO(weights/best.pt) app.post(/detect) async def detect(file: UploadFile): data await file.read() img cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR) results model.predict(img, conf0.25)[0] boxes [box.xyxy[0].tolist() for box in results.boxes] return {count: len(boxes), boxes: boxes}这个接口的吞吐量取决于GPU性能和图像尺寸。我实测在RTX 3060上640输入大概能做到60到80毫秒一次推理完全能满足单工位流水线的实时质检需求。如果并发量上来可以结合队列或批处理但那是另一个话题了。6. 实测踩坑记录裂纹标注、小目标气孔与反光干扰6.1 裂纹标注方式对训练结果影响非常大这是整个项目里我踩得最深的一个坑单独拿出来讲。第一次训练时我让标注团队把一条长裂纹标成一个完整大框结果验证集mAP50只有0.4而且预测框总是把整条焊缝都框进去。仔细分析预测结果才发现问题模型学到的框本质上是标注框的分布标注框里如果有大量正常焊纹背景模型就会认为包含正常焊纹的背景区域也是目标特征的一部分。后来把裂纹按形态拆成多段标注每段框控制在缺陷本身mAP50直接提升到0.6以上。这个教训提示得很明确标注框含多少背景模型就会容忍多少背景所以框一定要紧贴缺陷。验证阶段我还用了错误可视化脚本把预测错误的图片和对应的标注框画在一起一眼就看出模型把整条焊缝当目标来框。这种可视化排查方法很值得养成习惯比单看指标更直观。6.2 气孔类小目标引发loss振荡气孔视觉上很清楚但训练时经常遇到loss波动剧烈的问题尤其是直径只有8到10像素的气孔。640输入下这类小目标在特征图里可能只剩一个点模型根本提取不到有效特征。我的解决路径是两步。第一步把imgsz从640提到960小目标在特征图上的响应强了很多漏检下降明显但显存占用接近翻倍训练速度也慢了。第二步是采集时把气孔密集区域裁成512的patch单独训练然后再和整图模型结果融合这样密集小目标的召回才真正稳下来。如果不想做两个模型也可以看SAHI切片推理本质上也是把图切成小图再分别推理但推理耗时增长明显产线实时场景需要权衡。6.3 反光与过曝干扰的处理不锈钢焊缝打磨后反光严重高光区域在图像上是一片死白模型经常把亮斑当成夹渣误检。模型层面能做的只是把曝光校正加进预处理流程但治标不治本。真正的解法在采集端。我在镜头前面加了偏振片同时把环形光源角度调低让缺陷形成稳定的阴影而不是镜面反射误检率显著下降。如果反光已经不可避免建模前一定要把同一工件的反光和不反光状态都拍进训练集模型才有机会学到光照不变性。这个坑给我们的通用教训是图像采集质量决定了模型表现的上限而后处理、调参只能在采集方案确定的框架内小幅优化。问题出现在源头时回源头解决永远是效率最高的。我对这套系统最大的体会是模型只占了三分之一的功夫另外三分之二是数据和部署过程中的细致活。如果来了一个新场景不要急着把网络换成更复杂的结构先拿10到20张代表性图像跑一遍标注规范确认你要教模型学什么这件事定义清楚了再开始训练。源代码、权重文件和使用说明只能帮你省掉搭框架的时间真正决定检测效果上下限的永远是现场采集的数据质量和标注一致性。这些小细节是跑完整个项目之后最想提醒后来人的。本文还有配套的精品资源点击获取