The Nature of Curved-Surface Pattern Inspection: Structural Normalization and Defect Measurement

English Abstract
This article argues that curved-surface pattern inspection should not be reduced to ordinary character recognition, simple template matching, or generic defect classification. Its core lies in structural normalization and defect measurement over structured patterns under geometric deformation, imaging disturbance, process variation, and changing business inputs. What matters is not merely recognizing isolated characters, but establishing a stable and comparable relation between the expected pattern and the measured one, and then performing defect measurement on top of that relation. From this perspective, the system is better understood as a structured pattern inspection system rather than a conventional character inspection pipeline.

很多人第一次接触曲面 Pattern 缺陷检测时,往往会自然把它理解为字符识别、模板匹配,或者某种缺陷分类问题。但在我当时设计这套系统时,问题的核心并不在那里。我一开始就很清楚,这件事真正困难的,不是把字符“看出来”,而是如何在产品、图档、业务输入和现场条件不断变化的情况下,仍然建立起稳定、可比较、可实施的检测关系。也正因为如此,这套系统从设计之初就不是围绕“识别字符”展开的,而是围绕结构化归一化与缺陷测量展开的。

如果只从抽象层面谈“曲面形变”和“产品差异”,读者未必能立刻感受到这类问题为什么会把普通字符检测思路彻底推翻。更直观的方式,是先看两张真实现场 CCD 采集图。

Two real-world sources of difficulty in curved-surface pattern inspection

图 1:曲面 Pattern 检测中两类最基本、也最容易被低估的难点。左图展示了曲面成像带来的明显形变;右图展示了不同国别 Pattern 之间的巨大差异。真正关键的并不是“变化很多”,而是这些变化不能每来一次都回到核心程序里重写。对这套系统而言,耳机与充电盒、不同国别乃至不同产品对象之间的切换,原则上应通过图档、XML、INI 与运行配置层完成,而不是频繁改动 DLL 本身。这也正是它能够走向产品化和跨场景推广的前提。

从这两张图其实就能看出,这个问题一开始就不是“把某几个字符认出来”那么简单。左图说明,同样的结构对象一旦落到曲面成像条件下,局部形态就会发生明显变化;右图则说明,系统面对的并不是单一版式,而是大量国别 Pattern、图样组合乃至产品对象本身的变化。

真正困难的地方并不只是“变化很多”,而是:这些变化不能每来一次就回到核心程序里重写一遍。对一个真正想走向产品化的工业检测系统来说,核心 DLL 及其软件主架构必须尽可能保持稳定;产品切换、国别切换、产线切换乃至面别分支,原则上都应通过图档、XML、INI 以及相关运行配置层来完成,而不是不断回灌到核心代码里。换句话说,这套系统真正有价值的地方,不是“同一套代码勉强还能适配不同对象”,而是它从一开始就试图把变化压缩到外部描述层中,把 DLL 的改动降到例外,而不是常态。

也就是说,这套系统既要处理曲面带来的成像与几何变化,又要把不同国别、不同图档、不同产品对象所带来的差异,尽可能吸收到外部模板与配置体系中。这正是为什么后面必须引入模板、配准、参数链和配置链,而不能把它理解成普通字符检测。因为普通字符检测的思路默认对象本身相对单纯,变化主要落在识别层;而在这里,变化本身已经进入了系统组织层,必须被一种更稳定的结构化方式接住。

从这个角度看,曲面 Pattern 检测首先不是一个读取字符类别的问题,而是一个建立结构对应关系的问题。系统真正要回答的是:当前图像中本来应该出现什么 Pattern,实际出现了什么;它们之间哪些差异只是正常的几何形变、成像扰动或工艺波动,哪些差异才构成真正的缺陷;而在包含实时 SN code 的场景里,图像中的字符内容还必须与当前业务侧输入保持一致。也就是说,系统面对的从来不是一张孤立的字符图像,而是一个会随着产品、图档、业务输入和现场条件共同变化的检测对象。

