26  缺陷检测专题

检测篇的前三章交给了你三件工具:Blob 分析(章节 23)从二值图中分割并度量区域,轮廓分析(章节 24)把实际轮廓与理论轮廓逐点对账,形状特征则把”长什么样”压缩成可比较的数字。但它们回答的都是”这个东西是什么、有多大、偏了多少”——产线上最常见的问题却是另一个:“这个产品有没有不该有的东西?”污染、异物、划痕、缺口、毛刺……缺陷的形态枚举不完,无法为每一种写一个检测器。本章给出收束整个检测篇的范式缺陷(defect)就是对”正常”的偏离。问题于是被反转——与其定义千变万化的缺陷,不如先定义唯一的”正常”。沿着”正常从哪里来”这条线,工业缺陷检测分成三条路线:参考比对——用良品样本建立参考,逐像素比对(本章主角变量模型);规则判定——用几何规则描述合格条件,如”边缘平直度不超过 2 px”(边缘缺陷、轮廓缺陷检测);统计离群——不依赖外部参考,直接在图像内找统计上的异常区域。本章用一组真实工业样图贯穿实验:Smart3「划痕检测示例方案」中的 5 张 2448×2048 的 8 位灰度图(图 26.1),每张是一枚纤维滤片圆盘(盘面均灰度约 150、暗背景灰度约 80),盘上分布着真实的划痕,并各带一类真实缺陷——大块暗污染、亮异物、边缘缺口。正是这组”没有干净底图、只有真实零件”的样图,把变量模型在理想合成场景里学不到的几堂课逼了出来。

图 26.1: “划痕检测示例方案”中的一枚真实缺陷滤片(样图 002):纤维盘面布满真实划痕,左偏上有一处近背景灰度的大块暗污染(异物嵌入/缺料)。盘心亮、边缘有亮晕环,盘面经强度归一到均值 150。

26.1 变量模型:让样本定义正常

滤片检测的朴素做法是拿一张金样本(golden sample)图像与被测图像相减、对差值取阈值。它会立刻失败:盘面是随机纤维纹理,每一枚盘的纹理走向都不一样;即使两枚都是良品,逐像素相减也会在每根纤维、每道划痕处冒出”缺陷”。变量模型(variation model)的洞察是:正常不是一张图,而是一个带(band);带的宽度不该由工程师拍脑袋给定,而应由训练样本自己的变化来定

\(n\) 张良品训练图像,逐像素计算灰度均值 \(\mu(x,y)\) 与标准差 \(\sigma(x,y)\),则该像素的合格区间——容差带(tolerance band)——为

\[ \big[\,\mu - \max(a,\ k\sigma),\ \ \mu + \max(a,\ k\sigma)\,\big], \]

其中 \(a\) 是绝对阈值(absolute threshold),\(k\) 是方差阈值系数(variation threshold)。\(k\sigma\) 项让容差自适应每个像素的真实波动;\(a\) 则是地板——在 \(\sigma\) 接近零的区域,仅几张样本估出的 \(\sigma\) 本身就不可靠,绝对下限防止容差带塌缩成零宽、把纯噪声判成缺陷。检测时,被测像素落在带外即标记为缺陷像素。模型本体就是两张图:上限图与下限图。

这组真实样图把变量模型的前提条件直接逼到了墙角。课本里的变量模型有一个隐含假设:\(n\) 张良品图必须逐像素可重复——同一坐标在每张良品上看到的是同一处结构,差异只来自工艺波动(套印抖动、墨量、光照)。印刷标签满足这一点,松散的纤维滤片不满足:把 5 枚盘按重心配准(平移居中、强度归一)后训练 SDK 变量模型,纹理在像素级根本对不上,逐像素 \(\sigma\) 被纹理失配撑爆,结果对每一枚盘——包括最干净的金样本——都报出近千个纹理误检区域(小节 26.2 给出实测的 692–1459)。这是真实样图教的第一课:配准金样本的变量模型需要”可重复的外观”,纤维、织物、毛面这类非重复纹理它管不住

“可重复外观”是参考比对路线的隐形门槛。印刷、贴标、丝印、注塑件表面在配准后逐像素可重复,是变量模型的主场;而纤维纸、无纺布、拉丝金属、磨砂面是逐像素随机的,跨样本配准只会把纹理失配烘进容差带。判断一类表面能否用配准变量模型,先问一句:把两张良品配准相减,差值图是平的,还是布满纹理?

