☰
基于深度学习的焊接缺陷检测系统:从数据到YOLOv8部署全解析
2026/10/1 3:13:49 网站建设 项目流程

1. 传统焊缝质检的短板:从人工目检到深度学习这条路的必然性

我最早接触这个项目,是在一个焊接结构件工厂蹲点调研的时候。车间里质检师傅拿着手电筒和放大镜,对每一条焊缝逐段看,一天下来要看几百米焊缝,眼睛早就疲劳了。哪怕是有十年经验的老师傅,在不同批次的工件上判宽严尺度也很难完全一致——上午精力好的时候觉得裂纹可疑,下午疲惫了可能就放过去了。那个时候我就意识到,焊接缺陷检测系统如果还停留在传统图像处理的思路上,很难真正解决问题,必须上深度学习。

之所以这么判断,是因为传统视觉检测在焊缝场景里有几个绕不开的硬伤。

第一,缺陷定义不是简单的灰度阈值。气孔、夹渣、未熔合、裂纹、咬边、飞溅,它们在某些光照和成像角度下看起来和正常的焊纹非常接近。传统算法用固定阈值、边缘提取、形状匹配这套打法,只要换个工件批次、换种焊接手法、换条焊缝表面处理工艺,参数就得重调一遍。我见过很多项目死在“换一批工件就失灵”这个环节上。

第二,真实焊接现场的干扰太多了。弧光、烟尘、飞溅颗粒、工件表面的油污和锈迹,都会污染图像。传统特征工程在这种复杂背景下非常脆弱,依赖打光方案反复折腾,甚至要定制暗箱来隔绝环境光,部署成本高得离谱。

第三,缺陷的形态多样且尺度差异巨大。一条裂纹可能只有几个像素宽,但长度横跨几十个像素;气孔可能成片出现,也可能单个孤立;未熔合藏在焊缝边缘,对比度极低。传统算法对这类问题几乎只能靠堆规则,规则一旦多了,误报率就控制不住。

深度学习带来的变化是本质性的。它不靠人定义特征,而是从数据里自己学习“什么是缺陷”的边界。用卷积神经网络做目标检测,相当于让模型同时承担了特征提取和缺陷判别的任务,面对复杂背景和形态变化时,泛化能力远超手工特征方案。再加上推理框架的成熟,检测一张几百毫秒变成几十毫秒甚至更低,完全能满足产线节拍。

我记得项目立项时,客户给的关键指标是三条:检出率不低于95%,误报率低于5%,单张图检测时间不超过100毫秒。传统算法组折腾了两个月,检出率卡在80%上下,误报率却居高不下。后来切换到深度学习路线,两周内就把指标跑通了。这个对比让我在后续几乎所有检测类项目里,都会优先考虑深度学习方案。

这篇文章我把整套“基于深度学习的焊接缺陷检测系统”从数据、模型、代码到部署的经验拆开来讲,所有实现都是Python代码,模型以YOLOv8为基线。适合正在做工业视觉检测、想入坑深度学习落地的工程师,也适合刚学完Python基础、想找个完整项目练手的朋友。

2. 检测流程整体设计:从焊件图像输入到缺陷框输出的完整管线

很多人以为做个深度学习检测系统就是把图喂给模型再等结果,实际工程上远不是这么简单。整个流水线从图像采集、预处理、缺陷检测到结果后处理,每一环都会影响最终质量指标。我画过一张流程图,虽然最终文中不放图表,但核心链路就这么串起来:工业相机抓取焊件图像,经过图像预处理增强缺陷特征,输入检测模型输出缺陷类别和位置框,再由后处理规则过滤明显误检,最后把结构化结果推到产线的工控机界面上。每一步都有讲究。

2.1 系统模块划分与数据流向

先讲模块划分。一个能落地到车间的系统,通常由这几个部分构成:成像单元(相机、镜头、光源)、采集与通信模块(图像触发、传输)、预处理器(降噪、增强、缩放)、深度学习推理引擎(模型加载、前向推理)、后处理规则引擎(置信度过滤、尺寸校验、缺陷去重)、可视化与报警模块、数据存档模块。