只要这一点想清楚,后面很多设计就会自然变得顺理成章:为什么图档本身必须兼顾检测,为什么模板不能只是参考图片,为什么系统里会有 block、骨架/特征点、注册集与测量集,以及为什么不同国别、不同产品、不同产线之间的切换,应当优先通过 XML、INI、图档与运行分支来完成,而不是不断改动 DLL 本身。对这类系统而言,真正的产品化并不是“同一套代码大致还能用”,而是:新变化优先进入外部描述层,而不是重新进入 DLL。

如果说前一组现场 CCD 图说明了这类问题为什么天然复杂,那么下面这组真实产线检测结果图则更直接地说明:系统最终面对的,并不是“字符整体是否存在”,而是字符或图样内部那些尺度很小、却又确实存在的局部异常。下面这组图都来自现场上位机保存的检测结果,红色框标出了系统实际判定出的缺陷区域。

Typical defect examples from curved-surface pattern inspection

图 2:真实产线中的几类典型缺陷检测结果,包括镭断(laser break)、多镭(excess laser)、色浅(shallow engraving)和色深(deep engraving)。图中的红色框为系统实际检出的缺陷区域。尤其左上角那处镭断缺陷及其检测框都非常微小,这也说明这类问题并不是粗粒度的字符识别,而是面向细微局部异常的工业检测任务。

从这组图其实就能看出,系统要处理的并不是“字符整体是否存在”这种简单判断,而是字符或图样内部某一小段结构是否断裂、某一小块区域是否多镭、局部颜色或深浅是否偏离正常状态。换句话说,检测对象表面上是字符或 Pattern,真正需要被判别的却是它们内部的局部几何与局部成像异常。

所以,如果让我用一句更接近问题本体的话来概括它,我会说:曲面 Pattern 缺陷检测的关键,不在于把字符图像单独拿出来做识别,而在于先对结构化 Pattern 建立可比较关系,再在这个关系上做缺陷测量。只有这样理解,后面关于骨架模板、参数体系、两次配准、实时编码输入、插件接口以及系统节拍的讨论,才会真正连成一个整体。否则,这个项目就很容易被轻描淡写地概括成“做了一个字符检测算法”,而它最有价值的部分,恰恰会在这种概括里被抹平。

一、它不是把字符“认出来”,而是先把结构关系建立起来

普通字符识别最关心的是类别判断:这是不是某个字母,这是不是某串字符,这段内容到底是什么。而我当时做这套系统时,关注点从一开始就不在那里。对产线检测来说,更重要的问题是:这个位置本来应该有什么结构,这个结构在当前图像里是否以正确的方式出现了,它和应有结构之间的偏离是正常波动,还是已经构成缺陷。也就是说,系统面对的不是一个“读字”问题,而是一个“应有结构与实测结构之间如何建立比较关系”的问题。

这也是为什么单纯把它说成 OCR,会一下子把问题说浅。因为真正困难的部分并不在字符类别本身,而在于字符只是承载 pattern 的一种常见形态。项目里真正要处理的,是一类具有内部几何组织、局部笔画结构、拓扑关系和可测量特征的 pattern。字符只是最常见、也最典型的一类对象,但不是问题的全部。

二、它也不只是模板匹配,因为模板本身就是检测系统的一部分

如果说 OCR 离这个问题太远,那么模板匹配似乎近一点。毕竟这套系统里确实有图档、有模板、有对位、有匹配。但如果把它简单理解成“拿模板去和图像比一比”,仍然是不够的。

因为我当时设计的模板,并不是一张单纯拿来参考的图片,而是整个检测系统的一部分。图档本身就必须兼顾检测;xml 也不是为了存一张视觉参考图,而是为了存储可用于定位、注册和测量的结构对象。最常见的模板之一,就是 medial axis,也就是骨架点集。但这里的 skeleton 又不必被理解得太死,它在工程上更像是一类可用于注册与测量的结构特征点集。也正因此,模板不是静态附属物,而是后续整个检测过程的几何基准。

从这个角度看,模板的意义已经和普通模板匹配完全不同了。它不只是“像不像”的参照物,而是一个要被带入现场、带入参数体系、带入实施流程的结构载体。它不仅决定能不能检,还决定能不能导入、能不能交付、能不能在不同产品和不同国别之间平稳切换。

三、真正的问题主线,是归一化、对应、注册、测量,而不是直接判缺陷