出路是把”正常从哪里来”换一个来源:不跨样本,而是在同一张图内找正常。对每一枚盘,它自己的盘面在大尺度上是缓变的(盘心亮、边缘晕、整体平场),局部异常才是缺陷。于是”正常模型” \(\mu\) 取该盘自身的大窗平滑背景(半径 150 px 的盘面掩膜盒均值),它抹掉划痕与污染、只保留缓变光照;容差带宽里的 \(\sigma\)金样本残差的鲁棒尺度 \(1.4826\cdot\mathrm{MAD}=8.69\)(盘面纤维纹理的正常噪声水平),地板 \(a=10\)。检测就落在残差 \(R=I-\mu\) 上:\(|R|>\max(a,k\sigma)\) 即缺陷。这仍是变量模型同一套带数学,只是 \(\mu\) 来自空间平滑、\(\sigma\) 来自金样本纹理——它同时落在”参考比对”与”统计离群”两条路线的交集上。

一个工程巧思值得点出:盘面分割用 Otsu,暗污染的核心比阈值还暗,被划到背景、在盘面掩膜里留下一个洞。平滑背景因而在洞处取的是周围的亮纤维值(图 26.2 (b) 的均值图里污染已被”填亮”成干净盘面),于是残差在洞处强烈为负——污染孔洞反而被这套机制干净地暴露成一个大块负残差缺陷(图 26.2 (c) 的变差图)。

(a) 金样本盘(005,最干净)
(b) 自参照”正常”背景 \(\mu\)
(c) 变差/残差图 \(|R|\)
图 26.2: 自参照变量模型。(a) 金样本盘 005,盘面仅余细划痕,用来标定正常纹理噪声尺度 \(\sigma=8.69\);(b) 缺陷盘 002 的大窗平滑背景 \(\mu\)——划痕与污染被抹平,污染孔洞被周围亮纤维”填亮”成干净盘面,正是”正常”该有的样子;(c) 残差图 \(|R|\):盘面近乎全黑(正常),唯独左偏上的暗污染整团亮起、细划痕作为浅亮线浮现,亮边晕环也亮起——后者由 interiorR 圈外排除。

26.2 检出实验

先把配准多样本 SDK 变量模型失效的实测摆出来。取内部洁净的 003、004、005 三盘作良品参考(它们的真实缺陷在边缘,被内部圆形掩膜排除在外),按重心配准、强度归一后训练 SDK 变量模型(\(a=12\), \(k=3\)),再逐盘比对:

表 26.1: 配准多样本 SDK 变量模型在纤维表面上的输出:每一枚盘——连作训练用的金样本 005 自己——都被纹理失配刷出近千个误检区域,真缺陷淹没其中,不可用。
被测盘 001 002 003 004 005(金样本)
缺陷区域数 1017 1298 692 1459 1094

金样本 005 是模型的训练数据之一,却仍被报出 1094 个”缺陷”,这把问题钉死了:不是阈值没调好,而是逐像素可重复这一前提不成立。改用 小节 26.1 的自参照带后,检测立刻变得可读。在正常档(\(k=5\),带宽 \(\max(10,5\times8.69)\approx43\),最小连通域 30)下逐盘检测,按极性(暗缺陷 / 亮划痕)分别统计:

  • 002 暗污染:检出暗缺陷面积 9811 像素,最大连通域 9738 像素、平均对比 −101 灰度级——一块比盘面暗 100 级、近一万像素的污染团,位置 (504, 676)(图 26.3 (a))。这是全组最强、最无歧义的真缺陷。
  • 001 异物:一枚卷曲的亮纤维异物嵌在盘面上——亮部检出(最大连通域对比 +93 灰度级)、其暗影同时被检出(暗缺陷面积 2960、最大 2771、对比 −82),亮暗双极性都越带(图 26.3 (c))。
  • 005 金样本:暗缺陷面积仅 343 像素(无污染),但盘面真实划痕被检出 2934 亮像素(图 26.3 (b))——金样本”干净”只是相对的,它一样布满划痕。
  • 003 / 004:内部暗缺陷面积 480 / 440(轻微),其真正的缺陷是边缘缺口,落在内部检测圈之外,归规则路线处理(小节 26.4)。