逻辑上有个先后顺序:相机采集到的原始图不要直接进模型。工业现场图像往往伴随噪声和光照不均,我习惯先做一次快速预处理,把图像从采集分辨率缩放到模型输入尺度,顺便做一次直方图均衡或自适应增强,让缺陷区域更突出。这一步不要做太重,毕竟推理速度考核摆在面前,预处理耗时最好控制在几毫秒内。

另外强调一下触发方式。产线上的工件是动的,不能一直拍。常见方案是光电传感器触发相机,工件到位瞬间抓拍。如果工件太大需要分区域成像,还要配合运动控制平台做多工位拍摄。当初我们做大型结构件焊缝检测时,一条长焊缝需要分段拍十几张图,每张都带位置信息,检测结果再拼接回整条焊缝的坐标系里。这种情况要考虑图像拼接和重叠区域的缺陷去重,否则同一个缺陷被相邻两个画面拍到,会被统计成两个缺陷。

2.2 成像条件对缺陷可见性的决定性影响

成像质量决定了检测系统的天花板。模型再强,图里没有信息,也是白搭。焊接缺陷里,裂纹和未熔合对光照角度极其敏感,侧光、暗场、同轴光的效果差异非常大。常规做法是用条形光源从焊缝两侧打低角度光,让焊缝余高的凹凸在图像里形成明暗交替纹理,缺陷位置的特征会自然凸现出来。

有一个常见误区:一味追求亮度均匀。其实对焊缝检测来说,适度的方向性光照反而是好事,它能把浅表面缺陷的阴影结构凸显出来,帮助模型区分真实缺陷和油污脏点。相机选型上,工业面阵相机配远心镜头或者常规定焦镜头都能用,主要看视场和分辨率需求。举个例子,如果要识别的裂纹宽度低于0.2毫米,那么单个像素对应的物理尺寸最好不要超过0.1毫米,否则裂纹在图上只占一两个像素,模型再强也难稳定命中。

预处理环节里,我还会加一步对比度增强。OpenCV里一句cv2.createCLAHE就能实现限制对比度自适应直方图均衡,这对低对比度焊缝图像很有帮助。实测中这个操作对未熔合、细小裂纹的召回率提升最明显,代价只是每个像素几次运算,性价比很高。

预处理之后,图像进入模型推理。将焊接缺陷检测系统真正跑起来之前,我建议先把成像和预处理的基线定好,再做模型迭代。别一上来就调网络,成像不稳定会让实验全乱。

3. 焊接缺陷数据集的正确打开方式:数量少、类别不均衡时的处理策略

深度学习落地的核心瓶颈往往不在模型,而在数据。焊接缺陷图像有一个现实问题:真实产线上有缺陷的样本本来就不多,而且缺陷类别分布极不均衡——气孔最常见,裂纹很少见,未熔合中等频率。直接拿原始数据训练,模型大概率会牺牲掉少数类,因为少数类学不到足够的特征。

3.1 数据采集和标注的规范

先讲数据怎么来。通常有三个渠道:客户提供的真实缺陷工件图像、工厂历史质检存档、公共数据集。公共数据集方面,GDXray系列里有焊接缺陷的X光图像,做学术预研很有用,但和实际工厂的可见光成像差异很大,只能用来做可行性验证,不能直接当生产数据。

采集时记住一个原则:尽量覆盖工况多样性。不同母材材质、不同焊接工艺、不同焊工手法、不同光照条件都要覆盖。同一个缺陷在镜面反光面上和粗糙表面上的特征完全不同,如果只采集单一工况,模型拿到现场就会出现“训练测试指标很好、上线就崩”的窘境。