很多视觉问题容易给人一种错觉,好像缺陷检测的核心就是“最后怎么判”。但对这个项目来说,我从一开始就知道,真正的主线不在最后那一下判别,而在更前面的几步:先把对象分成合理的 block,先建立 block 与 block 的对应关系,再把模板中的结构点带到实测图像里,最后才沿着这些结构点去做局部测量和缺陷判别。

换句话说,缺陷检测不是起点,而是终点。前面的归一化和对应关系没有建立起来,后面的镭断、色异常、多镭、偏移、码数量异常这些判断都会失去基础。很多人看项目时会先盯着“最终是怎么判 NG 的”,但真正把系统做起来的时候,决定成败的恰恰是前面的几何准备阶段。

这也是为什么系统里会自然地出现 block、Geo、skeleton、注册集、测量集以及两次配准。它们不是为了把系统写复杂,而是因为只有把这些层次建立起来,后面的检测才真正有了可比性。

四、实时 SN code 的存在,使它从纯视觉问题变成了视觉与业务流耦合的问题

这个项目里还有一个特别容易被低估的点,就是实时 SN code 的接入。只要场景里涉及动态生成的编码内容,问题就不再是“拿静态模板和静态图像做比较”这么简单了。系统必须同时知道两件事:当前业务流程要求出现什么内容,图像里实际又出现了什么内容。只有这两者对应上,后面的缺陷判断才成立。

也就是说,系统不只是看图,还要接收业务侧的实时输入,并把它转成当前应有的 pattern 结构,再和实测图像建立对应关系。到这一步,它就已经不再是一个单纯的图像处理模块,而是一套视觉、编码信息、模板系统和上位机流程共同耦合的工业系统。

正因为如此,这类项目的门槛其实并不只在图像算法本身,而在于你能不能把视觉对象、业务输入和工程接口同时组织起来。很多看上去“也会做视觉”的团队,一旦碰到这一步,复杂度就会迅速上升。

五、这套系统真正难的地方,是把变化压缩到少量可控的外部对象里

如果这只是一个单次 demo,那么最直接的做法当然是:换一个产品就改一次代码,换一个图档就重新调一次流程,换一个国别就重新写一套逻辑。但我当时的设计思路不是这样。从设计阶段开始,我追求的就是让内核稳定,让变化尽量收敛到少量可控对象里。

所以最后形成的形态才会是:核心 DLL 尽量不动,主要通过图档、xml 模板和 ini 参数去承接不同产品、不同国别、不同产线带来的变化。今天回头看,这其实正是这套系统真正高级的地方。因为一个系统是否成熟,很多时候不在于内部写得多复杂,而在于你能不能把外部世界的复杂性压缩进几个清晰、可替换、可维护的对象里。

这件事说起来很朴素,但真正做起来并不容易。因为只有当你在设计时就抓住了问题本体,知道哪些东西应该固化进内核,哪些东西应该留在模板层和参数层,系统才可能成长出这样的结构。

六、所以,它更准确的名字,应该是“结构化 Pattern 缺陷检测系统”

如果一定要给这类问题一个更准确的名字,我不会把它叫作字符识别,也不会把它简单叫作模板匹配或缺陷分类。我更愿意把它理解为一套面向曲面/平面结构化 Pattern 的归一化、注册、测量与判别系统。

这里面最重要的词其实不是“检测”,而是“结构化”。因为一旦把对象理解成结构对象,而不是孤立图像,后面的很多东西就都会回到正确位置:为什么图档必须兼顾检测,为什么模板要保存骨架或特征点,为什么需要注册集和测量集,为什么要做两次配准,为什么系统最后会长成一套模板、参数、接口和节拍共同组织起来的工业框架。

从这个意义上说,这个项目最怕的,不是技术难,而是从一开始就把名字叫错。一旦把它理解成普通字符检测,后面的很多设计就都会显得过重、过繁、甚至莫名其妙;但如果把它理解成结构化 Pattern 的归一化与测量问题,那么整套系统的逻辑反而会变得非常自然。

下一讲,我会继续写这套系统真正的骨架:图档、block、Geo、skeleton、注册集、测量集,以及两次配准为什么能把一个工业检测系统真正撑起来。