印刷车间里最容易让人头疼的,不是机器速度不够,也不是油墨调不准,而是质检这一关。一卷纸跑下来,几个老师傅拿着放大镜翻来覆去找刀丝、蹭脏、漏印,眼睛花不说,不同人看的标准还不一样。这套“基于图像处理的印刷品缺陷检测系统”就是冲着这个痛点去的——用工业相机把产线上的印刷品连续拍下来,靠图像处理算法把缺陷从复杂的印刷背景里揪出来,再按缺陷类型分类告警。这篇文章我会完整复盘这套系统的设计与实现过程,从缺陷类型分析、硬件选型、图像采集,到算法链路的每一步细节,再到控制误检的判定策略和评估指标,适合正在做视觉检测项目、或者准备在产线上落地类似方案的工程师参考。
1. 印刷品缺陷的“脾气”:为什么这套系统难做
1.1 先分清缺陷类型再谈检测
做缺陷检测第一件事不是选相机,也不是调算法,而是把要检测的缺陷类型彻底理清楚。印刷品缺陷种类不少,形态差异极大,处理方式完全不同。
| 缺陷类型 | 典型成因 | 成像特征 |
|---|---|---|
| 刀丝 | 刮刀磨损、金属异物卡在刮刀上 | 线状,沿走纸方向延伸,粗细不均,可能周期性出现 |
| 蹭脏 | 传送辊粘墨、擦拭不净 | 团块状、条状,灰度对比高,有方向性 |
| 漏印 | 供墨不足、网辊堵塞 | 大面积灰度偏低,边缘模糊 |
| 飞墨 | 墨雾飞溅落点 | 细小点状,分布随机,灰度较高 |
| 套印不准 | 多色套印偏差 | 彩色边缘错位,在灰度图下表现为重影边界 |
| 死点 | 干燥油墨颗粒脱落 | 点状或带小尾巴,灰度偏低 |
我早年第一次做这类项目时,客户说“只要检刀丝就行”,结果系统上线三天,漏了一处蹭脏被投诉。后来才明白,印刷品的缺陷检测从来不是单目标检测,而是“抓异常”的通用能力——你根本想象不到下一秒会跑出什么奇怪的脏点。所以系统设计一开始就要按“多缺陷类别并行检测”来考虑,哪怕第一版只重点处理两类缺陷,算法框架也要为后续扩展留好接口。
1.2 印刷品背景对视觉检测非常不友好
印刷品缺陷检测难,难在背景本身极不干净。杂志封面、包装盒、标签上全是色块、文字、网点渐变的复杂图案,这些正常元素在图像里呈现出的灰度变化,有时候比缺陷还剧烈。
这里有一个关键概念:网点。印刷品上的图像是通过大小不一、密度不一的网点排列实现的,150线、200线网点的周期大概在0.1毫米到0.2毫米级别。对相机来说,这些网点是高频空间纹理,对算法来说是强烈的背景噪声。如果直接用全局阈值分割,网点密集区域会整片被判定为缺陷。
再叠加印刷材质问题:铜版纸反光、覆膜表面有镜面反射、镭射纸干脆不同角度颜色完全不一样。普通面阵相机配一个环形光源,图像上会出现明显的明暗条纹,这类低频光照不均匀,和缺陷在灰度特征上有重叠,轻则干扰阈值变化,重则直接误检。解决这些干扰,不是靠某一个算法特效,而是要靠后面第4章的那套组合流程。
2. 系统的整体架构与关键选型取舍
2.1 相机选型:先算分辨率再谈型号
很多新手选相机,上来就问“两百万够不够、五百万够不够”。我先给一套可复用的计算逻辑。
假设检测幅面宽度是400毫米,客户要求最小缺陷0.2毫米要稳定检出。工业视觉领域的通行经验是:一个稳定可识别的目标,至少要有5个像素以上去覆盖。也就是说,单个像素对应的物理尺寸要小于等于0.04毫米。
需要的像素数 = 400毫米 / 0.04毫米 = 10000像素。
这个分辨率意味着,常规的面阵相机(比如500万像素,横向约2448像素)根本不够用,横向需要10000像素已经超过大多数面阵相机的单幅覆盖范围。所以产线用的基本都是线阵相机加编码器触发方案,一行一行扫过来。像8192像素的线阵相机就很常见,配合编码器输出脉冲信号,每走固定距离触发一次采集,能从物理层面保证图像在走纸方向上的均匀采样,不会因为速度波动导致图像拉伸或压缩。
如果检测幅面很小,比如200毫米以内,且最小缺陷尺寸放宽到0.3毫米以上,那500万像素面阵相机完全够用,安装调试也比线阵更省事。这个取舍没有绝对好坏,一切由检测精度和幅面决定。
2.2 镜头与光源的搭配逻辑
镜头选型的核心指标是焦距和工作距离。比如传感器宽度12.8毫米,想在工作距离600毫米处覆盖400毫米视野,需要的焦距约为:
焦距 = 12.8 × 600 / 400 = 19.2毫米
实际选型时会选接近的工业定焦镜头(比如25毫米),再通过调整工作距离来满足视野要求。这里注意一个坑:镜头畸变。普通监控镜头畸变很大,边缘的刀丝会被拉弯,差影时产生大量假边缘。工业级远心镜头或者低畸变定焦镜头是首选,尤其是检测幅面边缘区域时,畸变带来的影响远比你想象的大。
光源方案我踩过不少坑,这里直接给结论:
- 检测刮痕、划伤、刀丝这类低对比度线状缺陷,用低角度暗场光,让缺陷在暗背景上形成亮线,对比度能翻好几倍。
- 检测色差、蹭脏这类灰度变化缺陷,用漫射光(比如圆顶光源),照明均匀,不带方向性,否则同一个缺陷换个角度就看不见了。
- 检测覆膜、镭射这类高反光材质,优先考虑同轴光,光线垂直照射避免镜面反射直接进入镜头,不然图像上全是亮斑。
2.3 主控与软件模块划分
这套系统的实时计算压力很大,8192像素线阵相机在1米/秒产线速度下,每秒要处理的图像数据量超过100兆字节。我最终用的是工控机加独立显卡的架构,而不是PLC——PLC逻辑控制很强,但图像处理需要的矩阵运算、卷积、形态学操作,靠PLC完全跑不动,更别说实时跑算法了。
软件上我分了几个模块:采集模块(相机SDK、编码器触发、图像缓存)、预处理模块(灰度化、降噪、背景校正)、检测模块(差影、阈值分割、形态学处理)、分类模块(特征提取、规则判定、周期性分析)、结果模块(告警、记录、图像存储)。每个模块独立一个进程,模块之间通过消息队列传递数据,这样某一个模块崩了不会导致整条系统停摆,也方便单独升级算法。
3. 图像采集环节最容易翻车的三个细节
3.1 频闪与运动模糊
产线上没有“静止图像”这回事。线阵相机在1米/秒的产线速度下,哪怕曝光时间只开100微秒,图像上也会出现运动模糊。具体算一下:100微秒内走纸距离是0.1毫米,如果单个像素物理尺寸是0.05毫米,那这个模糊会让缺陷在两个像素之间“拉花”,小刀丝的灰度对比度被摊薄,本来能检出来的缺陷就漏掉了。
解决办法是同步曝光加短曝光控制。编码器发出的脉冲直接控制相机的行频和曝光,曝光时间尽量压在50微秒及以下,同时打强光保证图像亮度。这里有个常识很多人忽略——光源的功率和曝光时间是一对互补参数,光源越强,曝光时间就能越短,运动模糊就越小。
3.2 光照一致性
光源用久了会衰减,LED从满功率到衰减20%,肉眼几乎看不出来,但算法对光照变化非常敏感。差影法里,背景模板是固定的,而实际图像如果整体暗了几个灰度级,差影结果会自动产生一整片“伪缺陷”。
我在系统里加了一个光照校准流程:每班次开机后,先传送一段空白样张(或者标准灰阶卡),统计图像灰度均值和标准差,和基线值对比。如果偏差超过一定范围,算法自动补偿增益——相当于给图像做了一个整体亮度归一化。这个看似不起眼的模块,后期降低过检率的贡献其实很大。
3.3 机台震动与对焦漂移
线阵相机工作距离短,景深也浅,机台一旦有震动,画面就会周期性模糊,或者出现线条偏移。我遇到过最诡异的现象:同一套算法白天过检率0.5%,晚上变成3%。排查到最后发现是车间夜班时段旁边一台重型设备启动,整个检测平台都在微幅震动。
后来把所有相机支架换成铸铁底座并加装橡胶减震垫,把相机与产线机架的连接点从3个增加到4个对角锁定,问题才消停。另外,对焦漂移是不知不觉发生的——镜头固定螺丝松动、温度变化导致镜筒热胀冷缩,都会让清晰度下降。每两周做一次标定板对焦校验,比什么算法优化都管用。
4. 图像处理算法链:从灰度化到缺陷分割的完整流程
4.1 预处理:降采样与去噪
拿到原始图像后,第一步是灰度化。线阵相机输出的一般是RGB三通道,缺陷检测本质上关心的是亮度异常,所以灰度化权重用标准公式:
Gray = 0.299R + 0.587G + 0.114B
如果检测的幅面很大而实际缺陷尺寸允许,我会先做一次降采样,例如把图像缩小到原来的二分之一。这一步别看简单,处理速度能提升3到4倍,因为后续所有的形态学操作、阈值分割都在像素数量更少的图像上计算。代价是灰度细节略损失,但只要最小缺陷在降采样后仍然大于等于8个像素,就完全不影响检出效果。
然后做中值滤波,核大小选3×3就够了。印刷品图像里常有孤立的小噪点,中值滤波在保留边缘细节的同时能把这些椒盐噪声去掉,为后面的阈值分割提供干净输入。
4.2 模板差影与背景模型
差影法的核心思路很简单:拿当前图像和一张“标准无缺陷图像”逐像素相减,差值大的地方就是缺陷。
D(x, y) = |I(x, y) − B(x, y)|
但关键在于B这张标准图像怎么来。直接在产线上停机拍一张,完全不现实——产线一停就是钱。我的做法是连续采集当前批次前100张通过人工确认无缺陷的图像,逐像素求均值,作为背景模板B。这样做能平均掉随机噪声,同时保留印刷图案的结构信息。
还有一个细节:印刷品的套印位置本身有轻微波动,同一个图案在不同张图像上可能偏移一两个像素,直接做差影会产生一条条边缘轮廓伪影。解决办法是先做相位对齐——用归一化互相关(NCC)找到当前图和模板的位移偏移量,把当前图平移对齐后再做差影。这一步的计算量不小,但能稳稳压住后续的误检率。
4.3 光照不均可怎么办:顶帽变换
差影能解决“和标准图不一样”的问题,但解决不了光照不均匀带来的“同一张图上亮度不一致”的问题。印刷品表面有凹凸、覆膜反光、边缘翘起,这些区域在图像上形成不规则的灰度渐变,直接进阈值分割会把一大片区域全判成缺陷。
这里我用的是形态学顶帽变换。做法是:
- 对图像做一次灰度开运算(先腐蚀后膨胀),得到一个近似的背景估计图。
- 用原图减去背景估计图,得到突出暗缺陷的顶帽图。
开运算会把比结构元素小的细节(包括缺陷)抹掉,只保留大区域的背景趋势。相减之后,光照不均匀的“低频背景”被去掉了,而缺陷这种“局部暗斑”被完整保留下来。注意:如果缺陷是亮斑(比如白点),则用黑帽变换,效果对称。
这个处理的价值在于,它把“不患寡而患不均”的光照问题转成了纯局部的异常问题,后面阈值分割变得非常稳定。
4.4 局部自适应阈值:为什么全局阈值在这里不灵
印刷品背景复杂,同一张图上,深色油墨区域和浅色空白的灰度值可能差上100多。如果用固定阈值或全局自适应阈值,深色区域的背景会被直接当成缺陷处理。
局部自适应阈值算法的思路是:对每个像素,只看它周围一个小窗口内的灰度统计,然后根据局部均值μ(x,y)和局部标准差σ(x,y)计算该像素的阈值。我常用的是Sauvola变体:
T(x, y) = μ(x, y) × (1 + k × (σ(x, y) / R − 1))
其中k取0.2左右,R取128。窗口尺寸选择很关键:太小了容易被网点本身干扰,太大了又失去“局部”的意义。实践下来,窗口大小取待检最小缺陷宽度的3到5倍,同时必须大于印刷网点的周期,比如最小缺陷0.2毫米对应图像上10个像素,窗口就设在30到50像素之间。
对于印刷品这类背景复杂的图像,局部自适应阈值比Otsu可靠得多,因为Otsu默认图像是单峰或双峰分布,而印刷品图像往往是多峰分布,全局分割必然翻车。
4.5 形态学开运算与连通域筛选
阈值分割完成后,图像上会残留两类噪声:一类是比真实缺陷更细小的孤立噪点,另一类是背景纹理分割后留下的小碎片。这两类噪声我统一用一次开运算处理——先腐蚀再膨胀,规则是:如果一个白色噪声区域的宽度小于结构元素,腐蚀步骤会把它完全消失,之后膨胀也没法恢复。结构元素一般取3×3圆形或5×5方形,具体取多大要看你设定的最小缺陷尺寸。
接下来做连通域标记,把白色像素聚成一个个独立区域。然后做一轮初步筛选,剔除明显不合格的候选:
- 面积小于设定阈值的直接丢弃
- 长宽比过于极端的丢弃
- 与背景灰度差过小的丢弃
这一步之后,剩下的候选区域数量通常已经很少,再从几十个排到个位数,接下来进入分类判定阶段。
5. 缺陷判定与分类:传统方案怎么控制误检
5.1 误检的来源分析
只要跑过产线都知道,算法误检永远是比漏检更麻烦的问题。漏检顶多是客户投诉,过检率高会被现场质检员骂死——一堆没有问题的产品被拦下来,人工复核根本忙不过来。
误检来源主要有三类:
第一类是印刷品图案本身的边缘。图案的色块边界对比度极高,差影后如果对齐稍有偏差,边界轮廓就会变成“伪缺陷”候选。
第二类是网点聚集区域。浅色调的网点在局部密集排列,阈值分割后可能连成不规则的块状区域。
第三类是光照反射形成的亮斑,尤其是覆膜表面,反光区域的灰度特征和真实缺陷几乎一样。
理解了这三类误检来源,才能有针对性地设计判定策略,而不是盲目调阈值。
5.2 特征工程与规则判定
对每个候选区域,我会提取一组特征:
- 面积:连通域的像素总数
- 长宽比:最小外接矩形的长宽比例
- 灰度差:区域平均灰度与邻域背景平均灰度的差值
- 对比度:区域灰度标准差与邻域灰度标准差的比值
- 位置:在图像中的坐标,靠近边缘的候选区域要额外标注
然后走一套规则判定逻辑。例如刀丝的典型特征是:面积中等、长宽比极大(大于8)、灰度差明显、方向接近走纸方向。蹭脏的特征是:面积大、长宽比接近1、灰度差大、边界不规则。飞墨的特征是:面积很小、对比度高、分布随机。
规则判定最大的好处是结果完全可解释,现场调试时你能直接告诉操作员“这个被检出来的东西,为什么会被判成蹭脏”,操作员也能根据经验快速反馈哪些特征判断错了,调参就有方向。换成深度学习的话,现场工程师面对一个误检只能干瞪眼,不知道从何下手。
5.3 周期性缺陷的专门通道
印刷品里有一类缺陷非常讨厌——齿轮印、橡皮布损伤,这类缺陷会在走纸方向上周期性重复出现,周期可能是一圈辊的周长。它们单从灰度上看可能非常微弱,甚至比正常图案的纹理差异还小,普通差影很难稳定检出。
我单独设计了一个周期性缺陷检测通道:对差影结果图在走纸方向做一维傅里叶变换,把图像信号转换到频域,寻找频谱上的尖峰。如果有明显的频谱峰,对应的就是周期性重复的异常信号。找到周期后,再回到空间域,按周期分帧做相位对齐和累计平均——把每一周期内的信号叠加平均,随机噪声在平均中被消掉,而有规律的缺陷会被增强。这个增强后的信号再去做阈值判定,微弱刀丝和齿轮印就能稳定检出来了。
这条通道不走常规的检缺陷流程,但对印刷行业非常实用。凡是有滚筒结构的印刷机,周期性缺陷基本是必然存在的,搭一条专职通道比靠主流程“碰运气”可靠得多。
5.4 深度学习要不要上
很多读者可能会问:既然传统方案这么费劲,直接上深度学习和语义分割行不行。
我的看法是:深度学习适合场景高度一致的缺陷类型,但印刷品缺陷的问题在于背景变化太丰富,换一个订单就换一套图案,深度学习模型的泛化能力很难保证,需要大量标注样本重新训练,而客户往往根本凑不出几百张连贯的缺陷样本图。
所以我对这套系统的定位是:主流程用传统图像处理——解释性强、调参快、不吃样本;如果客户确实需要对特定纹理类型做深分类(比如区分是刀丝还是咬痕),旁路挂一个轻量级分类网络即可,但绝不把检测核心放在深度学习上。这个路线选择,在项目交付压力下帮我省了太多精力。
6. 评估指标与落地数据:识别率之外更重要的东西
6.1 样本库建设与标注
说到落地,先解决一个很现实的问题:你拿什么评估系统“好用”?
很多现场项目没有现成的标注数据集。我的办法是前期每天让质检员把人工检出、系统漏掉的缺陷图攒下来,单独存一个漏检库。同时把系统报警但人工确认没问题的图存到另一个过检库。跑一个月,两个库加起来就有几百张真实缺陷样本。
标注统一规则很重要:刀丝要标出起止点和宽度区域,蹭脏要标轮廓,模糊的边缘怎么算、算不算,都要定义清楚。否则两个标注员画的框不统一,评估指标就没法看。
6.2 四个核心指标与实测结果
我最后盯的是四个指标:
| 指标 | 含义 | 实测值 |
|---|---|---|
| 检出率 | 有缺陷且被系统检出的比例 | 97.3% |
| 漏检率 | 有缺陷但系统未检出的比例 | 2.7% |
| 过检率 | 无缺陷但系统报警的比例 | 0.8% |
| 单张处理时间 | 每张图像的完整处理耗时 | 37ms |
单张37ms意味着产线速度在1米/秒时,处理能力完全可以覆盖采集速度,不会形成积压。漏检主要集中在两类:极浅的蹭脏(灰度差只有10左右,肉眼勉强能看到)和轮廓型刀丝。过检则集中在深色油墨区域的废屑,灰度差和真实缺陷几乎没有区分度。
对于这类系统,我的经验是先保证检出率,把参数放宽,宁可多报一点;等检出率稳定在97%以上了再压过检率。反过来做很容易翻车——参数一开始调太严,漏检了都不知道漏在哪。
6.3 上线调试的顺序和避坑经验
顺序很重要,别跳过步骤直接调阈值。我复盘了一下,这套系统成功落地的调试顺序是:
第一步,确认图像质量。打开实时采集画面,看画面是否清晰、是否有运动模糊、光照是否均匀。图像质量不行,后面算法再好都白搭。
第二步,确认差影效果。把当前图和背景模板直接做差,看无缺陷区域是否干净——如果无缺陷区域差影后还有大量噪声,说明对齐有问题或者光照有波动,先解决这类系统性问题。
第三步,调阈值分割参数。这里慢工出细活,每次改参数后用同一批历史样本回放对比,不要一次调太多。
第四步,调分类规则。每个规则都留出“未分类”状态,让未知情况先报警但不分类,人工确认后再补规则。
这套流程走下来,系统才能从“实验室Demo”变成“产线能用”的状态。
最后说一个很多项目复盘不会提的体会:这家客户最后验收时最关心的其实不是检出率97.3%这个数字,而是过检率。过检率高了,质检员全天都在处理虚假报警,几分钟就烦了,最后直接把系统关掉。所以做这类项目,一定要在过检率上死磕到底——哪怕漏检稍微高零点几个点,只要过检率压得住,系统就有活路;反过来,再漂亮的检出率也撑不住一个被现场操作员讨厌的系统。