标注规范直接决定模型上限。我建议用矩形框还是多边形,取决于你要检测的缺陷形态。气孔、飞溅这类近圆形缺陷用矩形框就行,效率高;裂纹和未熔合这类细长、边界不规则的,用多边形标注能保留更多形状信息,虽然标注成本高一些,但对语义分割或带旋转框的检测器来说价值更大。标注时还要注意边界情况——贴着焊缝边缘的小飞溅,算不算缺陷?这需要焊接工艺人员参与制定标注细则,而不是让标注员自行判断。

3.2 数据增强怎么加才不过拟合

焊接缺陷数据少,数据增强是好刚就得用在刀刃上。我常用的增强组合包括:随机翻转、随机旋转、HSV扰动、亮度对比度扰动、高斯噪声、随机裁剪。具体用哪几种,取决于模型可能会遇到什么变化。

我得特别提醒一句:别把所有增强都堆上去。焊接缺陷是尺度敏感问题,过度的随机缩放会破坏缺陷的真实尺度比例,模型反而学不到准确的尺寸概念。我一般把缩放控制在±20%以内,旋转角度控制在±15度以内。还有一点要注意,像随机擦除这种增强,如果擦除区域正好落在气孔上,标注框还在但缺陷没了,会让模型学习到矛盾信号。这类增强用在焊接缺陷上需要格外谨慎。

3.3 类别不平衡的几条实用策略

不平衡问题的处理手段,按对模型影响从大到小排:调整损失权重、困难样本挖掘、过采样少数类、对多数类做降采样。对YOLO系列模型来说,最直接的是设置每个类别的损失权重或类别权重,让少数类在计算分类损失时贡献更大。

我自己的习惯是,先跑一轮基线训练,统计各类别Precision和Recall。召回率低的少数类别,用拼接和复制粘贴方式补充样本:把含有裂纹的小片段用不规则掩码贴到正常焊缝图上,同时把标注框跟着变换,这种合成手法在工业检测里非常实用,能让稀有缺陷样本数量翻几倍。至于数量特别少的类别,比如一共才几十个样本,不要硬放大,先把它们单独作为验证集,确认模型在这几类上的能力边界,而不是假装没看见。

数据阶段还有一个容易被忽视的操作:训练集和验证集一定要按工件ID切分,不能按图像切分。同一个工件的多张连续图像特征高度相似,如果一部分在训练集、一部分在验证集,验证结果会虚高,误导你做错误判断。这是工业检测项目里非常容易踩的数据泄漏陷阱。

4. 模型选型的真实考量:为什么我以YOLOv8为基线而不是其他网络

接下来是模型选型。这个环节我踩过不少坑,早期试过分类网络、语义分割网络、两阶段检测网络,最后稳定下来以YOLOv8作为基线。不是赶时髦,而是每一类方案都有明确的适用边界,得先搞清楚检测需求到底是什么。

4.1 三类主流方案的适用边界

把检测问题抽象成三种:第一种,只需要判断“这条焊缝有没有问题”,那是图像分类,用ResNet或MobileNet就能做,速度快但定位能力为零,后续没法引导修复;第二种,需要知道“缺陷在哪一片区域”,那是语义分割,用U-Net系列,像素级输出,适合缺陷区域不规则、边界模糊的场景,但工程上需要把分割结果转成缺陷坐标,流程较长;第三种,需要输出“缺陷是什么类别+外接框在哪”,那是目标检测,YOLO系列天然适合。

焊接缺陷检测最典型的落地需求是第三种:告诉工人或机械臂,这条焊缝在什么位置出现了什么类型的缺陷。目标检测直接输出类别和框,工业接口最友好。如果后续想做缺陷面积统计,再在检测框基础上接一个小的分割头就行,整体架构依然是检测主导。

4.2 从YOLOv5到v8,核心机制的变化与理解

YOLOv8相比v5主要变化在三点:换上了Anchor-Free的检测头,不再需要预设锚框,省去了聚类锚框的麻烦;C2f模块替代C3模块,在保持轻量的同时改善了梯度流动;解耦分类和回归头,分类分支和回归分支各自独立学习,收敛更稳。对焊接缺陷这种类别不多(通常4~6类)、目标密集的场景,这些改动让模型更容易聚焦在每个缺陷框上。

