1. 工业缺陷检测的现状与核心痛点拆解
1.1 为什么通用目标检测模型在产线上经常“水土不服”
做过工业质检项目的人都有一个共同感受:拿开源数据集训出来的模型,在实验室里mAP能跑到0.85以上,一上产线就原形毕露。这不是模型本身的问题,而是工业场景和自然场景之间存在几道很难逾越的鸿沟。
第一道鸿沟是缺陷样本极度稀缺。一条正常运转的产线,良品率通常在95%以上,有的精密制造环节甚至达到99.5%。这意味着你蹲守一整天,可能只采集到几十张有缺陷的图片,其中某些缺陷类型可能只有个位数样本。拿这种数据去训YOLO,模型很快就会过拟合到那几个样本上,换一批产品就完全失效。
第二道鸿沟是缺陷形态的高度不确定性。划痕、凹坑、脏污、气泡、裂纹、色差——这些缺陷在图像上的表现千变万化。同一类缺陷在不同光照、不同角度、不同批次材料上的外观差异可能比不同类缺陷之间的差异还大。传统的数据增强手段(翻转、旋转、裁剪)在这种场景下能提供的帮助非常有限。
第三道鸿沟是漏检代价远高于误检。在工业质检中,漏掉一个缺陷意味着不良品流入下游甚至流向客户,可能引发批量召回、产线停线、客户投诉。而误检只是把良品判为不良,代价是复检人力。所以产线对漏检率的要求通常是零容忍或者接近零容忍,这就对模型的召回率提出了极高的要求。
第四道鸿沟是部署环境的算力约束。产线工控机通常不会配高端GPU,很多场景用的是边缘计算盒子或者带集显的工控机。你训出来的模型如果参数量太大、推理速度太慢,根本没法满足产线节拍要求。一条高速产线可能要求单张图片的推理时间控制在30ms以内,这对模型选型和优化提出了硬性约束。
1.2 小样本训练到底“小”到什么程度
很多人说自己是小样本训练,但“小”的定义差别很大。根据我在多个工业项目中的实际经验,可以大致分三档:
| 样本量级别 | 每类缺陷样本数 | 典型场景 | 可用策略 |
|---|---|---|---|
| 充裕 | 200+ | 成熟产线、缺陷频发 | 常规YOLO微调+数据增强 |
| 紧张 | 30-200 | 多数工业场景 | 迁移学习+强增强+注意力机制 |
| 极端稀缺 | 5-30 | 精密制造、新产线 | 少样本学习+异常检测+合成数据 |
| 近乎没有 | 0-5 | 新品导入、零缺陷产线 | 无监督异常检测为主 |
大部分工业项目落在“紧张”和“极端稀缺”这两档。这也是为什么单纯拿YOLO官方预训练模型直接fine-tune往往效果不理想——预训练模型学的是COCO数据集上80类的通用特征,和工业缺陷的纹理、边缘、颜色分布差异很大。
1.3 漏检控制的本质是什么
漏检控制的本质是一个阈值决策问题。模型输出的是每个预测框的置信度分数,你需要设定一个阈值来决定哪些框算缺陷、哪些算背景。阈值设高了,漏检增加;阈值设低了,误检爆炸。
但问题远不止调一个阈值这么简单。真正有效的漏检控制需要从三个层面同时入手:
- 数据层面:确保训练集中覆盖了足够多样的缺陷形态,让模型见过足够多的“坏样子”
- 模型层面:通过损失函数设计、注意力机制、多尺度特征融合等手段,提升模型对微小缺陷和低对比度缺陷的敏感度
- 后处理层面:通过合理的NMS策略、多模型集成、置信度校准等手段,在推理阶段进一步压低漏检
这三个层面缺一不可。只调阈值是最粗暴的做法,效果也最有限。
2. 小样本训练的核心策略与实操细节
2.1 迁移学习的正确打开方式
拿YOLO预训练模型做迁移学习是标准操作,但怎么“迁”很有讲究。我见过太多人直接把预训练权重加载进来,然后所有层一起训,结果模型在少量数据上迅速过拟合,验证集loss不降反升。
正确的做法是分层解冻+差异化学习率。YOLO的backbone(主干网络)负责提取通用特征(边缘、纹理、形状),这些特征在工业缺陷检测中同样适用,所以backbone的前几层应该冻结或者用极小的学习率。而neck和head部分负责任务特定的特征融合和预测,需要较大的学习率来适应新任务。
具体操作上,我通常这样设置:
# 以YOLOv8为例的分层学习率配置思路 # backbone前10层:冻结或lr=1e-5 # backbone后10层:lr=1e-4 # neck部分:lr=1e-3 # head部分:lr=1e-3 # 在配置文件中体现为不同的param_groups # 实际训练时先用小学习率warmup 3-5个epoch # 再进入正常训练实测下来,这种分层策略比统一学习率在50张训练样本的场景下,mAP能高出8-12个百分点。原因很简单:底层特征不需要大改,改了反而破坏预训练学到的通用表示;高层特征需要大幅调整来适应新任务。
另一个关键点是预训练模型的选择。YOLOv8在COCO上预训练的权重和YOLOv5的权重,在工业缺陷任务上的表现可能差很多。我的经验是:如果缺陷以纹理异常为主(如布匹瑕疵、金属表面划痕),选在ImageNet上预训练过的backbone效果更好;如果缺陷以形状异常为主(如零件缺失、装配错误),COCO预训练的检测头迁移效果更好。有条件的话,两种都试,用验证集说话。
2.2 数据增强:小样本场景下的“救命稻草”
小样本场景下,数据增强不是锦上添花,而是雪中送炭。但工业缺陷的数据增强和自然场景有本质区别——你不能随便翻转旋转,因为很多缺陷是有方向性的。
比如金属表面的划痕,水平划痕和垂直划痕在物理成因上可能完全不同,你把它旋转90度,模型学到的特征就乱了。再比如布匹的经纬向纹理,旋转之后纹理方向变了,缺陷的视觉表现也跟着变。
我通常把工业缺陷的数据增强分成两类:
几何增强(谨慎使用):
- 小角度旋转(±10度以内):适用于大多数场景
- 随机缩放(0.8-1.2倍):模拟不同工作距离
- 随机裁剪:模拟缺陷出现在图像不同位置
- 水平翻转:仅适用于对称性缺陷
像素级增强(放心使用):
- 亮度/对比度扰动:模拟光照变化
- 高斯噪声:模拟传感器噪声
- 高斯模糊:模拟失焦
- Cutout/Random Erasing:模拟遮挡
- MixUp/CutMix:在缺陷区域进行混合
其中CutMix和MixUp在小样本场景下效果特别明显。它们的核心思想是把两张图按一定比例混合,同时混合标签。这样做的妙处在于:模型不会只盯着那几个缺陷样本死记硬背,而是被迫学习更鲁棒的特征表示。我在一个只有30张缺陷样本的项目中,加入CutMix后召回率从72%提升到了86%。
还有一个容易被忽视的技巧是Mosaic增强。YOLOv5/v8默认开启的Mosaic把四张图拼成一张,这在小样本场景下相当于把batch size扩大了4倍,对BN层的统计量估计非常有帮助。但要注意,Mosaic会改变缺陷的尺度分布,如果产线上缺陷尺度比较固定,Mosaic可能带来负面影响。我的建议是:训练前期用Mosaic加速收敛,最后10-20个epoch关掉Mosaic,让模型在真实分布上做最后微调。
2.3 损失函数的选择与调参
YOLO的损失函数由三部分组成:分类损失、定位损失、置信度损失。在小样本工业缺陷检测中,这三部分的权重需要重新平衡。
默认配置下,分类损失和定位损失的权重是1:1左右。但在工业场景中,定位精度往往比分类精度更重要。一个缺陷被分错类(把划痕判成脏污)可能还能接受,但如果框的位置偏了,后续的尺寸测量、位置判定就全错了。所以我通常会把定位损失的权重调高,比如设为分类损失的1.5-2倍。
另一个关键点是Focal Loss的使用。工业场景中正负样本极度不平衡——一张200万像素的图片中,缺陷可能只占几百个像素。标准的BCE损失会被大量的背景样本主导,导致模型倾向于预测“无缺陷”。Focal Loss通过降低易分类样本的权重,让模型聚焦于难分类的样本(也就是那些模糊的、微小的缺陷),在漏检控制上效果显著。
具体参数上,Focal Loss的gamma值我一般设在1.5-2.0之间。gamma越大,对难样本的聚焦越强,但太大也会导致训练不稳定。alpha值(正样本权重)通常设在0.25-0.5之间,取决于正负样本比例。
还有一个实战技巧是标签平滑(Label Smoothing)。工业缺陷标注中,不同标注员对同一张图的标注可能有细微差异,标签平滑可以缓解这种标注噪声带来的影响。通常设0.05-0.1即可,太大反而会损害模型置信度。
2.4 注意力机制与特征融合的改进
小样本场景下,模型需要更高效地利用有限的数据。注意力机制可以让模型聚焦于缺陷区域,忽略无关背景,相当于变相增加了有效样本量。
在YOLO中嵌入注意力模块,我推荐几个经过实战验证的方案:
CBAM(Convolutional Block Attention Module):同时做通道注意力和空间注意力,计算量小,即插即用。在YOLOv8的neck部分每个C2f模块后加一个CBAM,mAP通常能提升2-4个点。
SE(Squeeze-and-Excitation):只做通道注意力,更轻量。适合算力受限的边缘设备。
ECA(Efficient Channel Attention):SE的改进版,用一维卷积代替全连接,参数更少。
但要注意,注意力模块不是越多越好。我试过在backbone每一层都加CBAM,结果推理速度降了40%,mAP只涨了1个点。合理的做法是在neck部分的关键位置加2-3个注意力模块即可。
另一个重要改进是多尺度特征融合。工业缺陷的尺度变化很大——有的缺陷只有几个像素,有的占半张图。YOLO默认的FPN+PAN结构已经做了多尺度融合,但在小样本场景下,可以进一步强化小目标检测分支。具体做法是增加一个更高分辨率的检测头(比如从P3扩展到P2),专门负责微小缺陷。代价是计算量增加,需要根据产线节拍权衡。
3. 漏检控制的全流程实操
3.1 数据层面的漏检控制
漏检控制的起点在数据,而不是模型。我见过太多团队把精力全花在调模型上,却忽视了数据本身的问题。
第一件事:确认标注质量。漏检的锅有时候真不能全让模型背。如果标注员在标注时漏标了某些缺陷,模型学到的就是“这些不是缺陷”,推理时自然也会漏掉。我的做法是:在训练前随机抽20%的图片做交叉复核,两个人独立标注同一张图,计算标注一致性。如果一致性低于90%,说明标注标准不清晰,需要重新对齐。
第二件事:分析缺陷的尺度分布。统计训练集中所有缺陷框的宽高分布,看看是否存在某些尺度区间的缺陷样本特别少。如果有,针对性地补充这类样本,或者在数据增强时重点增强这些尺度。
第三件事:难例挖掘。先用初始模型跑一遍训练集和验证集,找出那些模型置信度低但实际有缺陷的样本(假阴性),把这些难例加入训练集重新训练。这个迭代过程通常做2-3轮,召回率能有明显提升。
第四件事:合成缺陷数据。当真实缺陷样本实在不够时,可以考虑合成。方法包括:从正常样本中裁剪出缺陷区域,粘贴到其他正常样本上;用GAN生成缺陷图像;用传统图像处理模拟缺陷(如高斯模糊模拟失焦、形态学操作模拟划痕)。合成数据不能完全替代真实数据,但可以作为补充,提升模型的泛化能力。
3.2 模型层面的漏检控制
模型层面的漏检控制,核心思路是让模型对“疑似缺陷”更加敏感。
策略一:降低分类阈值,提高NMS阈值。这是最直接的方法。把置信度阈值从默认的0.25降到0.1,让更多候选框进入NMS。同时把NMS的IoU阈值从0.45提高到0.6,避免相邻的缺陷框被误删。代价是误检会增加,但后续可以通过复检环节过滤。
策略二:多模型集成。训练多个不同初始化、不同数据增强策略的模型,推理时取并集。比如模型A检测到的缺陷和模型B检测到的缺陷都保留,只有两个模型都认为不是缺陷的才丢弃。这种方法对漏检的抑制效果非常明显,但推理成本翻倍。适合对节拍要求不高的场景。
策略三:级联检测。第一级用高召回率的模型快速筛选出疑似缺陷区域,第二级用高精度的模型做精细分类和定位。第一级可以是一个轻量级的异常检测模型(如基于自编码器的重构误差),第二级是完整的YOLO检测器。这样既保证了召回率,又控制了计算量。
策略四:测试时增强(TTA)。推理时对同一张图做多种变换(翻转、多尺度),分别推理后融合结果。TTA通常能提升1-3个点的召回率,代价是推理时间增加数倍。适合离线抽检场景。
3.3 后处理层面的漏检控制
后处理是漏检控制的最后一道防线,也是最容易被忽视的环节。
置信度校准是第一步。YOLO输出的置信度分数并不直接等于缺陷存在的概率。你可以用Platt Scaling或Isotonic Regression在验证集上做校准,让置信度更准确地反映真实概率。校准后,你可以更放心地降低阈值,因为你知道0.3的置信度确实对应30%的缺陷概率。
NMS策略的调整也很关键。标准NMS会抑制IoU高的框,但如果两个缺陷靠得很近,标准NMS可能会误删其中一个。改用Soft-NMS或者Cluster-NMS可以缓解这个问题。Soft-NMS不是直接删除高IoU框,而是降低其置信度,给它们“申诉”的机会。
多尺度推理融合是另一个有效手段。把同一张图缩放到不同尺寸分别推理,然后把所有预测框合并再做NMS。小尺度推理擅长检测大缺陷,大尺度推理擅长检测小缺陷,融合后漏检率通常能降低2-5个百分点。
基于规则的过滤在工业场景中非常实用。比如你知道缺陷的最小面积是50像素,那么可以把面积小于50像素的预测框直接过滤掉,减少误检。反过来,如果你知道某个区域不可能有缺陷(如产品边缘的夹具区域),可以在这个区域屏蔽检测结果。
3.4 阈值调优的实操方法
阈值调优不是拍脑袋,而是一个系统性的过程。
首先,在验证集上跑一遍推理,收集所有预测框的置信度和对应的TP/FP/FN标签。然后,绘制P-R曲线,找到满足召回率要求的最低阈值。比如你要求召回率不低于98%,那就找到P-R曲线上召回率98%对应的置信度阈值。
但P-R曲线只考虑了单一阈值。实际产线中,你可能需要对不同缺陷类别设置不同阈值。比如划痕类缺陷漏检代价高,阈值设低一点;脏污类缺陷误检代价低,阈值可以设高一点。
更进一步,可以引入代价敏感学习。给不同缺陷类别赋予不同的漏检代价,在训练时通过加权损失让模型更关注高代价类别。这样模型输出的置信度本身就隐含了代价信息,阈值设置更简单。
我通常的做法是:先按类别分别调阈值,然后在整体验证集上做一次联合优化,确保整体漏检率满足要求的同时误检率可接受。这个过程可能需要迭代3-5轮,但值得花时间。
4. 完整实操流程与关键环节实现
4.1 环境搭建与工具选型
工业缺陷检测的工程环境,我推荐以下配置:
| 组件 | 推荐选择 | 理由 |
|---|---|---|
| 深度学习框架 | PyTorch 2.x | 生态完善,YOLO官方支持好 |
| 检测模型 | YOLOv8n/s | 小样本场景下小模型反而更稳 |
| 标注工具 | LabelImg/Labelme | 轻量,支持YOLO格式导出 |
| 训练平台 | 本地GPU或云GPU | 视数据隐私要求选择 |
| 部署框架 | ONNX Runtime/TensorRT | 推理加速明显 |
| 边缘设备 | Jetson系列/工控机 | 根据算力需求选择 |
模型选型上有个反直觉的经验:小样本场景下,小模型往往比大模型表现更好。YOLOv8n(nano)只有300万参数,YOLOv8x有6800万参数。在50张训练样本的场景下,v8x几乎必然过拟合,而v8n因为容量有限,反而能学到更泛化的特征。我做过对比实验,同样30张缺陷样本,v8n的验证集mAP比v8x高出15个点。
当然,如果样本量在200张以上,大模型的优势会逐渐体现。所以选型要看你的实际样本量。
4.2 数据准备与标注规范
数据准备阶段,我建议按以下流程走:
第一步:采集。尽量覆盖不同光照、不同批次、不同工位的样本。如果产线有多个相似工位,每个工位都要采。采集时注意保存原始图像,不要做任何预处理。
第二步:清洗。剔除模糊、过曝、欠曝、重复的图片。重复图片尤其要注意,如果训练集里有大量相似图片,模型会过拟合到这些特定样本上。
第三步:标注。标注规范要提前定好。缺陷的边界怎么定?是紧贴缺陷边缘还是留一点余量?不同标注员之间要统一。我的经验是:标注框比缺陷实际区域大10%-20%比较合适,给模型一点容错空间。
第四步:划分数据集。训练集:验证集:测试集 = 7:2:1。小样本场景下,验证集至少要有20张图,否则评估结果波动太大。如果样本实在少,可以用交叉验证。
第五步:格式转换。统一转成YOLO格式(txt文件,每行:类别 x_center y_center width height,归一化到0-1)。
4.3 训练配置与参数设置
以YOLOv8为例,小样本工业缺陷检测的训练配置我通常这样设:
# 训练超参数 epochs: 200 batch: 8 # 小样本场景batch不宜太大 imgsz: 640 workers: 4 device: 0 # 优化器 optimizer: AdamW lr0: 0.001 # 初始学习率 lrf: 0.01 # 最终学习率 = lr0 * lrf momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 5 # 损失权重 box: 7.5 # 定位损失权重,调高 cls: 0.5 # 分类损失权重 dfl: 1.5 # 分布焦点损失 # 数据增强 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 10.0 # 小角度旋转 translate: 0.1 scale: 0.5 shear: 2.0 perspective: 0.0 flipud: 0.0 # 工业场景通常不上下翻转 fliplr: 0.5 mosaic: 1.0 # 前期开启 mixup: 0.1 copy_paste: 0.1几个关键点说明:
- batch size不宜太大。小样本场景下,batch太大意味着每个epoch的迭代次数很少,BN层统计量估计不准。batch=8或16比较合适。
- 学习率要小。预训练模型已经学到了很好的特征,大学习率会破坏这些特征。lr0=0.001是安全起点。
- warmup很重要。前5个epoch用线性warmup,让模型慢慢适应新数据,避免一开始就震荡。
- Mosaic最后关掉。训练到150epoch后,把mosaic设为0,让模型在真实分布上做最后微调。
4.4 训练过程监控与早停策略
训练过程中要盯紧几个指标:
训练loss和验证loss的走势。如果训练loss持续下降但验证loss开始上升,说明过拟合了,该早停。小样本场景下,验证loss通常在第50-80epoch达到最低点。
mAP50和mAP50-95。mAP50看召回能力,mAP50-95看定位精度。工业场景中,mAP50更重要,因为漏检控制主要看召回。
每类的AP。如果某一类的AP特别低,说明这类缺陷的样本太少或者特征太难学,需要针对性补充数据或调整损失权重。
早停策略我通常设patience=30,即验证集mAP连续30个epoch不提升就停止。同时保存验证集mAP最高的那个checkpoint作为最终模型。
4.5 模型导出与部署优化
训练完成后,模型需要导出为推理格式。YOLOv8支持导出ONNX、TensorRT、OpenVINO等多种格式。
# 导出ONNX yolo export model=best.pt format=onnx opset=12 simplify=True # 导出TensorRT(需要GPU) yolo export model=best.pt format=engine half=True device=0部署时的关键优化点:
- FP16量化:推理速度提升30-50%,精度损失通常小于1个点
- INT8量化:速度再提升一倍,但需要校准数据集,精度损失可能到2-3个点
- 动态batch:如果产线节拍允许,攒几帧一起推理,吞吐量更高
- 预处理优化:把resize、归一化等操作放到GPU上做,减少CPU-GPU数据传输
在Jetson Orin上,YOLOv8s用TensorRT FP16推理,640x640输入,单帧耗时约8ms,完全满足大多数产线节拍要求。
5. 常见问题与排查技巧实录
5.1 训练不收敛或loss震荡
这是小样本训练最常见的问题。原因通常有几个:
学习率太大。小样本场景下,梯度估计的方差很大,大学习率会导致参数更新方向不稳定。把lr0降到0.0005甚至0.0001试试。
batch size太小。batch=2或4时,BN层的统计量估计极不准确,导致训练震荡。如果显存允许,尽量用batch>=8。如果显存不够,可以用梯度累积模拟大batch。
数据标注有问题。检查标注文件是否有越界坐标、类别编号错误、空标注文件等问题。我遇到过一次,标注文件里有个类别编号写成了99(实际只有3类),导致模型训练时直接报错。
预训练权重不匹配。如果自定义了模型结构(比如加了注意力模块),加载预训练权重时会有部分层匹配不上。检查日志中的“missing keys”和“unexpected keys”,确保关键层都加载了预训练权重。
5.2 验证集mAP很高但产线漏检严重
这是典型的分布偏移问题。验证集和产线的数据分布不一致,模型在验证集上表现好不代表产线上表现好。
排查方法:在产线上采集一批新数据,人工标注后作为测试集评估。如果测试集mAP远低于验证集,说明分布偏移严重。
解决方案:
- 把产线数据加入训练集重新训练
- 使用领域自适应技术(如风格迁移)对齐两个域的数据分布
- 在产线数据上做测试时增强(TTA)
5.3 小缺陷漏检严重
小缺陷漏检是工业质检的顽疾。原因通常是模型的下采样倍数太高,小缺陷在特征图上只剩几个像素甚至消失。
解决方案:
- 增加高分辨率检测头(P2层)
- 使用空洞卷积增大感受野而不降低分辨率
- 在训练时过采样包含小缺陷的图片
- 推理时用滑动窗口切图检测,把大图切成小图分别推理
我做过一个PCB缺陷检测项目,缺陷最小只有3x3像素。用640输入直接推理,漏检率40%以上。改成1280输入+滑动窗口后,漏检率降到5%以下。
5.4 误检太多导致复检人力爆炸
漏检控制做过头就是误检爆炸。产线上如果误检率太高,复检工人会疯掉。
控制误检的方法:
- 提高置信度阈值(但会牺牲召回)
- 加入负样本训练(把容易误检的正常区域作为负样本)
- 使用二级分类器对疑似缺陷做精细分类
- 基于规则的过滤(面积、长宽比、位置)
我的经验是:先保召回,再压误检。先把漏检率降到可接受范围,然后通过二级分类和规则过滤把误检压下来。不要一开始就追求低误检,那样会牺牲召回。
5.5 模型在不同批次材料上表现不稳定
工业场景中,不同批次的原材料可能有色差、纹理差异,导致模型表现波动。
解决方案:
- 训练时加入不同批次的样本
- 使用颜色归一化(如直方图均衡化)预处理
- 在模型中加入域适应层(如AdaBN)
- 对每个批次做在线微调(用少量该批次样本快速adapt)
5.6 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决方案 |
|---|---|---|---|
| 训练loss不降 | 学习率过大/标注错误 | 检查lr和标注文件 | 降lr,修正标注 |
| 验证loss上升 | 过拟合 | 看训练/验证loss曲线 | 早停,加正则化,增数据 |
| mAP高但漏检多 | 分布偏移 | 产线数据测试 | 加入产线数据训练 |
| 小缺陷漏检 | 分辨率不足 | 看缺陷像素尺寸 | 提高输入分辨率,加P2头 |
| 误检太多 | 阈值过低/负样本不足 | 看FP样本 | 提阈值,加负样本 |
| 推理速度慢 | 模型太大/未优化 | 测单帧耗时 | 换小模型,量化,TensorRT |
| 不同批次不稳定 | 域偏移 | 分批次评估 | 域适应,颜色归一化 |
| BN层崩溃 | batch太小 | 看batch size | 增大batch,梯度累积 |
6. 工业异常检测算法的补充思路
6.1 什么时候该用异常检测而不是目标检测
YOLO这类目标检测算法是有监督的,需要标注缺陷样本。但有些场景下,你根本不知道缺陷长什么样,或者缺陷形态太多无法穷举。这时候就该用无监督异常检测。
异常检测的核心思想是:只学习正常样本的分布,任何偏离这个分布的都判为异常。常用算法包括:
- 基于重构的方法:自编码器、VAE、GAN。学习正常样本的重构,重构误差大的判为异常。
- 基于密度估计的方法:高斯混合模型、核密度估计。估计正常样本的概率密度,低密度区域判为异常。
- 基于特征嵌入的方法:PatchCore、PaDiM。用预训练CNN提取正常样本的特征,构建特征记忆库,测试时计算最近邻距离。
异常检测的优势是不需要缺陷样本,劣势是无法分类缺陷类型,且对阈值敏感。实际项目中,我通常把异常检测作为第一级筛选,YOLO作为第二级确认。
6.2 异常检测与YOLO的融合方案
一个经过实战验证的融合方案是:
第一级:PatchCore异常检测。用正常样本训练,输出像素级的异常热力图。设定一个较低的阈值,确保高召回。
第二级:YOLO缺陷分类。对第一级检出的异常区域,裁剪出来送入YOLO做精细分类和定位。YOLO只需要在异常区域上推理,计算量大大降低。
第三级:规则后处理。结合产线知识做最终判定。比如连续多帧检测到同一位置异常才报警,避免偶发噪声。
这个方案的好处是:第一级保证了召回率(异常检测对未知缺陷也敏感),第二级保证了准确率(YOLO做精细分类),第三级保证了稳定性(规则过滤偶发误报)。
6.3 时间序列异常检测的启发
虽然图像缺陷检测和时间序列异常检测看起来是两回事,但底层思路有相通之处。时间序列异常检测中的一些技巧可以借鉴到图像领域:
- 滑动窗口:时间序列用滑动窗口检测局部异常,图像可以用滑动窗口切图检测局部缺陷
- 多尺度分析:时间序列在不同时间尺度上分析异常,图像可以在不同分辨率上检测缺陷
- 在线学习:时间序列模型持续更新以适应分布变化,图像模型也可以用产线数据做在线微调
这些跨领域的思路迁移,往往能带来意想不到的效果。
7. 一些踩坑后的个人体会
做工业缺陷检测这些年,踩过的坑比做过的项目还多。有几个体会特别深:
第一,数据质量决定上限,模型只是逼近上限。我见过太多团队花80%时间调模型,只花20%时间搞数据。正确的比例应该反过来。标注质量、样本多样性、难例覆盖,这些才是决定漏检率的关键。
第二,小样本场景下,简单方法往往比复杂方法有效。我试过各种花哨的少样本学习算法(原型网络、匹配网络、MAML),在工业场景下效果都不如老老实实做迁移学习+强数据增强。工业缺陷的特征相对固定,不需要那么复杂的元学习。
第三,漏检和误检的平衡是艺术,不是科学。理论上你可以画出P-R曲线找到最优阈值,但实际产线上,工人的接受度、复检成本、客户投诉风险,这些都无法量化到公式里。最终阈值往往是多方博弈的结果。
第四,部署不是终点,运维才是。模型上线只是开始。产线换批次、换材料、换光照,模型表现都会波动。建立一套监控和快速迭代机制,比一次性把模型调到完美更重要。
第五,不要迷信SOTA。最新的论文算法不一定适合你的场景。YOLOv8出来这么久了,在很多工业场景下依然是最稳的选择。稳定、可解释、易调试,这些工程属性比那零点几个点的mAP提升重要得多。
最后分享一个实用小技巧:在产线部署时,保留一个“影子模式”——模型正常推理但不实际控制产线,同时记录所有预测结果和人工复检结果。运行一周后,你就有了一份真实的产线分布数据,可以用来评估模型真实表现并做针对性优化。这个做法帮我避免了好几次“实验室完美、产线翻车”的尴尬。