(a) 002 暗污染
(b) 005 表面划痕
(c) 001 亮异物
图 26.3: 正常档(\(k=5\))的检出结果,暗缺陷反白、亮缺陷反黑叠加,最强区域加外接框。(a) 002 的暗污染整团(9738 像素、对比 −101)被干净圈出;(b) 005 盘面的真实划痕被检出为成串亮线——金样本一样有划痕;(c) 001 的卷曲亮异物及其暗影被双极性检出。

002 一例印证了自参照路线的稳健:污染团比盘面暗一百个灰度级,远离纹理噪声尾部,无论阈值松紧都稳稳越带。而 005 的划痕则演示了另一极——它们只比盘面亮十几到几十个灰度级,紧贴噪声尾部,是阈值整定真正的战场。

26.3 阈值的两难

正常档的 \(k=5\) 不是天上掉下来的。把同一组自参照模型与五盘扫过紧(\(k=3\),带宽≈26)、正常(\(k=5\),≈43)、松(\(k=8\),≈70)三档(地板 \(a=10\)、最小连通域 30),按极性分列的检出面积如下(手写确定性带,与 小节 26.5 的 SDK 输出交叉验证):

表 26.2: 三档阈值下的检出面积(像素,最小连通域 30)。暗缺陷(002 污染、001 异物)穿透所有阈值;亮划痕与颗粒随阈值快速衰减——金样本 005 的亮划痕从紧档 13384 一路掉到松档 236。
圆盘(缺陷) 暗缺陷 紧 正常 亮划痕 紧 正常
001 亮异物 5939 2960 1935 4984 864 179
002 暗污染 12065 9811 9133 4592 241 0
003 边缘缺口 5228 480 0 8729 1552 74
004 边缘缺口 4168 440 109 13345 1520 163
005 金样本 2204 343 35 13384 2934 236

表格里两类缺陷的不同命运,就是缺陷检测的根本两难。暗污染与异物穿透所有阈值:002 的暗缺陷从紧档 12065 到松档 9133 几乎不变,001 异物从 5939 到 1935 仍稳稳在检——它们对比足够强,是”必检”的真缺陷。划痕与颗粒则对阈值极度敏感:金样本 005 的亮检出从紧档 13384 像素塌到松档 236 像素,003、004 的亮划痕也成数量级地衰减。图 26.4 把 005 的两端并排:左图(紧档)盘面密布检出的细划痕与颗粒——若划痕属可接受的外观瑕疵,这些就是虚警(false alarm);右图(松档)画面几乎干净,只剩最深的几道划痕。

图 26.4: 阈值的两难(被测均为金样本盘 005)。左:紧档(\(k=3\))检出 13384 像素,盘面密布细划痕与纤维颗粒;右:松档(\(k=8\))只剩 236 像素的最深划痕。划痕是”瑕疵”还是”缺陷”由验收标准决定——而阈值正是这条线在灰度上的位置。

这正是真实样图比合成场景更诚实的地方:这里没有”干净良品”——每一枚盘都有划痕,“缺陷”与”瑕疵”的边界由验收标准而非物理决定。工程上的整定方法是两端夹逼:先在一组判定为”合格”的盘上收紧阈值,直到可接受瑕疵(浅划痕)恰好不报、虚警压到允许的 PPM 水平,这给出下界;再用已知必检的真实缺陷(污染、异物、缺口)验证检出,这给出上界。两界之间就是工作窗口——窗口若不存在(最浅的必检缺陷与可接受瑕疵在灰度上不可分),该换的不是阈值,而是成像方案:打光角度、波段或分辨率(章节 4 的暗场/明场选择往往就是为了拉开这个窗口)。

这与 章节 7 的教训同构:阈值的”自动”只是自动执行了选阈值的动作,不保证适应你的场景。变量模型的”自动容差”同样如此——\(k\sigma\) 自动适应的是金样本里有的纹理噪声,但”哪种偏离算缺陷”仍是一条要靠验收标准画的人为界线,不能因为”自动”就免检。

26.4 规则路线:边缘与轮廓缺陷

自参照变量模型擅长盘面内部的污染、异物、划痕,却管不到 003、004 那种边缘缺口——它们落在内部检测圈之外,本质是盘的轮廓偏离了应有的圆。当合格条件可以用几何规则写出来时(比如”边缘应是半径 760 的圆”),SciVision 提供两个规则路线的模块,此处做侦察性介绍(本章不演示)。