放一组我用YOLOv8n、YOLOv8s在自建焊接缺陷数据集上的对比数据(训练150轮,输入640分辨率,硬件为单张RTX 3060):

模型每秒处理帧数mAP@0.5模型大小适用场景
YOLOv8n约160帧0.89约6MB边缘盒子/在线检测
YOLOv8s约95帧0.93约22MB常规工控机部署
YOLOv8m约55帧0.94约50MB离线抽检/高精度要求
Faster R-CNN约15帧0.92约108MB不推荐,速度劣势明显

从实测角度看,YOLOv8s在这个任务上性价比最高。速度完全满足产线节拍,精度比n版本高出一截,模型体积在嵌入式设备上也放得下。如果你算力紧张,n版本配合TensorRT加速也能用,但小目标缺陷的精度要接受一定损失。

4.3 其他值得关注的模型

也要提一下RT-DETR和DINO这类基于Transformer的目标检测模型。它们在大尺度通用检测上表现很好,但在工业小目标缺陷检测上,端到端结构训练周期长、小目标精度优势不明显,而且要配合大算力。我的看法是:先把YOLO系列吃透,再根据问题特性决定是否升级。

从原理上讲,YOLO系列之所以能快速收敛并且在小目标检测上不拉胯,核心靠的是特征金字塔结构(FPN/PAN)。高层特征负责捕获全局语义,低层特征保留细节位置,多层融合后,模型能同时看得见小而细的裂纹和大而散的气孔群。理解这个机制,对后续调参和填坑非常关键。

5. Python实现要点拆解:数据加载、训练与推理的核心代码与参数含义

到了代码环节。项目整体围绕Python展开,环境上我推荐直接用ultralytics库,它封装了YOLOv8的完整训练、验证、导出流程,几行就能跑起来。但想用好它,必须搞清楚背后配置的含义,否则默认参数在工业数据上并不总是最优。

5.1 数据组织与配置文件

训练前先把数据组织成YOLO格式。目录结构如下:

dataset/ images/ train/ val/ labels/ train/ val/ data.yaml

每张图片对应一个同名txt标签文件,每行格式为:class_id x_center y_center width height,四个坐标都归一化到0~1之间。注意宽高是归一化比例不是像素值。这个格式踩坑的人很多,不少人直接填像素值,训练时模型直接不收敛。

data.yaml里的关键配置:

path: ./dataset train: images/train val: images/val names: 0: porosidad 1: crack 2: slag 3: lack_of_fusion 4: spatter

类别名称尽量用英文,中文命名在部分环境下会引起编码问题。

5.2 训练代码与关键参数解析

训练代码本质上很短,但每一行都要理解。

from ultralytics import YOLO model = YOLO("yolov8s.pt") # 加载预训练权重 results = model.train( data="dataset/data.yaml", epochs=150, imgsz=640, batch=16, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3, cos_lr=True, patience=20, device="0", workers=8, )

这里挑几个容易出问题的参数讲清楚。

lr0是初始学习率,0.01是YOLO官方默认,但它基于COCO类的大数据集。焊接缺陷数据量小,0.01经常导致震荡,我通常会降到0.005或0.003。判断标准很简单:如果前几个epoch的loss发散或剧烈震荡,先把lr调小一档再试。

cos_lr=True配合warmup_epochs使用。前3个epoch让学习率从很小的值慢慢升到目标值,避免刚开始权重剧烈波动。之后按余弦曲线衰减,后期收敛更稳。这个组合我基本固定不变,经验证对中小规模数据集效果比阶梯式衰减好得多。

patience=20是早停策略:连续20个epoch验证集mAP没有提升就停止训练。焊接数据量小,很容易过拟合,早停一定要开,否则150轮的训练后段几乎都在过拟合打转。

imgsz=640是输入分辨率。如果缺陷很小,比如细小裂纹,我会试1280。分辨率翻倍对小目标检出率提升明显,但显存和时间成本也翻几倍。先跑通640,再专项调小目标。

