工业质检首先要回答漏掉一个缺陷和误拦一个正常件各有什么代价。其次才是模型:缺陷样本是否足够,拍摄光照是否稳定,一件产品允许多少处理时间?本篇以金属表面缺陷检测为教学场景,按冷启动、检测、复核和产线监控组织方案,不把模型分数直接当成产线验收结果。
前置阅读:建议先读 目标检测 YOLO、异常检测实战、SAM 与开放词汇检测、模型压缩与部署。
先理解工业质检的三个特殊性
- 数据极度不平衡:良品率 99.9% 意味着 1000 件里 1 件缺陷——而且缺陷种类还会「上新」(没见过的缺陷类型)。这和 类别不平衡篇的场景同源但更极端。
- 指标的不对称性:漏检(缺陷流出)代价 >> 过杀(良品误判复判)。产线指标的设定逻辑:漏检率压到接近 0,过杀率控制在人工复检能消化的范围(<5%)——和「准确率最大化」完全不同的目标函数。
- 环境即敌人:车间光照变化、传送带抖动、工件位置偏差——实验室 99% 的模型上产线就废,一半功夫花在成像侧(光源、工装、触发)而不是模型侧。
冷启动:50 张缺陷样本怎么开局
缺陷样本攒不够是常态,我的三步冷启动:
第一步:成像标准化先行(比模型重要)。固定光源(同轴光/条形光消除反光)、固定工装定位、固定拍摄参数——成像一致性值 20 个点的模型提升。金属反光件尤其:换个光源角度,划痕从不可见变清晰可见。
第二步:异常检测打底(PatchCore 路线)。不需要缺陷样本——只用良品图片训练「正常长什么样」,推理时特征库比对找离群区域:
# PatchCore 概念流:用 anomalib 库几行跑通
from anomalib.models import Patchcore
from anomalib.data import Folder
datamodule = Folder(root="data/metal_parts",
normal_dir="good", # 只需要良品图
abnormal_dir="defect") # 缺陷图仅用于评估阈值
model = Patchcore(backbone="wide_resnet50_2")
# 训练 = 提取良品 patch 特征建记忆库,无梯度训练
PatchCore 类方法在「缺陷形态未知/多变」场景是工业界第一基线——不用标缺陷,良品图管够就行。
第三步:Grounded-SAM 预标注攒数据(SAM 篇的打法)。「scratch . dent . stain .」做文本提示自动预标缺陷框 → 人工修正(修正率 ~30%)→ 攒到 500+ 张标注后训练 YOLOv8 缺陷检测器,进入「监督模型 + 异常检测兜底」双轨阶段。
双轨架构:检测与兜底的配合
工件图像
├── YOLO 缺陷检测(已知缺陷类型,精确分类定位)
└── PatchCore 异常检测(未知缺陷兜底,只报「不正常」)
↓
任一路报警 → 缺陷件分流(NG 通道)+ 类型标签
为什么双轨:监督检测对「见过的缺陷」精度高,但新品缺陷(没见过的裂纹形态)会漏——异常检测对「任何不像良品的」敏感,正好补这个洞。双轨的代价是过杀率叠加,需要分别调阈值平衡。
产线指标:怎么和业务对齐
和工厂谈指标用他们的语言:
- 漏检率(逃逸率):缺陷件被判良品的比例——客户投诉的直接来源,目标趋近 0,用「缺陷样本集」测。
- 过杀率:良品被判 NG 的比例——对应人工复检工作量,目标 <5%,用「良品大样本」测。
- 节拍:单件处理时间(成像+推理+分拣动作)< 产线节拍(如 500ms)——决定了模型尺寸和硬件(模型压缩:TensorRT + FP16 是标配)。
阈值调优的具体做法:在验证集上扫描阈值,画出「漏检率-过杀率」的权衡曲线(类似 ROC),按业务可接受的过杀率选工作点——和 阈值调优的成本矩阵法一脉相承。
上线后的运营:质检模型是「养」出来的
- 误判回流:人工复检的结果(哪些 NG 是误判、哪些漏检被发现)每日回流,每月增量训练——这是模型适应「新缺陷类型」的生命线。
- 边界 case 库:收集「难判」样本建专库,每次模型更新必须在边界库上回归(防改进一边、退化另一边)。
- 环境监控:定期拍标准件验证成像稳定性——光源老化、镜头积灰会缓慢拉低模型表现,比模型本身更早出问题。
踩坑排查
| 现象 | 原因 | 解法 |
|---|---|---|
| 实验室指标好产线全废 | 光照/位置/分辨率分布差异 | 成像标准化;产线实拍数据训练 |
| 反光件划痕全漏 | 光源角度不对 | 换低角度环形光/同轴光,成像先行 |
| 新缺陷类型全漏检 | 监督模型只见旧缺陷 | 异常检测兜底轨 |
| 过杀率 20% 人工检不过来 | 阈值太激进 | 按权衡曲线重选工作点 |
| 模型上线后缓慢退化 | 光源老化/镜头脏 | 标准件日检 + 环境监控 |
| 小缺陷(<10px)漏检 | 输入分辨率不足 | 原图切 patch 检测;提高输入尺寸 |
练习
- 用 anomalib 在一个公开工业数据集(MVTec AD 的 metal_nut/screw 类)上跑 PatchCore,只用良品训练,报告 AUROC。
- 对比实验:同一数据集上 PatchCore(无缺陷训练)vs 用 50 张缺陷图训练的 YOLOv8——已知缺陷和未知缺陷各自的表现。
- 画「漏检率-过杀率」权衡曲线:扫 PatchCore 的阈值,按「过杀率 ≤5%」选工作点,报告此时的漏检率。
- 用 Grounded-SAM 对 30 张缺陷图自动预标注,统计人工修正率,估算标注成本节省比例。
面试常问
Q:工业质检为什么常用异常检测而不是监督分类? 三个结构性原因:缺陷样本稀缺(新品投产无历史积累)、缺陷类型开放(质检标准是「任何不正常」而非固定类别表)、漏检代价不对称(宁可错杀)。异常检测只需良品数据、对未知缺陷天然敏感——它和监督检测是互补而非替代:稳定量产后监督检测提供「缺陷分类」(什么类型的缺陷,指导工艺改进),异常检测继续兜底未知。
Q:小样本缺陷检测有哪些技术路线? ① 异常检测(零缺陷样本);② 预训练 + 微调(ImageNet 主干 + 小数据微调检测头);③ 数据合成(缺陷粘贴法:把缺陷纹理贴到良品图上,CutPaste 思想;或扩散模型生成缺陷图);④ 基础模型预标注(Grounded-SAM)攒数据;⑤ Few-shot 方法( prototypical network 系)。实战常组合:异常检测冷启动 → 合成数据增强 → 监督模型接管 → 双轨运行。
Q:质检系统的阈值怎么和业务对齐? 把误判换算成钱:漏检一件 = 客户投诉/召回成本(业务估),过杀一件 = 复检人工成本 × 复检量。阈值选在「总期望成本最小」处——通常因为漏检成本 >> 过杀成本,工作点会压到极低漏检率。关键是让业务方给出两个成本的量级,而不是让算法猜「准确率」。
Q:成像侧为什么比模型侧更重要? 「垃圾进垃圾出」的工业版:同一缺陷在不同光照下可以从「明显」变「不可见」——成像差异造成的信息损失,任何模型都补不回来。工业视觉的常识分配:70% 精力在成像方案(光源选型、视场、分辨率、触发同步)、30% 在算法。评估项目可行性先做「成像实验」:目标缺陷在所选光源下人眼可见吗?人眼都看不见,模型更看不见。
Q:MVTec AD 之外,工业质检的真实挑战? 学术数据集(MVTec)是「干净棚拍」,真实产线多一层:节拍约束(实时性)、环境漂移(光照温度振动)、缺陷演化(新类型持续出现)、判标模糊(「这条划痕算不算缺陷」的判定标准本身有主观性——标注一致性都是问题)。最后一个最隐蔽:先和质检员对齐「判定标准文档」,否则标注数据本身就是噪声。
相关阅读
- 异常检测实战——PatchCore 的思想根源
- 目标检测实战:YOLO——监督检测轨
- SAM 与开放词汇检测——冷启动标注加速器
- 模型评估指标与类别不平衡——阈值与权衡曲线
- 模型压缩与部署——节拍达标的工程手段
工业质检教会我的最重要一课:AI 项目里「模型」只是系统的一个零件——成像、机械、流程、判定标准、人员协作,每个零件都能让最好的模型失效。全栈思维在这个场景不是加分项,是生死线。
💬 评论
这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。