字符缺陷检测这个需求,这几年在非标自动化项目里出现频率相当高。表面看,它就是把产品上的字符拍清楚,再判断有没有缺陷;实际上,缺笔画、断线、油墨堆积、字符粘连、喷码模糊,每一种缺陷的成因和呈现方式都不一样,参数调不好就是误检漏检来回折腾。这篇文章以海康VM(VisionMaster)为平台,完整复盘一个电源适配器外壳丝印字符检测项目的全过程,从需求拆解、硬件选型、流程编排到参数调优和上线排障,把我在这个项目里踩过的坑和验证过的做法一并讲清楚,给正在做同类项目的同行一个可参考的路线。
1. 字符缺陷检测到底在检什么:需求比想象中复杂
1.1 先和客户把"缺陷"的定义对齐
很多人一开始会把字符缺陷检测和OCR识别混在一起,觉得字符能读出来就算成功。实际上这是两个完全不同的任务:OCR关心的是"这几个字符是什么",缺陷检测关心的是"这几个字符印得完不完整、清不清楚、有没有多余的东西"。我的项目里,客户最初也只说了一句"把坏字挑出来",等我细问才知道他们内部对缺陷有完整的分类。
这个项目做的是电源适配器外壳丝印,要检测的是外壳上的型号字符和日期喷码。客户给的缺陷类型一共有六类,每类的视觉特征和成因差别很大:
| 缺陷类型 | 表现特征 | 视觉判断依据 |
|---|---|---|
| 缺笔画 | 字符部分笔画缺失 | 连通域面积偏小、笔画端头异常 |
| 断线 | 本应连续的笔画断裂 | 单个字符出现多个连通域 |
| 油墨堆积 | 墨量过大导致笔画粘连 | 字符外接矩形变宽、相邻字符连通 |
| 污点/溅墨 | 字符周围出现多余墨点 | 出现孤立小面积连通域 |
| 模糊 | 喷头偏移或墨量不足 | 边缘梯度弱、字符与背景对比度低 |
| 歪斜/移位 | 字符整体位置偏移 | 外接矩形角度变化、质心偏移 |
这些缺陷如果靠人眼在产线上看,时间一长必然漏检,所以才需要视觉方案。但方案能不能做好,第一步不是选算子,而是和客户把"什么算NG"定清楚。同一个字符,墨量厚一点和薄一点都算正常,可如果客户要求的是零容忍,任何肉眼可见的波动都要拦下,那算法就要做到极其严格,误检率必然飙升。我这次和客户开了两次会,才把缺陷程度、检测范围、抽样还是全检这几个关键口径完全确认下来,这一步省下来的时间足够抵掉一次返工。
1.2 判定指标和节拍约束决定了后面所有选型
这个项目客户给了三组硬指标:漏检率不能超过0.5%,误检率允许在3%以内,单件检测节拍2秒。这三组指标是互相拉扯的关系:检测条件调严,漏检率降下去了,误检率就会上来;条件调松,误检率好看,漏检风险就埋下了。所以方案设计阶段就要想清楚怎么在这两个指标中间留出余量,而不是等软件写完了再慢慢磨阈值。
节拍2秒听起来宽裕,但如果方案里用了相机全分辨率出图,再加好几个大计算量的模块叠在一起,实际耗时很容易超支。而且这个节拍不只是算法时间,还要算上相机取流、图像传输、结果通信、PLC应答这些环节。我后来在评审时用秒表实测,才发现预估的1.2秒和实际差了快0.6秒。这些约束条件在项目一开始就要摆到桌面上,后面每一步选型都得围着它们转。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 海康VM里的方案工程结构:从取流到结果输出
2.1 为什么选海康VM而不是自己写一套算法
字符缺陷检测的技术路线很多,可以用OpenCV自己写,也可以用商用视觉平台。我这次选海康VM,主要看中三点:第一,可视化流程编排,现场调试改参数不用重新编译代码,改完直接跑;第二,相机取流、模板匹配、Blob分析、字符识别这些常用模块都是现成的,不用自己造轮子;第三,VM在国产工业现场的普及度很高,项目交付后客户自己的工程师也能上手维护,这对验收和售后都有帮助。
VM的基本组织方式是"方案-流程-模块"三层。一个方案就是一个工程项目,里面可以建多个流程,每个流程是一条按顺序执行的模块链,相当于一个完整的检测任务。我的搭建思路是把整个检测任务拆成六个环节:取流、预处理、定位、裁剪、检测、结果输出,每个环节对应一到两个模块。这样结构清晰,哪一环出问题,直接看中间结果就能定位。
2.2 硬件侧:相机、镜头和光源怎么搭配
算法再好,图像质量不行也白搭。这个项目的产品是深色外壳白色丝印,字符是浅色、底是深色,天然对比度不错,但外壳表面有一点弧度,丝印区域不是完全平面,所以光源和打光角度很关键。
我用的是一只500万像素的工业相机,配8mm定焦镜头,工作距离大概300mm,视场能覆盖整个丝印区域,单个字符在图像里大约占40×60像素,这个分辨率对检测缺笔、断线够了。光源用的是低角度环形光,让字符边缘形成明显的明暗过渡,后面做二值化时阈值比较好选。这里有个经验:字符检测场景,光源的角度比亮度更重要。低角度光能把字符表面的凸起打出立体感,让笔画边缘更锐利;如果打成正面高光,反光区域容易把字符细节淹没。
现场调光时,我习惯先把相机曝光和光源亮度调到灰度直方图上字符和背景两个峰尽量分开。这个状态下拍出来的图信息量最大,后续无论做二值化还是算梯度,都有足够的余量。调光这一步千万别偷懒,光源角度差一点,后面的阈值就全要重调。
2.3 软件流程的六段式结构
在VM里我搭的流程大致如下:
- 取流模块:从相机获取图像,触发方式设为外部硬触发,和产线传感器联动,保证每次拍到的都是产品到位后的画面。
- 图像预处理:先用高斯滤波去噪,再做二值化把字符和背景彻底分开。这里我特意没有用形态学闭运算去连接断裂笔画,因为断线本来就是我们要检测的缺陷,提前把断线补上等于掩盖问题。
- 定位模块:用模板匹配找外壳上的固定特征(比如外壳边缘的角点),算出字符区域相对这个特征的位置偏移,再做仿射变换把字符区域校正到标准位置。这一步是为了抵消产品在传送带上每次停靠位置的微小偏差。
- 区域裁剪:在校正后的图像上按固定ROI把要检测的字符区域裁出来。ROI可以稍微留一点余量,但要保证包含完整字符,又不能把旁边的花纹、Logo裁进来。
- 缺陷检测:对裁剪后的区域做Blob分析和连通域特征计算,再送到判定逻辑模块。这是整个方案的核心,后面单独展开。
- 结果输出:把OK/NG结果通过IO或通信协议发给PLC,同时把NG图像保存到本地文件夹,方便事后追溯。
这六段不是一次性调通的。我习惯先把取流和定位跑通,用几十张正常产品图像把ROI和定位模板确认好,再往后面加检测逻辑。每加一段就停下来看中间结果,避免问题层层叠加,到最后不知道是哪个环节出的错。调试顺序上,先固定输入,再验证输出,这是视觉项目通用的排错思路。
3. 核心检测路线:三种方案怎么选,为什么这样选
3.1 方案A:模板比对,实验室很香现场就碎
最直接的想法是把标准字符图存下来,对每一帧图像做差分,差异大的判NG。这个方案在实验室里效果确实不错,拿到现场就很快暴露问题:光照稍微变化、产品位置有偏差、正常喷码本身的墨量波动,都会在差分图上造成大量伪差异,误检率根本压不下来。除非字符区完全固定、光照恒定、喷码质量极高,否则生产现场直接用模板差分,结果就是在误检的泥潭里出不来。
3.2 方案B:字符提取加Blob特征分析,这次的主路线
这个方案是主路线。思路是:把字符区域分割成一个个连通域,计算每个连通域的面积、周长、外接矩形宽高、孔洞数量、质心位置等特征,再和标准范围做比较。缺笔画的字符面积会明显偏小,断线的字符连通域个数会变多,粘连的字符外接矩形会变宽,污点本身就是孤立小连通域。这些特征对光照波动没那么敏感,因为只要二值化能把字符和背景分开,连通域的基本形状就是稳定的。
在VM里我用的是Blob分析模块,它自带面积、周长、外接矩形、圆形度这些常用特征的计算,还能按特征范围做筛选。我的做法是把每个字符单独切成一个小图,再对每个小图跑Blob分析,这样字符与字符之间的粘连、污染也能被独立识别。字符切割用投影法就能做:把字符区域的二值图分别向水平和垂直方向做像素投影,根据投影峰的位置把每个字符分开。这个方法对等宽的印刷字符非常有效,一旦字符有倾斜,投影法容易切歪,所以前面定位校正那一步一定要做好。
3.3 方案C:OCR比对当辅助,不拿它扛大梁
海康VM里有字符识别模块,能直接把字符读出来。把读到的字符串和标准字符串比对,能发现字符打错、漏印、多印这类问题,但对缺笔画、断线这类"字符还是那个字符、只是质量有瑕疵"的缺陷基本无能为力,因为OCR的输出是字符串,不是缺陷描述。
所以我把OCR当成辅助手段:识别结果先确认喷码内容与当前产品型号匹配,再交给Blob分析去做质量判定。两个维度结合,既能防内容打错,又能防内容打缺打歪。三种方案的对比我整理成了表:
| 方案 | 能检出 | 弱点 | 适用场景 |
|---|---|---|---|
| 模板差分 | 明显缺笔、大块污点 | 对光照和位置太敏感,误检多 | 光照恒定、位置固定、字符规整 |
| Blob特征分析 | 缺笔、断线、粘连、污点、部分模糊 | 字符变体多时需要单独调阈值 | 字符种类有限、喷码工艺稳定 |
| OCR比对 | 漏印、多印、错字 | 检不出笔画质量缺陷 | 搭配使用,确认内容正确性 |
我的最终方案是B为主、C为辅。这个选择不是拍脑袋:客户的产品只有两种型号,每种对应固定的喷码格式,字符种类有限,Blob特征分析能把尺度和阈值定得比较准;同时喷码内容偶尔会打错,加一道OCR比对能兜底。
4. 参数调优实战:漏检率与误检率的平衡术
4.1 采集样本,先摸清正常产品的波动范围
参数调优的第一步不是调参数,而是采集样本。我在产线上连续采了200多张正常产品的图像,又请客户从退货品和人工检出的NG品里找了几十张带各种缺陷的图像,一起喂给方案跑。跑完之后我做的第一件事不是看误检率,而是把所有正常产品图像的特征值分布画出来——每个字符的连通域面积、个数、外接矩形尺寸到底是什么水平,波动范围有多大。
这一步非常关键。生产现场的正常喷码并不是一个标准值,它是有波动的:墨量多时笔画粗一点,墨量少时细一点,网点形状也各不相同。只有先摸清正常波动的上下限,才能知道检测阈值应该定在哪里。比如某个字符的标准面积是2600像素,正常波动范围在2400到2800之间,那我把面积下限定在2200,既能避开正常波动,又能让明显缺笔的NG品(面积可能只有1500以下)稳稳被拦下来。
4.2 特征阈值怎么定:先定特征,再定挡位
我把每个字符要检测的特征归纳成几类,分别设定阈值,再用逻辑组合串起来:
| 特征 | 正常范围(示例) | 异常判定 |
|---|---|---|
| 字符连通域总面积 | 2400-2800 | 小于2200判缺笔/断线,大于3000判粘连 |
| 连通域个数 | 1-2 | 大于3判断线或碎墨 |
| 外接矩形宽高比 | 0.55-0.65 | 偏差超过10%判粘连或变形 |
| 孔洞数量 | 1(如O、A) | 孔洞消失判油墨堵塞 |
| 孤立小连通域面积 | 0 | 出现面积大于30的小块判溅墨 |
在VM里,Blob分析模块可以对筛选出的连通域输出这些特征值,然后我用条件判断模块做逻辑组合。逻辑上用"OR"关系:任意一个字符满足"面积小于2200"或者"连通域个数大于3"或者"存在明显孤立小连通域",整体判NG。这种"一票否决"的设计优先保证漏检率,因为漏检一旦发生就是质量事故,误检顶多增加人工复检工作量。
4.3 误检压不下去?先找图像处理的问题,别急着动阈值
调试过程中我最头疼的是误检率下不来。有一批正常产品老是有一两个字符被判成断线,放大图像一看,字符边缘有一圈淡淡的墨雾,二值化时墨雾区域被当成背景的一部分,导致字符主体被切得零零碎碎,连通域个数暴增。这时候如果直接去调判定阈值,只会让真正的断线缺陷漏过去。误检的根源在图像预处理环节,不在判定环节。
解决思路有两个:一是调整二值化的阈值,让墨雾部分的灰度值落到背景一侧;二是用先膨胀再腐蚀的闭运算,把墨雾造成的细小断裂弥合掉。但这个动作要非常小心,闭运算的核不能太大,否则真实的断线缺陷也会被补上。我最后用的方案是:对二值图先做一次3×3的闭运算,只弥合几个像素宽度的细小缝隙,而真实断线的缝隙一般超过5像素,核大小控制在不会把它们完全补上的程度。处理后正常产品的连通域个数恢复正常,真实断线缺陷仍然能被检出。
4.4 批量回放样本验证阈值,而不是拍脑袋
阈值定完后,我在VM里建了一个批处理流程,把之前采集的样本全部重跑一遍,统计OK图上的误检比例和NG图上的漏检比例。这一步相当于把整个方案回放一次,看它在样本集上的整体表现。第一次统计出来误检率大概1.5%,漏检率0%,都满足客户指标。
但我不放心,又故意把光照调暗一档,模拟现场灯具老化的极端情况,发现有个别字符开始误报。于是我把二值化从固定阈值改成自适应阈值,让它根据每帧图像的灰度分布自动计算分割点,光照波动时依然能稳定分割。这个改动让方案的鲁棒性上了一个台阶,也让我意识到,验证一定要覆盖极端条件,只看理想条件下的指标没有意义。
5. 上线后踩过的坑:光照漂移、节拍和批次切换
5.1 光照漂移排查全过程:从误报突增到双层解决
上线两周后,客户反映误报突然变多。我到现场第一件事是看NG图像,发现大量字符的边缘响应偏弱,二值化分割点明显偏移。接着我用灰度直方图对比了调试时和当天的图像,确认不是算法问题,而是成像条件变了:灯具亮度确实衰减了,而且车间下午的阳光会从窗户斜射在传送带上,改变了环境光。
排查链路走下来,本质是图像前端的成像条件变了,而我的参数是在固定条件下调的。决办法分两层:硬件层,给相机和光源区域加装遮光罩,减少环境光干扰;软件层,把二值化阈值改成基于灰度直方图的动态计算,并给光源加定期亮度标定动作,每周用标准件拍一帧基准图,比对灰度均值,漂移超过一定比例就提示维护人员调整亮度。这两层处理之后,同一套参数在白天晚上都能稳定运行。
5.2 节拍超时:全分辨率图像的代价
评审时我预估单件检测耗时1.2秒,实际跑起来达到1.8秒。多出来的时间主要花在取流和图像传输上。原因是我一开始用的是相机全分辨率出图,分辨率高确实能提高检测精度,但整帧图像传输、滤波、定位都要处理更大的数据量。
优化思路有两个方向:一是把ROI在采集端就定下来,相机只输出字符区域,减少图像传输量;二是把定位用的模板匹配改成先降采样再匹配,粗定位用低分辨率图快速算,精确定位再回原图做。两个方向组合后,单件检测耗时降到约0.9秒,留出了充足余量。这个经历说明,节拍预算要提前算,不能等上线了再挤。
5.3 批次切换:不同喷码格式的参数管理
客户的产品线不是一成不变的,隔一段时间会换型号、换喷码格式。按我最初的方案,每个字符区域的特征标准是写死的,换了喷码格式就得重新调一遍ROI和阈值,费时又容易出错。
后来我用VM的配方管理功能,把不同产品型号对应的相机参数、ROI坐标、检测阈值、标准字符串做成一个个配方,切换时一键加载。配方切换的逻辑放在流程最前面:先识别当前产品型号(用一个固定位置的二维码或人工输入),再去配方表里查对应的检测参数。这样换产线只需要换配方,不用改流程,维护成本大幅下降。这一点在做多型号产线时尤其重要,别等到客户换型号了才想起来。
5.4 灰度偏低的模糊缺陷:加一道前置筛选
六类缺陷里,模糊最难用Blob分析检出,因为模糊字符二值化后的面积可能没有明显变化,只是边缘过渡带变宽,连通域特征全都正常。针对它,我在流程最前面加了一道前置筛选:计算字符区域的灰度梯度和对比度,用索贝尔算子求出边缘响应均值,低于正常范围就认为印刷模糊,直接判NG。这个方法不能替代主检测,但能把模糊类缺陷独立兜住,和Blob分析形成互补,让六类缺陷都有了对应的检测手段。
6. 几点体会和可以直接抄的小技巧
先说一个容易被忽略的点:字符缺陷检测项目的成功,一半在算法,一半在样本。正式开发前一定要花时间把正常产品和NG产品的样本采集齐,特征分布清楚了,参数才能定得准。这个项目我最大的教训是没有在最初阶段建好样本库,导致前期调参一直靠现场来回试,进度至少慢了一周。
几个实用小技巧,都是实际项目验证过的:
- 任何判NG的图像都要留存,按日期和产品型号分文件夹保存,方便分析误报原因,也能在客户投诉时快速举证。
- 二值化优先用自适应阈值,不要用固定阈值。生产现场光线一定会飘,自适应阈值能帮你省掉大量后续维护工作。
- 定位环节不要省。哪怕产品有定位治具也会有细微偏差,一个稳定的定位模块可以省掉大量误检排查时间。
- 检测逻辑用"OR"组合,把漏检率放在第一位。漏检是客户最不能接受的问题,误检可以靠阈值微调来压,漏检一旦发生就是质量事故。
- 调试时准备一张模拟最差情况的NG图,比如刻意调暗、调偏光,用来验证方案在最恶劣条件下还能不能兜住。
字符缺陷检测说到底是把"正常波动"和"真实缺陷"分开的问题。正常喷码本来就有墨量、位置、形状的波动,缺陷则是在这个波动范围之外的异常。想清楚这一点,方案设计就不会跑偏。这次项目做完,我对VM的模块化流程有了更深的理解,也把Blob分析和OCR结合的路子完整验证了一遍。如果后面遇到字符种类更多、背景更复杂的场景,我会优先考虑在VM里接入深度学习分类器,替换掉一部分手工阈值逻辑,进一步把检测稳定性往上提。