5.3 推理与可视化代码

训练完直接推理很简单,但工业部署要做更多处理。基础推理:

from ultralytics import YOLO model = YOLO("runs/detect/train/weights/best.pt") results = model.predict( source="image.jpg", conf=0.25, imgsz=640, device="0", save=True, )

conf阈值要按实际场景调,不是越高越好。焊接生产线上普遍存在飞溅颗粒,它们形状像缺陷但又不是缺陷,阈值调高了漏检真实缺陷,调低了误报满天飞。我建议分两步:训练时看各类别的置信度分布,把验证集上假阴性对应的置信度上限统计出来,选择一个能在“漏检”和“误报”之间平衡的阈值。这个数字不同项目差异很大,我在裂纹检测上用过0.15的阈值,因为裂纹和背景对比度太低,模型置信度普遍偏低;在气孔检测上用过0.4,因为气孔特征清晰,置信度很高。

后处理环节,我会再做几个过滤:缺陷框面积小于某个像素阈值的直接忽略(可能是噪声);同一缺陷跨多个框的做NMS去重;缺陷位置超出焊缝区域的过滤掉。这些规则看似简单,但能把误报率再压下去两三个百分点,在真实产线上非常值钱。

6. 训练实测中的隐蔽问题:loss不降、漏检小缺陷、误检飞溅的排查链路

这一章单独写排查链路,因为训练过程中遇到的问题远不比模型结构少。我把三种最典型的实际问题拿出来,按排查顺序展开,这样你们遇到类似情况也有章可循。

6.1 排查链路第一步:loss不降或震荡,先怀疑数据而非模型

有次训练焊瘤检测模型,loss在训练了一万多次迭代后还是在高位震荡,没有任何下降趋势。我第一反应是学习率太高,调低一轮之后改善不明显。接着把batch从16改成8,依然没用。一步步排查下去,最后发现问题出在标签文件上——训练集里有一部分图片是从视频抽帧得到的,抽帧之后缺陷发生了形变,原本标注的框位置和实际缺陷对不上了,模型一直在学习“既对又错”的目标,loss自然降不下去。

排查顺序按概率从高到低排:数据标注错误(约一半以上项目是这个原因)→ 学习率设置不合适 → 类别严重不均衡 → 模型结构输错参数 → 硬件精度问题。检查标注错误最简单的方法是随机抽50张训练集图片,把标注框画上去肉眼过一遍。不要嫌麻烦,这50张图能帮你发现绝大部分低级错误。

6.2 小缺陷漏检的专项优化过程

细裂纹和小气孔的漏检是我调得最久的问题。初期模型对常规缺陷的mAP已经有0.93了,但小缺陷召回率只有0.7左右。排查思路是:先确认是小目标比例太低,直接看训练集里缺陷框宽度小于图片宽度5%的目标占多少。统计下来只有8%,而大目标是45%。针对性操作分三路走:

第一路,把imgsz从640提到1024。这一步最立竿见影,小目标在放大后特征更明显,召回率直接提升了5个百分点。代价是显存占用翻倍,训练速度下降约一半。

第二路,调整数据增强策略的随机裁剪比例,增加局部放大样本。让模型在训练时更多看到“缺陷充满画面”的形态,这也是一种隐式的小目标增广。

第三路,调低分类置信度阈值并配合推理时的TTA(测试时增强)选项。虽然TTA让推理时间变长,但作为离线抽检工具精度提升很可观。

综合这三路操作后,小缺陷召回率从0.7提升到了0.84,虽然没到完美,但已经能满足客户给出的95%检出率考核标准。

6.3 误检飞溅:聚焦区分度不够还是后处理规则缺失

另一种高频问题是飞溅颗粒被模型识别成缺陷。飞溅在图像上和气孔非常相似:都是圆形、都带高光、都出现在焊缝附近。模型区分它们的难度相当高,有时候一张焊缝图上几十个飞溅,模型标出十几个“气孔”,误报率一下就被打爆了。

