1. 工业缺陷检测为什么难:从产线现实说起
1.1 缺陷样本稀缺是常态,不是例外
做过工业质检项目的人都有一个共同体会:正常样本堆积如山,缺陷样本屈指可数。一条SMT贴片产线一天跑几万片板子,可能只挑出几十片有虚焊、立碑、偏移的次品;一个冲压车间一个月下来,划痕、凹坑、毛刺的样本加起来可能不到两百张。这不是数据采集不努力,而是良率本身就高——良率越高,缺陷越少,这是制造业的天然矛盾。
所以工业缺陷检测的核心矛盾从来不是"模型够不够大",而是在极小样本条件下,如何把漏检率压到产线能接受的水平。很多团队拿着COCO预训练的YOLO直接微调,结果验证集mAP看着还行,一上产线就疯狂漏检,原因就在这——验证集和真实产线的缺陷分布根本不是一回事。
这篇文章我想把整套流程拆开讲:从数据采集策略、小样本增强、模型选型与损失函数调整,到漏检控制的阈值策略和上线后的持续迭代。适合正在做工业视觉落地、被小样本和漏检折磨过的工程师,也适合刚接触YOLO系列想往工业方向走的朋友。
1.2 漏检的代价远高于误检
先明确一个工程判断:在工业场景里,漏检(把缺陷判成良品)和误检(把良品判成缺陷)的代价完全不对称。误检的后果是多了几个复检工位、多扔几片料,成本可控;漏检的后果是缺陷品流到下游甚至客户手里,轻则整批退货,重则质量事故。
这个不对称性直接决定了后面所有的技术选择:损失函数要加权、置信度阈值要压低、后处理要保守、评估指标要看Recall而不是只看mAP。我见过太多项目栽在"指标好看但漏检高"上,本质就是没有把业务代价翻译成技术目标。
提示:项目启动第一件事,不是选模型,而是和产线质量部门确认"可接受的漏检率上限"和"可接受的误检率上限",这两个数字才是你后面所有调参的锚点。
2. 小样本训练的整体思路拆解
2.1 三条技术路线怎么选
面对小样本,业界大致有三条路,我按适用场景排一下:
| 路线 | 核心做法 | 适用场景 | 数据需求 | 落地难度 |
|---|---|---|---|---|
| 迁移学习+强增强 | COCO/ImageNet预训练权重微调,配合Mosaic、MixUp等 | 缺陷形态相对固定、有几十到几百张标注 | 50~500张 | 低 |
| 异常检测(无监督) | 只学正常样本分布,偏离即异常 | 缺陷形态多变、无法穷举、正常样本充足 | 0张缺陷 | 中 |
| 合成数据+半监督 | 生成缺陷/伪标签自训练 | 缺陷可仿真、标注成本极高 | 少量+大量无标注 | 高 |
我的经验是:如果缺陷形态能枚举清楚(比如固定几种划痕、脏污、缺件),优先走迁移学习路线,YOLO系列是最稳的选择;如果缺陷是"说不清道不明"的随机异常(比如织物、纹理表面的随机瑕疵),异常检测算法更合适。两条路不是互斥的,很多项目最后是YOLO负责已知缺陷、异常检测兜底未知缺陷。
2.2 为什么优先选YOLO而不是两阶段检测器
在工业产线上,节拍就是生命。Faster R-CNN这类两阶段检测器精度可能略高,但推理速度往往只有YOLO的一半甚至更低。一条产线如果要求30FPS以上,两阶段基本没戏。YOLO从v5到v8、v11,单阶段架构在工业缺陷这种"目标小、类别少、背景相对固定"的场景里,性价比是最高的。
另外YOLO的生态成熟度是实打实的优势:导出ONNX、TensorRT加速、各种部署脚本一应俱全,工程落地成本低。你不需要为了几个点的精度去啃一个冷门框架的部署坑。
2.3 小样本下最该做的三件事
很多人一上来就想着改网络结构、加注意力模块,我觉得这是本末倒置。小样本场景下,数据侧的收益远大于模型侧。我通常按这个优先级来:
- 数据增强做到极致:Mosaic、MixUp、随机仿射、色彩抖动、Cutout,把几百张样本"撑"出上万张的多样性。
- 预训练权重选对:用大规模数据集预训练的权重,而不是从零训练。工业缺陷和自然图像有域差异,但底层特征(边缘、纹理)是通用的。
- 损失函数针对漏检调权:这是最容易被忽略、但对漏检控制最直接的一环,后面单独讲。
3. 数据采集与增强的实操细节
3.1 采集阶段就要为小样本做准备
采集不是"把相机架上去录一天"这么简单。我踩过的坑是:录了一堆正常样本,缺陷样本还是那几十张,而且高度相似。正确的做法是主动制造多样性:
- 多光照条件:同一缺陷在不同打光角度下表现完全不同,环形光、同轴光、条形光各采一遍。
- 多姿态:工件在传送带上的位置、角度是随机的,采集时要覆盖这些变化。
- 多批次:不同批次的原材料、不同模具的磨损状态,缺陷形态会有细微差异,尽量跨批次采集。
- 负样本也要采:容易和缺陷混淆的正常特征(比如正常纹理、反光点)要专门采集,这些是降低误检的关键。
注意:缺陷样本的标注一定要让懂工艺的人参与。我见过标注员把"正常的水痕"标成缺陷,模型学完之后在产线上疯狂误报,返工成本极高。
3.2 增强策略的参数怎么定
YOLO自带的增强里,Mosaic和MixUp对小样本帮助最大,但参数不能照搬默认值。我的经验配置:
# 数据增强关键参数(以YOLOv8为例) mosaic: 1.0 # 小样本建议开满,增加目标组合多样性 mixup: 0.15 # 别开太高,工业缺陷语义强,混太狠会失真 copy_paste: 0.3 # 缺陷样本少时,复制粘贴缺陷到正常图上很有效 degrees: 10.0 # 旋转角度,根据工件姿态变化范围定 translate: 0.1 # 平移 scale: 0.5 # 缩放,覆盖不同拍摄距离 hsv_h: 0.015 # 色调抖动,模拟光照变化 hsv_s: 0.7 # 饱和度 hsv_v: 0.4 # 明度,工业场景光照波动大,可以适当调高这里有个关键判断:工业缺陷的语义比自然图像更"硬"。一只猫旋转180度还是猫,但一个划痕旋转180度可能就不像划痕了。所以旋转、翻转类增强要克制,而光照、对比度类增强可以放开。copy_paste对小样本特别有用,把缺陷抠出来贴到不同的正常背景上,能快速扩充样本。
3.3 合成数据的边界在哪
合成数据(GAN生成、仿真渲染)能缓解样本不足,但我建议合成数据只用于预训练或增强,不要作为主力训练集。原因是合成数据和真实数据之间存在域间隙,模型容易学到合成数据的伪特征。我一般的做法是:合成数据先训一个基础模型,再用真实小样本微调,这样既利用了合成数据的量,又保证了真实域的适配。
4. 模型选型与损失函数调优
4.1 YOLO版本怎么选
现在主流是YOLOv8和YOLOv11,v5依然有大量存量项目。我的选型建议:
- 追求稳定和生态:YOLOv8,文档全、部署方案多、社区活跃。
- 追求精度和速度平衡:YOLOv11,在同等参数量下精度有提升。
- 老项目维护:YOLOv5,别轻易换,迁移成本不划算。
模型尺寸上,工业缺陷检测我通常从s或m起步。nano太小,小目标缺陷容易丢;l和x在小样本下容易过拟合,而且推理慢。具体选哪个,用你的验证集实测,别拍脑袋。
4.2 损失函数里藏着的漏检控制开关
这是全文我最想强调的部分。YOLO的损失一般由三部分组成:分类损失、定位损失(CIoU等)、置信度损失(BCE)。漏检高,往往是因为正样本的损失权重不够,模型倾向于把模糊目标判成背景。
几个可操作的调整方向:
第一,分类损失的类别权重。如果缺陷类别样本远少于正常类别,给缺陷类加权。YOLOv8里可以通过调整数据集采样或自定义损失实现。
第二,正负样本分配策略。YOLOv8用的TaskAlignedAssigner,对小目标不太友好。如果缺陷都是小目标,可以考虑调低topk或调整对齐度量,让更多小目标被分配为正样本。
第三,置信度损失的调节。漏检的本质是模型对真实缺陷的置信度打得太低。可以在损失里对正样本的置信度误差加大惩罚,逼模型提高对缺陷的响应。
# 概念示意:给正样本置信度损失加权(需在自定义损失中实现) # 假设 pred_conf 是预测置信度,target 是标签 pos_weight = 2.0 # 正样本权重,根据漏检情况调 bce = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([pos_weight])) conf_loss = bce(pred_conf, target)提示:加权是把双刃剑,正样本权重调太高会导致误检飙升。建议每次只调一个参数,在验证集上同时看Recall和Precision的曲线,找平衡点。
4.3 小目标缺陷的专门处理
工业缺陷很多是小目标——一个针尖大的虚焊、一条细如发丝的划痕。YOLO的P3特征图(stride 8)对小目标已经比较吃力,如果缺陷更小,要考虑:
- 提高输入分辨率:从640提到960甚至1280,小目标像素数翻倍,检测率明显提升,代价是推理变慢。
- 加P2检测头:stride 4的特征图,专门抓小目标,但计算量增加。
- 切片推理(SAHI):把大图切成小块分别检测再合并,适合超大分辨率图像里的小缺陷。
我实测下来,提高分辨率+切片推理的组合对小目标缺陷提升最明显,加P2检测头性价比一般,除非缺陷真的极小。
5. 漏检控制的全流程策略
5.1 从评估指标开始就盯住漏检
很多人评估只看mAP,这是漏检失控的根源。mAP是Precision和Recall的综合,一个高Precision低Recall的模型mAP可能也不难看,但漏检一堆。工业场景必须单独盯Recall,尤其是缺陷类的Recall。
我通常建一个评估表,按缺陷类型分别统计:
| 缺陷类型 | 样本数 | Recall | Precision | 漏检数 | 误检数 |
|---|---|---|---|---|---|
| 虚焊 | 45 | 0.978 | 0.912 | 1 | 4 |
| 划痕 | 38 | 0.921 | 0.876 | 3 | 5 |
| 缺件 | 22 | 1.000 | 0.957 | 0 | 1 |
这样一眼就能看出哪类缺陷漏检高,针对性处理。整体mAP会掩盖单类问题。
5.2 置信度阈值:漏检控制的第一道闸
推理时的置信度阈值直接决定漏检和误检的平衡。默认0.25对工业场景往往偏高,会把一些低置信度的真实缺陷滤掉。我的做法是:
- 在验证集上画出不同阈值下的Recall-Precision曲线。
- 找到Recall达到目标(比如0.99)时的最高阈值。
- 如果这个阈值下误检太多,再考虑用后处理或二级分类来压误检,而不是简单提高阈值。
注意:阈值不是一次定死的。产线换批次、换光照后,分布会漂移,阈值要定期复核。
5.3 多模型融合与异常检测兜底
单一YOLO模型很难覆盖所有缺陷。我的常用架构是YOLO负责已知缺陷 + 异常检测负责未知异常:
- YOLO检测已标注的几类缺陷,Recall拉满。
- 异常检测算法(如基于特征重建、基于嵌入距离的方法)学习正常样本分布,任何偏离正常分布的区域都报警。
- 两者结果做融合,任一报警即判缺陷。
这样即使出现训练时没见过的缺陷类型,异常检测也能兜住,大幅降低"未知缺陷漏检"的风险。代价是误检会上升,需要后处理平衡。
5.4 后处理里的漏检补救
推理后处理也有文章可做:
- 降低NMS的IoU阈值:重叠的缺陷框不要合并太狠,避免把相邻缺陷吞掉。
- 多尺度测试(TTA):同一张图用不同尺度推理再融合,能捞回一些漏检,代价是速度。
- 滑动窗口:对超大图,重叠切块推理,避免边缘缺陷被裁掉。
这些手段都会增加计算量,要根据产线节拍取舍。我一般先保证Recall,再优化速度。
6. 部署与持续迭代的实战经验
6.1 推理加速与精度不能两全
工业部署绕不开TensorRT。YOLO导出ONNX再转TensorRT,FP16精度下速度能翻倍,精度损失通常很小。但要注意:
- INT8量化要谨慎:工业缺陷目标小,INT8的量化误差可能让小目标直接消失,漏检飙升。除非做过充分的校准,否则优先FP16。
- 动态shape vs 静态shape:静态shape推理更快,但要求输入尺寸固定。如果产线图像尺寸统一,用静态shape。
- batch推理:多路相机可以batch一起推理,提高GPU利用率,但会增加延迟。
关于"T4上1080p 25帧能跑多少路YOLO"这类问题,没有标准答案,取决于模型尺寸、分辨率、是否TensorRT、FP16还是INT8。我的经验是:T4上YOLOv8s、640分辨率、FP16+TensorRT,单路大概能到100FPS以上,理论上能带4路25FPS,但要留余量给预处理和后处理,实际带3路比较稳。具体数字一定要自己实测。
6.2 上线后的数据回流闭环
模型上线不是终点。产线上的真实数据是最宝贵的训练资源,一定要建回流机制:
- 所有被判缺陷的图,人工复核后标注对错。
- 所有被判良品但后续发现问题的图(漏检案例),重点收集。
- 定期用新数据微调模型,尤其是漏检案例要加权。
我见过做得好的团队,每周回流一批数据,每月迭代一次模型,漏检率能持续下降。反之,模型上线后就不管了,几个月后分布漂移,漏检率悄悄回升。
6.3 常见问题速查
| 问题现象 | 可能原因 | 排查方向 |
|---|---|---|
| 验证集好,产线漏检高 | 域差异、分布漂移 | 检查产线图和训练图的光照、角度差异 |
| 小目标缺陷漏检 | 分辨率不足、P3特征图不够 | 提高输入分辨率、切片推理 |
| 某类缺陷漏检特别高 | 该类样本太少、损失权重低 | 补充样本、类别加权 |
| 误检突然增多 | 阈值过低、环境变化 | 复核阈值、检查光照和背景变化 |
| 推理速度不达标 | 模型太大、未加速 | 换小模型、TensorRT+FP16 |
| 模型对某批次失效 | 原材料或工艺变化 | 收集新批次数据微调 |
6.4 几个我踩过的坑
坑一:过度依赖mAP选模型。早期我用mAP选最佳权重,结果上线漏检高。后来改成用缺陷类Recall选模型,漏检明显改善。
坑二:增强开太猛。有一次Mosaic和MixUp都开很高,模型学得"花里胡哨",真实缺陷反而认不准。工业场景增强要克制,语义保真优先。
坑三:忽略标注质量。标注边界框松紧不一致,模型学到的定位标准就乱,小缺陷尤其明显。标注规范要统一,最好做标注一致性检查。
坑四:阈值一劳永逸。定了一次阈值就不管,结果换季后光照变了,漏检率上升。阈值要跟着数据分布走。
坑五:只测不监控。上线后没有监控漏检率,等客户投诉才发现问题。一定要建线上指标监控,Recall、误检率、各类缺陷分布都要盯。
7. 异常检测算法的补充视角
7.1 什么时候该上异常检测
YOLO是监督学习,前提是缺陷类型已知且标注充分。但工业现场经常遇到"缺陷无法穷举"的情况——比如表面瑕疵的形态千变万化,你永远不知道下一种长什么样。这时候异常检测算法(只学正常样本)就是必要的补充。
异常检测的核心思想是:正常样本的分布是收敛的,任何偏离这个分布的都算异常。常见做法有基于重建的(自编码器、GAN,重建误差大即异常)、基于特征的(预训练特征提取+分布建模,如PaDiM、PatchCore)、基于流的(Normalizing Flow)。
7.2 异常检测和YOLO怎么配合
我的实践是分层:
- 第一层YOLO:检测已知的、有明确标注的缺陷,Recall拉满。
- 第二层异常检测:对YOLO判为正常的区域,再过一遍异常检测,捞未知异常。
- 融合决策:两层任一报警即判缺陷,最终由人工或二级模型复核。
这样既保证了已知缺陷的检出,又对未知缺陷有兜底。代价是误检上升,所以第二层的阈值要调得保守一些,宁可多报也别漏。
7.3 异常检测的落地难点
异常检测听起来很美,落地有几个坑:
- 正常样本也要多样:只采一种光照、一个批次的正常样本,模型会把其他正常变化也当异常。正常样本的多样性比缺陷样本还重要。
- 阈值难定:异常分数没有天然的阈值,要靠验证集调,而验证集里往往没有足够的异常样本。
- 定位精度差:异常检测能告诉你"这里有异常",但边界往往不如YOLO精确,对需要精确测量的场景不够用。
所以我的建议是:异常检测作为兜底,不作为主力。主力还是YOLO,把已知缺陷做扎实。
8. 一套可复现的最小流程
把上面的东西串起来,给一套可以直接抄作业的流程:
- 数据准备:采集多光照、多姿态、多批次样本,缺陷样本尽量覆盖各种形态,正常样本要包含易混淆特征。标注由懂工艺的人复核。
- 增强配置:Mosaic开满,MixUp适度,copy_paste针对缺陷样本,光照类增强放开,几何类增强克制。
- 模型训练:YOLOv8s或v11s起步,用预训练权重,输入分辨率根据缺陷大小定(小缺陷上960或1280)。
- 损失调优:针对漏检高的类别加权,调整正负样本分配,正样本置信度损失适度加权。
- 评估:按缺陷类型分别统计Recall和Precision,用缺陷类Recall选最佳权重。
- 阈值确定:在验证集上找Recall达标时的最高阈值,误检用后处理压。
- 部署:TensorRT+FP16,静态shape,batch推理,实测节拍。
- 兜底:异常检测作为第二层,捞未知异常。
- 迭代:建数据回流闭环,定期用新数据微调,监控线上漏检率。
这套流程我在几个项目里跑下来,小样本(几百张)条件下,缺陷类Recall能稳定在0.97以上,误检率控制在可接受范围。当然具体数字因场景而异,关键是这套思路——数据优先、Recall导向、损失调权、异常兜底、持续迭代。
最后分享一个我个人的小习惯:每次调参前,先固定一个基线,只改一个变量,记录结果。工业项目最怕的就是"一顿操作猛如虎,回头不知道哪个改动起了作用"。把实验记录做扎实,比任何技巧都管用。