单边缘缺陷检测SingleEdgeDefectDetection,手册 8.11)面向”一条边应该平直/光滑”类的需求:沿一组搜索线分别提取标准边缘与实际边缘的点对,对每一对计算距离与角度偏差,超出阈值即判 NG。它本质上是卡尺式(章节 20)的逐线测量加判限,适合冲压件毛刺、刀口崩缺、密封条缺口这类单边局部异常——也正对应本组 003、004 滤片边缘的缺口:把盘的理论圆当标准边,实际边缘内凹超限处即缺口,不需要金样本。

轮廓缺陷检测ContourDefectDetection,手册 8.14)则把实际轮廓与模板轮廓整体对比,并在超差之外给出缺陷分型:断裂、凹陷、凸起、细碎毛刺。它还支持轮廓对(contour pair)之间的宽度缺陷检测,并能从模板生成涂胶轨迹——这组能力明显面向点胶/涂胶检测:胶路是否断胶(断裂)、堆胶(凸起)、缺胶(凹陷)、胶宽是否合格(轮廓对宽度)。它与 章节 24 中的轮廓对比(ContrastContour)同族:后者输出连续的偏差曲线,前者直接输出分型后的缺陷清单。

两条路线的分工可以一句话记住:有几何先验、能写出规则,用规则路线;有可重复样本、写不出规则,用变量模型。盘面纤维纹理的”正常”无法用几条几何约束描述,也无法跨样本配准复现,只能靠单图自参照统计;反过来,盘的边缘”应为半径 760 的圆”是一条干净的规则,没必要为它训练模型。

26.5 SciVision 实现

变量模型由 SCIMV::SciSvVariationModel 提供,训练与比较各一个接口:

SCIMV::SciSvVariationModel vm;
SciImageArray trainImgs;          // 良品训练图(须逐像素可重复)
SciROIArray   maskArr;            // 逐图屏蔽区(GenCircle 圈出盘内)
SciROI        trainRoi;           // 训练区域
SciImageArray model;              // 输出:[0]上限 8U [1]下限 8U [2]保留 [3]均值 32F
long rc = vm.TrainModel(trainImgs, maskArr, trainRoi,
                        /*absThreshold*/ 12.0f, /*varThreshold*/ 3.0f, &model);

SciImage result;  SciContourArray contours;
SciVarArray lengths;  SciPointArray centers;
SciROI roi;                       // UNDEF = 整图比较(不接受圆形 ROI,见下)
rc = vm.CompareModel(testImg, model, roi, /*minLength*/ 30, /*maxLength*/ 100000,
                     &result, &contours, &lengths, &centers);

absThresholdvarThreshold小节 26.1 公式中的 \(a\)\(k\)。本章对真实样图的关键发现是:配准多样本训练在纤维表面上不可用表 26.1,金样本自身报 1094 误检区域)。出路是把 CompareModel 当作一个通用的”带外像素→轮廓提取→长度过滤”引擎,喂入一个逐图自合成的自参照模型——model[3] 放该盘的平滑背景 \(\mu\)model[0]/[1]\(\mu\pm\max(a,k\sigma)\)model[2] 置零。这样既绕开了配准前提,又复用了 SDK 的轮廓与长度过滤。实测交叉验证(带宽 43、\(k=5\)):

表 26.3: SDK CompareModel 引擎(自参照合成模型)与手写带的逐盘交叉验证:缺陷像素总数一致(002:9926 对 10052),仅区域划分粒度因连通规则不同而异。
SDK 比较输出(盘内非零像素 / 区域数) 手写带(面积 / 区域数)
002 污染 9926 / 100 10052 / 9
001 异物 3666 / 46 3824 / 18
005 金样本 2768 / 184 3277 / 54

这一族接口在实测中暴露了若干必须如实记录的坑:

  • minLength 必须 ≥1:传 0 报错 120001014,尽管文档标称取值范围 [0, 100000]。
  • maxLength 必须 ≤100000:传 1000000 报错 120001015(与”长度过滤上界”的直觉相悖,文档亦未注明)——本章实测新坑。
  • 四个输出参数都必须传实体:任何一个传 NULL 直接崩溃(0xC0000005),即使你不关心轮廓或中心。
  • CompareModel 不接受圆形 ROI:传 GenCircle 生成的 ROI 报 120001015(而 TrainModel 的 mask 接受圆形);比较只能用 UNDEF/矩形 ROI,盘内限定须自行用圆形掩膜后处理。
  • 配准多样本训练在非重复纹理上失效:见 表 26.1;变量模型的逐像素 \(\sigma\) 把跨样本纹理失配当成了”工艺波动”,金样本自身也被刷屏。

