1. 工业缺陷检测的底层逻辑与方案选型
1.1 为什么工业缺陷检测和常规目标检测完全不是一回事
做过通用目标检测的人第一次接触工业缺陷检测,大概率会踩同一个坑:拿COCO预训练的YOLO权重直接fine-tune,结果mAP看着还行,一上产线漏检率飙到两位数。原因不复杂——工业缺陷和自然图像里的猫狗行人,在数据分布上几乎是两个物种。
工业缺陷的核心特征可以归纳为三点。第一,缺陷与背景的对比度极低。划痕、脏污、微小凹坑这类缺陷,灰度差异可能只有十几个像素值,在自然图像里这属于噪声级别。第二,缺陷形态高度随机且类间差异极小。同一类缺陷在不同光照、不同批次物料上的表现可能完全不同,而不同类缺陷(比如浅划痕和轻微脏污)在低分辨率下几乎无法区分。第三,正负样本极度不平衡。一条产线跑一天可能产出几万件良品,缺陷件只有个位数,这就是典型的小样本场景。
所以工业缺陷检测的方案选型,不能照搬通用检测的思路。我一般会先问三个问题:缺陷的最小尺寸在图像上占多少像素?缺陷样本能收集到多少张?产线允许的漏检率和过杀率分别是多少?这三个问题的答案直接决定了你是走监督检测路线、异常检测路线,还是两者结合。
1.2 小样本条件下YOLO与异常检测的取舍逻辑
小样本训练是工业缺陷检测绕不开的坎。很多工厂给你的缺陷样本可能只有几十张,甚至十几张。这种情况下,纯监督的YOLO训练几乎必然过拟合。我的经验是:当每类缺陷样本少于200张时,不要指望单靠YOLO解决问题,必须引入异常检测做兜底。
具体来说,方案选型可以按样本量分档:
| 每类缺陷样本量 | 推荐方案 | 理由 |
|---|---|---|
| 500张以上 | YOLOv8/v11监督训练为主 | 数据量足够,YOLO的检测精度和速度都有保障 |
| 100-500张 | YOLO + 强数据增强 + 预训练微调 | 需要靠增强和迁移学习弥补数据不足 |
| 20-100张 | 异常检测为主,YOLO辅助定位 | 监督信号太弱,异常检测的无监督特性更合适 |
| 20张以下 | 纯异常检测 + 传统图像处理 | 监督方法基本不可用 |
这里要特别说一句,异常检测算法(比如基于特征重建的PatchCore、基于蒸馏的STPM、基于归一化流的FastFlow)在工业场景里的价值被严重低估了。它们的核心优势是只需要良品样本就能训练,这对产线冷启动阶段极其友好。但异常检测的缺点是定位精度不如YOLO,而且对缺陷类型的区分能力弱。所以实际项目中,我通常会用异常检测做初筛,把可疑区域裁出来再送给YOLO做精细分类,形成两级流水线。
1.3 漏检控制的本质是一个概率游戏
漏检控制不是简单调个置信度阈值就完事。你得理解漏检是怎么产生的。一个缺陷从进入相机视野到最终被判定,中间要经过成像、预处理、特征提取、后处理四个环节,每个环节都可能把缺陷"吃掉"。
成像环节的漏检最致命也最容易被忽视。光照不均匀导致缺陷区域过曝或欠曝,缺陷在图像上根本不存在,后面算法再强也没用。我见过太多项目,算法调了两个月,最后发现是光源角度差了15度。预处理环节的漏检主要来自降噪和增强,过度降噪会把微小缺陷当噪声抹掉。特征提取环节的漏检和模型容量、感受野设计有关。后处理环节的漏检则主要是NMS阈值和置信度阈值设置不当。
所以漏检控制必须是一个全链路的事情,不能只盯着模型。我的做法是:在成像阶段用缺陷样本做一次成像质量评估,确保缺陷在图像上的信噪比达标;在模型阶段用高召回率的配置先跑一遍,统计漏检分布;在后处理阶段针对漏检样本反向调整阈值。这个流程后面会详细展开。
2. 小样本训练的核心细节与实操要点
2.1 数据增强不是越多越好,要针对缺陷特性设计
小样本训练里数据增强是标配,但工业缺陷的增强和自然图像完全不同。翻转、旋转、裁剪这套通用增强在工业场景里可能起反作用。比如划痕缺陷,你水平翻转一下,划痕方向变了,但产线上划痕方向是有物理意义的,增强后的样本反而引入了错误先验。
我常用的工业缺陷增强策略是这样的:
- 光照增强:模拟产线光照波动,用随机Gamma校正(0.7-1.3)和亮度抖动(±15%)。这个几乎对所有缺陷类型都有效,因为光照变化是产线最常见的干扰。
- 对比度增强:针对低对比度缺陷,用CLAHE或者随机对比度拉伸。注意不要用直方图均衡化,它会放大背景噪声。
- 噪声注入:加高斯噪声和椒盐噪声,模拟相机噪声和粉尘干扰。噪声强度要控制,加到缺陷刚好能被肉眼分辨的程度就行。
- 弹性形变:针对柔性材料表面的缺陷,用小幅度的弹性形变模拟物料形变。幅度控制在5%以内,太大就失真了。
- Mosaic和MixUp:这两个要慎用。Mosaic在小样本下容易把缺陷拼到不合理的位置,MixUp会让缺陷和背景的边界模糊。我的经验是Mosaic概率降到0.3以下,MixUp基本不用。
还有一个容易被忽视的点:增强后的样本要人工抽检。我见过增强脚本把缺陷旋转到图像边界外,标注框还在,训练出来的模型全是假阳性。每次改增强策略,至少抽100张增强后的图肉眼过一遍。
2.2 预训练权重的选择和微调策略
YOLO的预训练权重选择直接影响小样本训练的收敛速度和最终精度。COCO预训练权重是默认选项,但工业缺陷检测里,我更推荐用ImageNet预训练的主干网络加上随机初始化的检测头。原因在于COCO的检测头学的是自然物体的边界和语义,和工业缺陷的局部纹理特征差异太大,直接fine-tune检测头反而会引入负面迁移。
微调策略上,我一般分三步走:
- 冻结主干,只训检测头:前20个epoch冻结backbone,学习率设1e-3。这一步让检测头先适应缺陷的尺度分布。
- 解冻主干后半部分:接下来30个epoch解冻backbone的后两个stage,学习率降到1e-4。这一步让主干的高层特征向缺陷纹理靠拢。
- 全网络微调:最后20个epoch全网络解冻,学习率降到1e-5,配合余弦退火。这一步精细调整所有参数。
这个三步走策略在小样本下比直接全网络fine-tune稳定得多。我实测过,同样50张缺陷样本,三步走的mAP比直接fine-tune高8-12个点,而且训练曲线平滑很多,不容易崩。
2.3 损失函数的选择和调参
YOLO默认的损失函数是CIoU Loss加分类交叉熵加目标置信度损失。工业缺陷检测里,这个组合有两个问题:一是小目标缺陷的定位损失权重不够,二是正负样本不平衡导致分类损失被良品样本主导。
我的调整方案是:
- 定位损失换成WIoU或EIoU:WIoU的动态聚焦机制对小目标更友好,实测在缺陷尺寸小于32像素时,定位精度比CIoU高5%左右。
- 分类损失加Focal Loss:把gamma设成1.5-2.0,让模型更关注难分类的缺陷样本。注意gamma不要设太大,否则训练后期会震荡。
- 正负样本分配用Task-Aligned Assigner:YOLOv8默认就是这个,但小样本下可以把topk从10降到6,让每个目标匹配更少的正样本,减少过拟合。
还有一个技巧是标签平滑,把平滑系数设成0.05-0.1。工业缺陷的标注边界往往有几个人像素的模糊,标签平滑能缓解标注噪声带来的过拟合。
2.4 小样本训练的验证集划分陷阱
小样本场景下,验证集的划分方式对结果影响极大。我见过有人把同一张图增强后的不同版本分别放进训练集和验证集,结果验证mAP虚高,上线就崩。正确的做法是按原始图像划分,增强只在训练集内部做。如果缺陷样本来自不同批次或不同光照条件,验证集要覆盖所有批次,否则你评估的只是模型在特定条件下的表现。
另外,小样本下验证集不能太小。每类缺陷至少留5-10张原始图做验证,如果实在不够,就用交叉验证。5折交叉验证在小样本工业检测里是标配,虽然训练时间翻5倍,但评估结果可靠得多。
3. 漏检控制的全流程实操
3.1 成像阶段的漏检排查清单
漏检控制的起点是成像。我有一套固定的排查清单,每次新项目上线前必过一遍:
- 光源角度和均匀性:用白纸或匀光板拍一张,看灰度直方图是否集中。如果标准差超过15%,说明光照不均匀,需要调整光源角度或加漫射板。
- 缺陷信噪比:拿已知缺陷样本,在图像上量缺陷区域和背景区域的灰度差。差值小于10个灰度级的,基本可以判定成像不合格。
- 相机曝光和增益:曝光时间要保证缺陷不拖影,增益尽量设低减少噪声。如果产线速度是1m/s,缺陷最小尺寸0.1mm,曝光时间要小于100微秒。
- 镜头畸变:用棋盘格标定,畸变系数超过0.1的镜头直接换。畸变会导致边缘区域的缺陷定位偏移,后处理阶段很难补偿。
- 触发同步:编码器触发和相机曝光的同步误差要小于1个像素对应的位移。这个用示波器量一下触发信号和曝光信号的时序就能确认。
这套清单过完,成像阶段的漏检基本能排除80%。剩下的20%是偶发的,比如物料反光、粉尘遮挡,这些只能靠多帧融合或者定期清洁来缓解。
3.2 模型推理阶段的漏检控制参数
模型推理阶段控制漏检,核心是置信度阈值和NMS阈值的联合调优。这两个参数不是独立的,得一起调。
我的做法是:先用一个很低的置信度阈值(比如0.05)跑一遍验证集,把所有预测框都导出来,然后画PR曲线。在PR曲线上找到召回率98%对应的置信度阈值,这个阈值作为初始值。然后在这个阈值下看假阳性分布,如果假阳性集中在某些背景区域,就针对性加负样本重训;如果假阳性分散,就适当提高阈值。
NMS阈值对漏检的影响主要体现在重叠缺陷上。如果产线上有密集缺陷(比如PCB板上的多个焊点缺陷),NMS阈值设太高会把相邻缺陷框合并,导致漏检。我的经验是:密集缺陷场景NMS阈值设0.3-0.4,稀疏缺陷场景设0.5-0.6。如果缺陷重叠严重,可以考虑用Soft-NMS替代标准NMS。
还有一个容易被忽视的参数是推理分辨率。YOLO默认输入640x640,但如果你的缺陷在原始图像上只有十几个像素,缩放到640后可能只剩两三个像素,模型根本看不到。这种情况下要么提高输入分辨率到1280,要么用切图推理(把大图切成小块分别检测)。切图推理的代价是推理时间线性增加,但漏检率能降一个数量级。
3.3 后处理阶段的漏检补偿策略
后处理阶段是漏检控制的最后一道防线。我常用的补偿策略有三种:
多尺度推理融合。把同一张图缩放到不同尺度分别推理,然后把所有预测框做加权框融合(WBF)。这个方法对尺度敏感的缺陷特别有效,代价是推理时间翻倍。实际部署时可以用两个尺度,比如640和960,兼顾速度和召回。
时序滤波。如果产线是连续检测的,同一件产品可能被多帧拍到。把连续几帧的检测结果做投票,只有连续两帧以上都检出的缺陷才判定为真。这个方法能把偶发漏检降下来,但会引入延迟。适合对实时性要求不高的场景。
异常检测兜底。前面提到的异常检测模型在这里发挥作用。YOLO没检出的区域,用异常检测模型再过一遍,如果异常分数超过阈值就报警。这个方法能把漏检率压到极低,但过杀率会上升。实际项目中,我会根据产线允许的过杀率来调异常检测的阈值。
3.4 漏检根因分析的实操方法
漏检发生后,不能只调阈值,得做根因分析。我的流程是:
- 收集漏检样本:把产线上漏检的图全部存下来,至少收集20-30张。
- 可视化特征图:用Grad-CAM或者Eigen-CAM把模型关注区域画出来。如果模型关注区域和缺陷区域不重合,说明特征提取有问题,需要改网络结构或加数据。
- 检查标注质量:漏检样本的标注是不是准确?有没有漏标?我见过不少情况是训练集本身就漏标了,模型学了个寂寞。
- 对比训练集分布:漏检样本的成像条件(光照、角度、背景)和训练集差异大不大?如果差异大,说明训练集覆盖不够,需要补数据。
- 检查后处理:把漏检样本的原始预测框导出来,看是不是被NMS或者置信度阈值滤掉了。如果是,针对性调参。
这个流程走一遍,基本能定位到漏检的根本原因。最怕的是不分析直接调阈值,调来调去把过杀率调上去了,漏检还是没解决。
4. 常见问题与排查技巧实录
4.1 训练阶段的高频问题
BN层崩溃。小样本训练时batch size通常很小(可能只有4或8),BN层的统计量估计不准,训练到一半loss突然变NaN。解决方案有三个:一是改用GroupNorm或SyncBN;二是冻结BN层,用预训练权重的统计量;三是用梯度累积模拟大batch。我一般优先用梯度累积,把accumulate设成4-8,效果比改BN好。
混淆矩阵总和不唯一。这个问题通常出现在多标签或者标注格式不统一的时候。检查一下标注文件里有没有类别ID超出范围,或者同一张图里有没有重复标注。另外,YOLO的混淆矩阵是在置信度阈值和NMS之后统计的,如果阈值设得太低,同一个目标可能被统计多次。
训练loss震荡不收敛。小样本下学习率要设小,我一般从1e-4开始试,如果还震荡就降到5e-5。另外检查一下数据增强是不是太激进,特别是Mosaic和MixUp,小样本下这两个很容易让loss震荡。
验证集mAP远高于测试集。这是典型的过拟合或者数据泄漏。检查验证集和训练集有没有同源图像,增强后的图有没有跨集。另外看看验证集的成像条件和测试集是不是一致。
4.2 部署阶段的高频问题
推理速度不达标。YOLOv8在V100上跑640输入大概2-3ms,但加上预处理和后处理,端到端可能到10ms以上。优化方向:预处理用GPU加速(比如用CUDA的resize),后处理用C++实现,模型用TensorRT量化。INT8量化后速度能再快一倍,但精度会掉1-2个点,需要评估是否可接受。
不同批次物料表现差异大。这是工业场景的经典问题。解决方案是在线自适应:用产线前100件良品做一次快速微调,让模型适应当前批次的光照和物料特性。微调只更新检测头,学习率设1e-5,跑10个epoch就够。这个方法能把跨批次精度差异从10个点降到2个点以内。
小目标漏检严重。除了提高输入分辨率,还可以改检测头。YOLOv8的P3特征图 stride是8,对应最小检测尺寸大概是8x8像素。如果缺陷小于这个尺寸,需要加P2检测头(stride=4)。加P2头会增加计算量,但小目标召回能提升20%以上。
模型对某类缺陷完全无响应。先检查这类缺陷在训练集里有多少样本。如果少于20张,基本是样本太少。解决方案:要么补样本,要么用异常检测兜底,要么用少样本学习(比如基于CLIP的零样本检测)。不要指望调参能解决样本量的问题。
4.3 漏检与过杀的平衡技巧
漏检和过杀是一对矛盾。产线通常对漏检零容忍,但过杀率太高会影响产能。我的平衡策略是:
- 分级报警:把检测结果分成三级——高置信度缺陷直接报警,中置信度缺陷标记待复核,低置信度缺陷放行但记录。这样既保证漏检率低,又不会因为过杀停线太频繁。
- 动态阈值:根据产线当前状态动态调阈值。比如换批次时阈值调低(宁可过杀不可漏检),稳定运行后阈值调高(减少过杀)。
- 人工复核闭环:待复核的样本由人工判定后反馈给模型,每周做一次增量训练。这个闭环跑起来后,模型会越来越准,过杀率自然下降。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 训练loss变NaN | BN统计量不准 | 检查batch size和BN层 | 梯度累积或改GroupNorm |
| 验证mAP虚高 | 数据泄漏 | 检查训练验证集同源性 | 按原始图划分 |
| 小目标漏检 | 输入分辨率不足 | 量缺陷像素尺寸 | 提高分辨率或加P2头 |
| 跨批次精度下降 | 域偏移 | 对比不同批次图像分布 | 在线自适应微调 |
| 推理速度慢 | 预处理后处理瓶颈 | profile各阶段耗时 | TensorRT量化+GPU预处理 |
| 某类缺陷无响应 | 样本太少 | 统计各类样本量 | 补样本或异常检测兜底 |
| 混淆矩阵异常 | 标注格式错误 | 检查标注文件 | 统一标注格式 |
| 过杀率高 | 阈值过低 | 统计假阳性分布 | 分级报警+动态阈值 |
5. 从项目实战中沉淀的经验
5.1 数据比模型重要,成像比数据重要
做了这么多工业缺陷检测项目,我最大的体会是:算法能解决的问题其实很有限。一个项目能不能做成,70%取决于成像方案,20%取决于数据质量,10%才是模型和调参。我见过太多团队把精力全花在模型改进上,结果成像一塌糊涂,怎么调都达不到产线要求。
所以我的建议是:项目启动阶段,先花两周时间专门做成像验证。拿缺陷样本在产线环境下拍几百张图,评估缺陷的可辨识度。如果成像阶段缺陷都看不清,后面所有工作都是白费。成像方案定下来之后,再谈数据采集和模型选型。
5.2 小样本训练的核心是"借力"
小样本训练不是硬训,而是要善于借力。借什么力?借预训练模型的力,借异常检测的力,借传统图像处理的力。YOLO的预训练权重、ImageNet的主干、甚至CLIP的视觉编码器,都是可以借的力。异常检测在良品数据上训练,不需要缺陷样本,这也是借力。传统图像处理(比如边缘检测、形态学操作)在特定缺陷上可能比深度学习还稳,这同样是借力。
我做过一个项目,缺陷样本只有15张,纯YOLO训练mAP不到0.3。后来用PatchCore做异常检测初筛,再用YOLO做分类,最终漏检率控制在0.5%以下。这就是借力的价值。
5.3 漏检控制要建立闭环
漏检控制不是一次性的调参,而是一个持续闭环。产线每天产生的漏检样本要收集起来,每周做一次根因分析和增量训练。这个闭环跑起来后,模型会持续进化,漏检率会逐月下降。我负责的一个项目,上线时漏检率2%,跑了三个月闭环后降到0.3%。
闭环的关键是数据回流。产线上的检测结果、人工复核结果、漏检反馈,都要自动存到数据库里。然后写个脚本每周自动拉数据、做分析、生成报告。这个自动化流程建起来后,维护成本很低,但效果很显著。
5.4 最后分享几个实用小技巧
技巧一:训练前先用小样本过拟合测试。拿10张图训练100个epoch,看模型能不能把loss降到接近0。如果降不下去,说明网络结构或损失函数有问题,先解决这个再上全量数据。
技巧二:验证集里故意放几张"困难样本"(成像差、缺陷模糊的),专门用来监控模型的鲁棒性。如果困难样本的召回率下降,说明模型过拟合了。
技巧三:部署时留一个"影子模式",新模型和旧模型并行跑,对比检测结果。只有新模型在影子模式下跑一周且指标全面优于旧模型,才正式切换。这个习惯能避免很多上线事故。
技巧四:标注规范要写成文档,每个标注人员上岗前先标100张做一致性校验。标注不一致是工业检测里最隐蔽的坑,模型学了一堆矛盾信号,怎么调都上不去。
技巧五:如果产线允许,尽量用高分辨率相机加小视场。一个相机拍小视野,缺陷像素多,检测难度直线下降。多相机拼接虽然成本高,但比算法硬扛划算得多。