排查后发现,模型不是分不清,而是训练集里对“作为正常区域的飞溅”标注不充分。我们一开始只标注了需要管理的缺陷类别,没有把飞溅标注为独立类别。后来把飞溅也单独建类,标为spatter,模型学会区分之后,气孔的误报率大幅下降。这是很多新手都会踩的坑:检测系统不只是检测“坏的东西”,还要把“好的但长相可疑的东西”明确成类,给模型一个学习的抓手。

如果数据实在有限,不想新增类别,另一个补救方案是后处理加规则:飞溅缺陷通常尺寸小、形状接近正圆、且置信度集中在一个区间。统计这些特征,用决策规则把疑似飞溅的框过滤掉。这个方法的好处是不动模型,快速上线,但治理效果上限低,治标不治本,最终还是把飞溅样本扩充进训练集靠谱。

7. 部署落地经验:速度与精度的取舍以及成本控制

模型在显卡上跑得飞快,不代表现场能用。真正的部署要面对工控机的算力限制、产线的节拍约束、长期运行的稳定性要求。一开始就把部署纳入考虑,能省很多返工成本。

7.1 模型量化和导出

部署首选导出为ONNX再转TensorRT,比直接用PyTorch推理快好几倍。导出代码:

from ultralytics import YOLO model = YOLO("runs/detect/train/weights/best.pt") model.export(format="onnx", opset=12, simplify=True)

导出ONNX之后,在NVIDIA GPU的设备上进一步转TensorRT,并启用FP16精度。FP16能在精度损失很小(通常mAP掉0.3个百分点以内)的情况下把推理速度提升一倍以上。如果设备用的是CPU,ONNX Runtime配合OpenVINO也能跑,但速度会慢不少,需要严格控制输入分辨率。

一个实用的成本经验:如果现场只有CPU,把输入分辨率从640降到512,配合Intel OpenVINO,推理速度可以压到50毫秒左右。代价是对小缺陷的检出率明显下降。所以在部署前必须想清楚一个核心问题:这条产线要抓的最小缺陷是多大,由此反推需要的输入分辨率和推理框架,再反过来指导模型训练。

7.2 硬件选择与产线节拍的匹配

算力配置上,单张RTX 3060级别显卡跑YOLOv8s,单帧推理在10毫秒以下,加上预处理和后处理,整体能做到20到30毫秒一个周期。对大部分焊接产线来说,这已经绰绰有余。如果产线节拍是3秒一件工件,模型性能完全护得住,甚至可以用更小的n模型,把计算资源省下来给其他模块。

除了推理耗时,还要考虑系统的持续稳定运行。工业现场长期高温、粉尘、震动,工控机选型要留足余量,散热要好。软件层面要做异常保护:单张图推理超时自动跳过、模型加载失败自动回退旧版本、GPU显存泄漏定期重启推理进程。这些工程细节看着不起眼,但能避免很多半夜加班调系统的痛苦。

7.3 上线后的持续迭代机制

最后讲迭代。深度学习系统的上线不是终点,而是新的起点。现场生产过程中会源源不断地产生新的缺陷形态、新的干扰因素,模型要持续学习。

迭代机制值得认真搭建:产线收集被人工复核过的检测结果图片,按“确认缺陷”“确认误报”“确认漏检”三档分类归档,定期(建议每周或每两周)合并进训练集,重新微调模型。微调用的是小学习率,比如lr0=0.001,在原有权重基础上继续训练几十个epoch即可,不用重新训练。

还有一类容易被忽略的数据:现场测试时保存的中间结果图像。模型在某个工件上输出的缺陷框,哪怕最后判错了,也记录了当前工况下的图像特征。把这些数据回收回来标注归档,长期积累下来,系统对现场复杂工况的适应能力会越来越强。

我在实际项目中,就是靠着这套“边运行边积累、定期重训”的机制,把模型在上线初期关注的几个误报场景一个个压下去。焊接缺陷检测系统不是买来的模型,而是在现场长出来的模型,数据闭环的节奏决定了项目最终能做多稳。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询