这些坑塑造了本章的实验方法论:阈值扫描与极性统计全部用手写的 \(\mu\pm\max(a,k\sigma)\) 模型(32 位浮点、完全确定),并以 SDK CompareModel 的输出交叉验证——002 污染 9926 对 10052、001 异物 3666 对 3824,缺陷像素总数一致,确认两者是同一数学。这延续了 章节 5 的黄金实验方法论:文档描述的是承诺,已知行为的对照实验验证的才是真相;当某种数据让商用库的某一档前提失效时,用自己写的数学本体当仲裁者。完整工程位于 code/defect_detection/,文件头保留了全部实测记录。

工业案例:把”金样本”误当万灵药

某无纺布滤材检测线照搬印刷检测的经验,想用配准变量模型做表面缺陷检测:采集二十张”良品”建模,逐像素均值方差建带,上线即虚警率 30% 以上,几乎每张都报满屏小区域。排查发现根因不在阈值、不在光照,而在滤材表面的纤维纹理逐张随机、配准后像素级对不上——变量模型把纹理失配当成了工艺波动,容差带被撑得要么处处虚警、要么放过真缺陷。最终方案是放弃跨样本配准,改用单图自参照:每张图与自身大窗平滑背景比对、容差带宽由本图纹理的鲁棒尺度定。教训:变量模型有一道隐形门槛——配准后逐像素可重复。印刷、贴标、丝印满足它;纤维、织物、磨砂、拉丝面不满足。上线前先做一次”两张良品配准相减”的体检,差值图布满纹理就别再指望配准金样本,换自参照或纹理统计的路子。

26.6 小结

  • 缺陷检测的范式是反向定义:缺陷形态枚举不完,可操作的定义是”对正常的偏离”——先定义正常,再量化偏离。正常可以来自配准良品(变量模型)、几何规则(边缘/轮廓缺陷)或单图内统计(自参照)。
  • 配准变量模型有一道隐形门槛:逐像素可重复。真实纤维滤片不满足——配准 5 盘训练,连金样本自身都被刷出 1094 个纹理误检区域。印刷类表面是它的主场,纤维/织物/磨砂面不是。
  • 出路是单图自参照带 \(|I-\mu|>\max(a,k\sigma)\)\(\mu\) 取本图大窗平滑背景、\(\sigma\) 取金样本残差鲁棒尺度(8.69)。它把污染孔洞(被 Otsu 划到背景、平滑背景填亮)干净地暴露为大块负残差——002 的污染团 9738 像素、对比 −101 灰度级。
  • 阈值靠两端夹逼整定:可接受瑕疵压虚警给下界(金样本划痕紧档 13384→松档 236),必检真缺陷验证检出给上界(污染穿透所有阈值)。真实样图里”缺陷”与”瑕疵”的界线由验收标准而非物理决定。
  • 商用库的每一档前提都要过黄金实验:SDK CompareModel 被复用为自参照检测引擎,与手写带交叉验证(9926 对 10052)才确认同一数学;实测还逼出 maxLength≤100000、圆形 ROI 被拒等新坑——文档是承诺,实验才是行为。

至此检测篇收束:Blob 分析给了”分割与度量”,轮廓分析给了”逐点对账”,形状特征给了”形状的语言”,本章把它们升华为”定义正常、检出偏离”的范式——并用一组真实滤片样图证明,范式落地时第一要紧的是问对”正常从哪里来”。纹理表面缺陷检测的方法图谱可参阅 Xie 的综述 (Xie 2008),其中以纹理分析为主线系统梳理了统计、结构、滤波与模型四类路线;纹理特征统计的经典出处仍是 Haralick 等人的 GLCM 论文 (Haralick, Shanmugam, 和 Dinstein 1973);本章未展开的频域(傅里叶)路线,Tsai 与 Hsieh 针对有向纹理的缺陷检测是一个干净的范例 (Tsai 和 Hsieh 1999)。更系统的工业缺陷检测工程讨论(含纹理表面与变差模型的扩展)可进一步阅读 Steger 等人的著作 (Steger, Ulrich, 和 Wiedemann 2018)