原文 第五讲曲面 Pattern 缺陷是怎么被测出来的——从模板落位到缺陷判定许多工业缺陷检测流程本质上仍然是以像素域异常响应为起点再将异常回溯到具体对象与局部结构上而这套曲面 Pattern 缺陷检测系统恰恰相反它以模板落位后的结构化测量关系为起点再由点级测量逐步生成最终缺陷。它的检测链条具有更强的前置条件模板必须先经过两层配准进入实测图像测量集必须先获得可靠落位后续缺陷判定才有意义。换句话说系统并不是先在整张图里生成异常响应再去解释异常属于什么字符、什么图样或什么局部结构恰恰相反它是先建立模板与实测对象之间的几何对应再沿已经落位的测量点逐点展开局部测量最后才把点级异常通过邻域一致性与结构聚并上升为可输出的缺陷。这件事非常关键。因为它意味着这套系统从一开始就不是一个无条件的全图异常检测流程而是一套建立在模板、配准与测量关系之上的结构化测量系统。到测量阶段系统真正操作的对象已经不再是未经组织的原始位图而是一个被几何关系约束过、被模板结构参数化过的局部测量空间。也正因为如此后续输出的缺陷结果并不是从整张图里“扫”出来的而是沿着已经成立的结构关系被逐步“测”出来的。前一讲我已经讲了两层配准、注册集和测量集的分工。到那一步为止系统其实只回答了一个问题模板落在哪里但“模板落在哪里”不等于“缺陷是什么”。真正的检测要从模板落位之后才开始。这一讲我想把这件事讲透主要说四个问题为什么缺陷检测不能脱离测量集单独谈系统到底在“测”什么为什么它不是沿整张图漫扫而是沿测量点逐点展开为什么这么多不同缺陷最后还能放进同一套测量框架里。一、为什么不能脱离测量集直接谈缺陷检测如果把问题理解得很浅最容易形成的印象就是系统面对一张图最后只要回答“有没有缺陷”就行。但对这套系统来说这种理解太粗了。因为它真正面对的并不是一张尚未组织的原始图像而是一个已经经过模板组织两层配准局部落位之后的结构化检测对象。也就是说系统不是先对整张图做全图异常扫描再回头解释这些异常到底属于什么字符、什么图样、什么局部结构。它的路径正好相反先有模板先有几何关系先有测量点然后才沿这些测量点去判断局部是否异常。从这个意义上说测量集并不是某种附属数据而更接近后续缺陷检测的工作坐标系。只有当测量点已经进入正确位置系统才知道应该在什么地方看应该沿着什么结构看某个局部偏差到底该怎么解释。一旦脱离了这一层很多原本可测的细微缺陷就会重新退化成位图层面的模糊差异。图 1测量层总流程图。模板与测量集落位之后系统沿测量点逐点展开局部测量并将点级异常进一步组织为最终缺陷输出。所以这里最重要的一句话其实是缺陷不是脱离结构关系直接从图里找出来的而是沿着已经落位的测量集被测出来的。二、系统到底在“测”什么很多时候一说“测量”大家脑子里会浮现出一种很模糊的印象好像就是“看看周围正不正常”。但在这套系统里测量不是这种抽象动作。它不是在“猜缺陷”而是在测一组明确的局部量。从工程上看这些量大致可以分成三类。1局部灰度与对比关系这一类主要对应色异常局部发白、发黑填充状态异常系统并不满足于看某个点是亮还是暗而是要看该点邻域的灰度区间对比关系局部投影结构是否与应有 Pattern 保持一致。换句话说它不是看“一个像素值”而是在看局部结构上的灰度关系。2局部宽度、断裂与连通状态这一类主要对应镭断局部缺口细微中断系统沿着测量点展开局部观察并不只是为了“看到某个点”而是为了进一步感知与该点相关的结构连续性是否还成立。这也是为什么这套系统能抓一些很细的 break。因为它关心的不是“图上某块是不是黑一点”而是这个本来应该连续的局部结构现在还连续吗3局部面积、残余与异常聚集这一类更接近多镭残胶局部残余区域异常填充它们往往不表现为单点灰度异常而表现为某种局部区域的宽度扩张面积残留异常堆积所以这一层“测量”从来都不是泛泛的它始终对应某类明确的局部几何量或灰度量而后续缺陷判定也正是建立在这些量之上。三、为什么系统不是沿整张图测而是沿测量点逐点展开这套系统最有特色的地方之一就是测量不是对整张图做盲目的密集搜索而是沿着已经落位的测量集逐点展开。这一点非常重要。因为一旦测量点已经通过配准进入了正确位置系统就不再需要在整张图里到处“猜”哪里值得看而是可以直接把注意力集中在那些本来就应该存在结构的位置上。换句话说后续测量不是在全图漫扫而是在一个已经被模板和配准缩小过组织过约束过的局部空间里进行。这样做的好处非常直接。第一对细微缺陷更敏感因为测量不是在无上下文的位图区域里比较亮暗而是在“本来应该有结构”的位置上比较结构偏差。这样一来非常小的缺口局部中断极细异常区域都会更容易被稳定地显现出来。第二对无关噪声更不敏感因为系统并没有把整张图都当成等价检测对象而是把注意力限制在已经落位的局部结构上。很多来自背景局部污染边缘偶然波动的干扰根本不会轻易进入最终判定链条。所以这套系统的检测并不是“看整张图哪里不对”而更接近于沿着一组已经落位的结构点逐点展开局部测量再把这些局部测量组织成最终缺陷。四、为什么这么多不同缺陷最后还能放进同一套测量框架从表面上看这套系统面对的缺陷类型很多镭断色异常多镭局部失配码数量异常等等它们看起来完全不像一回事似乎应该对应很多彼此独立的小算法。但如果从更深一层的机制看这些缺陷并不是若干套彼此孤立的逻辑而是被统一纳入了同一条主线测量集已经落位局部邻域被展开某种局部几何量或灰度量被测出点级异常被记录再通过邻域关系聚并为缺陷区域或缺陷类型。也就是说不同缺陷虽然“长得不一样”但它们在系统里进入检测链条的方式其实很相似都先表现为某些测量点上的局部异常再逐步从点级异常上升为最终可输出的缺陷结果。这件事非常关键。因为它说明这套系统并不是把每一类缺陷都单独写成一套完全不同的流程而是在一个统一的测量框架上允许不同类型的局部量去触发不同的异常解释。也正因为如此系统才没有退化成“缺陷类型越多逻辑越碎最后全是补丁和特例。”相反它始终保持了一条清楚的主线。五、从点级异常到最终缺陷为什么不是一个点异常就直接 NG测量点上的局部异常并不会立刻等价于最终缺陷。这是因为在真实现场里孤立的异常点可能来自局部波动偶然噪声边界不稳定局部污染如果系统只要某一个点异常就直接判 NG那么误报会非常高。所以这套系统真正的判定过程并不是点异常 缺陷而是更接近下面这条链某些测量点先表现出局部异常系统再观察这些异常点在邻域内是否形成足够稳定、足够密集的异常集合当这种集合达到一定结构条件后才进一步形成缺陷区域、缺陷类型和最终输出。这一步非常重要。因为它解释了为什么系统既能抓住很细微的缺陷又不会因为少数孤立噪声点就轻易乱报。说得更直白一点点级测量负责“发现异常苗头”后续聚并负责“把异常苗头解释成真正可输出的缺陷”。也正是在这一层系统才真正完成了从“局部测量”到“工业输出”的转换。图 2从点级异常到最终缺陷。系统不是看到单个异常点就立刻判 NG而是通过邻域聚并将局部异常点组织成最终可输出的缺陷区域。六、为什么这套系统能测到非常细微的缺陷如果只看最终结果很多人会把系统能抓到细微缺陷归功于某个特别强的分类器、某个很高深的特征或者某种特别神秘的阈值策略。但对这套系统来说更根本的原因并不在那里。它之所以能测到非常细微的缺陷首先是因为模板结构已经通过配准真正落入了实测图像其次是因为后续测量并不是在整张图里盲扫而是沿着这些已经落位的结构点逐点展开。也就是说系统始终是在“应该有结构的地方”测偏差而不是在无差别地扫整张图。为了让这一点更直观不妨把“模板已经真正落位”和“细微缺陷如何显现”放在同一张图里看。左侧给出的是中轴线配准后的现场效果图绿色线条并不是人工标注而是由现场软件依据模板结构在实测图像上自动生成的骨架也就是 XML 中skeleton在图像中的实际落位结果。它的意义不只是“看起来对齐了”而是说明后续测量所依赖的结构关系已经真正进入了实测对象。右侧则给出几类真实产线样本中的局部缺陷效果图包括镭断和多镭等典型情形。图中保留的是与缺陷相关的局部区域红色方框标示系统检测到的异常位置。这样并排来看这套系统之所以能测到非常细微的缺陷原因就会很清楚它不是先在整张图里盲目找异常而是在模板已经落位、骨架关系已经建立之后沿着这些结构去感知局部偏差。图 3左侧为配准后的中轴线覆盖效果右侧为真实产线样本中的局部缺陷检测结果。左绿色中轴线为配准后叠加到实测图像中的结构模板右红色方框标示系统检测到的局部缺陷。正因为如此它才能够对一些极其细小但真实的结构异常保持敏感。例如某个局部点缺失一段笔画中间断掉一个很小的方块某个局部邻域里出现轻微但真实的异常膨胀。如果只在原始位图层面去看这些现象很容易与噪声、局部亮度波动或成像不均匀混在一起但一旦放到已经落位的骨架和测量关系上它们就会变成更可解释、也更可测的局部结构偏差。七、为什么这套测量层本质上仍然是结构化测量而不是简单规则堆砌从表面上看这套系统当然有不少参数、阈值和局部判别逻辑。于是很容易有人觉得它最终不过是一套调参很多的规则系统。这个印象并不奇怪。因为如果只看配置文件里的参数名而不去看它们依附在哪一层机制上确实会觉得“规则很多”。但问题的关键不在于“有没有参数”而在于这些参数是不是悬空存在的。为了说明这一点不妨先看一小段经过简化后的参数组织方式[Path] XmlPath.\lab_config\AM\laserCarving_TCharge.xml [Param] ThresholdBlockSize... contAreaMin... contAreaMax... NeighbourSize... NgPointNumThres... CharPointNumThres... DiffThres... MatchingThres... IterCount... MaxPointDist... DistYThres... [Defect] detectType11 LightThres... DarkThres... GlobalColorThres... GumThres... DiaThres... ResidualAreaThres... ZeroDiaRate... detNormThres...如果只看这些名字确实会觉得参数不少。但稍微往下看一层就会发现它们并不是杂乱堆在一起的而是分属不同层级1模板入口与对象形成层XmlPath并不是一个普通路径项它实际上把当前这份INI直接连到了对应国别或产品面的XML模板上。也就是说这套系统一开始就不是“先有一堆阈值再想办法去适配对象”而是先由XML给出字符骨架、全局几何锚点、block组织和模板入口INI再去调节这一整条检测链如何工作。2前端提取与 block 形成层例如ThresholdBlockSize、contAreaMin、contAreaMax一类量控制的是局部二值化、轮廓筛选、膨胀与降噪等前处理过程。它们回答的不是“最后判什么 defect”而是“哪些区域有资格进入后续检测链”。3配准与结构落位层例如MatchingThres、IterCount、MaxPointDist、DistYThres、NeighbourSize等量控制的是模板匹配是否成立、点集对应范围有多宽、迭代配准做多少轮以及局部测量尺度取多大。它们首先服务的是“结构如何稳定落位”而不是“结果如何直接给出”。4局部测量对象层例如LightThres、DarkThres、GlobalColorThres、DiaThres、ResidualAreaThres、ZeroDiaRate、detNormThres分别对应局部灰度与对比关系、整体色异常、局部宽度或直径类量、残余区域以及整体失配程度等辅助量。5点级异常如何上升为最终缺陷例如NgPointNumThres以及更完整配置中出现的BreakPointNumThres、ColorDiffPointNumThres、LargeDiaPointNumThres、convergRadius一类量本质上都不是在定义单点异常本身而是在定义异常点在邻域内达到什么规模、什么密度之后才足以形成可输出的缺陷。所以从更本质的角度看这一层并不是简单规则堆砌而是一种建立在模板、配准、测量点和局部邻域之上的结构化测量系统。参数当然存在但它们不是主干主干始终是先把结构关系建立起来再让参数和规则落到已经成立的结构之上。八、这一讲的结尾缺陷不是“找出来”的而是“测出来”的到这里其实可以看清这套系统里的缺陷检测并不是直接从图像里“扫出来”的而是沿着已经落位的测量集被逐点测量、再逐步聚并出来的。所以这一讲最重要的结论其实可以压缩成一句话缺陷不是直接从整张图里找出来的而是沿着已经落位的测量集被测出来的。这也意味着系统真正的难点并不只是“有没有一个判定规则”而在于模板、配准、测量点、局部邻域和缺陷输出之间能否被组织成一条连贯的技术主线。下一讲我会继续沿着这里往下写这些已经形成的缺陷结果最终是如何进入并适应产线节拍、并行处理、多线程组织和工程实施流程的。