4. 图像预处理基础

在Halcon视觉检测项目中,图像预处理是决定检测算法成败的第一道关卡。很多初学者习惯直接对采集到的原始图像运行阈值分割或边缘提取算子,结果往往因为光照波动、噪声干扰或背景纹理复杂而导致检测结果极不稳定。本章将系统梳理灰度化、滤波、增强、阈值分割四类基础操作的原理、Halcon实现方法及其在真实检测场景中的定位,帮助您建立“预处理服务于检测目标”的工程思维。

4.1 核心原理:为什么检测前必须做预处理

工业相机采集到的原始图像是传感器对光响应的数字化结果,其中包含目标信息、背景信息、噪声以及光照不均匀带来的灰度漂移。检测算法的鲁棒性取决于输入图像的质量,而预处理的核心目标并非“让图像好看”,而是扩大目标与背景的可区分度,抑制与检测无关的干扰成分。

从信号处理角度看,预处理本质是一个滤波与变换的过程:灰度化将三维彩色信息压缩到单通道灰度空间,降低计算复杂度;滤波在频域或空间域抑制噪声;增强通过灰度映射拉伸对比度;阈值分割则根据灰度分布将像素划分为前景与背景。四者层层递进,构成一条典型的图像预处理流水线。

工程经验:预处理参数不应“一次调好永久使用”。同一产线在不同时段(如早晨与傍晚)的自然光变化、不同批次工件的表面反光差异,都可能导致最优参数漂移。建议在Halcon中建立预处理参数与检测结果的联动监控,必要时引入自适应阈值或动态滤波策略。

4.2 灰度化:从多通道到单通道的降维

Halcon中彩色图像通常以RGB三通道表示,但绝大多数检测算法(如阈值分割、形态学、Blob分析)基于灰度图像运行。灰度化的本质是加权求和,Halcon默认采用ITU-R BT.601标准:

Gray = 0.299 * R + 0.587 * G + 0.114 * B

在Halcon中,使用 rgb1_to_gray 算子完成转换:

read_image (Image, 'color_image.png')
rgb1_to_gray (Image, GrayImage)
* 若图像已经是单通道,则无需转换

灰度化在检测中的作用:

  • 降低计算量:单通道处理速度约为三通道的1/3,对高速产线至关重要。
  • 消除颜色干扰:当检测目标与背景颜色差异明显但灰度接近时,灰度化反而会丢失信息,此时应保留彩色通道或使用HSV空间。
  • 统一处理接口:后续滤波、阈值分割算子大多只接受单通道输入。
误区提醒:不要盲目对所有图像执行灰度化。若检测目标依赖颜色信息(如区分红色标签与蓝色标签),灰度化将导致信息不可逆丢失。此时应使用 decompose3 分离通道,或转换到HSV空间后对H(色相)通道做阈值分割。

4.3 滤波:抑制噪声,保留边缘

噪声是图像中随机出现的灰度突变,来源包括传感器热噪声、电磁干扰、光照闪烁等。滤波的目标是在不破坏目标边缘的前提下降低噪声。Halcon提供多种滤波器,按原理可分为线性滤波与非线性滤波两类。

4.3.1 常用滤波器对比

滤波器 算子 原理 适用场景 注意事项
均值滤波 mean_image 邻域像素取平均 高斯噪声、轻微噪声 边缘模糊严重,慎用于小目标
高斯滤波 gauss_filter 加权平均,权重服从高斯分布 通用降噪,保留边缘较好 Sigma参数控制平滑程度
中值滤波 median_image 取邻域灰度中值 椒盐噪声、脉冲噪声 对边缘保持优于均值滤波
双边滤波 bilateral_filter 同时考虑空间距离与灰度差 强噪声且需保留精细边缘 计算量大,参数敏感

滤波在检测中的作用:阈值分割对噪声敏感,一个孤立的噪声点可能被误判为目标像素。滤波能显著提升阈值分割的稳定性。例如,在检测PCB板上的微小焊点时,若直接使用全局阈值,噪声点会形成大量假阳性区域;先执行3×3中值滤波,再配合动态阈值,可有效抑制假阳性。

* 中值滤波示例:滤除椒盐噪声
read_image (Image, 'pcb_solder.png')
median_image (Image, ImageMedian, 'circle', 3, 'mirrored')
* 高斯滤波示例:平滑背景纹理
gauss_filter (Image, ImageGauss, 1.5)
参数选择建议:滤波核尺寸不宜超过目标最小尺寸的1/3。例如,检测目标最小宽度为15像素,则滤波核直径应≤5像素。过大的滤波核会抹平小目标,导致后续分割失败。

4.4 增强:拉伸对比度,突出目标

增强的目的是改善图像的灰度分布,使目标与背景的灰度差异更加显著。Halcon中常用的增强方法包括灰度线性拉伸、直方图均衡化、Gamma校正等。

4.4.1 灰度线性拉伸

当图像灰度集中在较窄区间(如100~150)时,直接阈值分割难以区分目标。线性拉伸将灰度范围映射到0~255:

scale_image_max (Image, ImageScaled)
* 自动将最小灰度映射到0,最大灰度映射到255

若需要手动指定拉伸范围,可使用 scale_image:

scale_image (Image, ImageScaled, Mult, Add)
* 输出灰度 = 输入灰度 * Mult + Add

4.4.2 直方图均衡化

直方图均衡化通过重新分布灰度级,使灰度直方图近似均匀分布,从而增强整体对比度。Halcon中使用 equ_histo_image:

equ_histo_image (Image, ImageEquHisto)

增强在检测中的作用:在检测金属表面划痕时,划痕与背景的灰度差异可能仅有10~20个灰度级。通过线性拉伸或直方图均衡化,可将差异放大到50个灰度级以上,使后续阈值分割能够稳定提取划痕区域。

工程技巧:增强操作应谨慎使用。过度增强会放大噪声,导致阈值分割产生大量碎小区域。建议在增强后立即观察灰度直方图,确认目标与背景是否形成双峰分布。若双峰不明显,应返回调整滤波参数,而非继续加大增强力度。

4.5 阈值分割:从灰度到二值的关键一步

阈值分割将灰度图像转换为二值图像(前景=255,背景=0),是Blob分析、形态学处理、特征提取的前提。Halcon提供多种阈值分割方法,选择依据是灰度直方图的分布特征。

4.5.1 全局阈值

当目标与背景灰度差异明显且光照均匀时,使用 threshold 算子:

threshold (Image, Region, MinGray, MaxGray)
* 示例:提取灰度在100~200之间的区域
threshold (Image, Region, 100, 200)

4.5.2 自动阈值

当最优阈值未知时,可使用 binary_threshold 自动计算:

binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold)
* 'max_separability' 基于Otsu方法,'dark'表示提取暗色目标

4.5.3 局部阈值

当光照不均匀导致图像不同区域灰度基准不同时,全局阈值失效。此时使用 local_threshold 或 dyn_threshold:

local_threshold (Image, Region, 'adapted', 15, 'dark')
* 基于局部灰度统计自适应计算阈值

阈值分割在检测中的作用:阈值分割是连接预处理与特征提取的桥梁。分割结果的质量直接影响后续区域面积、周长、圆度等特征计算的准确性。例如,在检测轴承滚珠数量时,若阈值分割将两个相邻滚珠粘连为一个区域,计数将产生严重偏差。

常见误区:阈值分割并非越“干净”越好。过度分割(将目标拆成多个碎片)与欠分割(目标与背景粘连)都是问题。建议在分割后使用 connection 算子将连通域分离,并通过面积、形状等特征过滤干扰区域,而非单纯依赖阈值参数调整。

4.6 案例:轴承表面缺陷检测的预处理流程

以轴承外圈表面划痕检测为例,完整展示预处理流水线的搭建过程。

场景描述:轴承外圈表面可能存在细微划痕(宽度2~5像素,灰度比背景暗30~50级),同时表面有油污反光造成的亮斑噪声,光照为环形LED光源,存在轻微不均匀性。

预处理流程:

  1. 灰度化:若相机输出为彩色,先执行 rgb1_to_gray。
  2. 中值滤波:使用 median_image (Image, ImageMedian, 'circle', 3, 'mirrored') 去除油污反光产生的椒盐噪声。
  3. 高斯滤波:使用 gauss_filter (ImageMedian, ImageGauss, 1.2) 平滑金属表面细微纹理,避免纹理被误判为划痕。
  4. 对比度增强:使用 scale_image_max 拉伸灰度范围,使划痕与背景差异更显著。
  5. 局部阈值分割:由于光照不均匀,使用 local_threshold (ImageGauss, Region, 'adapted', 15, 'dark') 提取暗色划痕区域。
  6. 形态学后处理:使用 opening_circle 去除小于划痕宽度的孤立噪点,使用 connection 分离连通域。
* 完整Halcon代码片段
read_image (Image, 'bearing_surface.png')
rgb1_to_gray (Image, GrayImage)
median_image (GrayImage, ImageMedian, 'circle', 3, 'mirrored')
gauss_filter (ImageMedian, ImageGauss, 1.2)
scale_image_max (ImageGauss, ImageScaled)
local_threshold (ImageScaled, Region, 'adapted', 15, 'dark')
opening_circle (Region, RegionOpening, 2.5)
connection (RegionOpening, ConnectedRegions)
* 后续可通过 select_shape 筛选面积、长度等特征

效果验证:对比未预处理直接阈值分割的结果,预处理后划痕区域的完整度提升约40%,假阳性区域数量下降约70%。这验证了预处理流水线在真实检测场景中的核心价值。

4.7 误区与复盘:预处理中的常见工程陷阱

在实际项目调试中,以下误区反复出现,值得重点复盘:

  • 误区一:滤波核越大越好。大核滤波虽然降噪明显,但会严重模糊边缘,导致后续阈值分割无法精确定位目标边界。正确做法是选择能抑制噪声的最小核尺寸。
  • 误区二:增强后阈值分割失败就继续增强。这往往导致噪声被同步放大。应回头检查滤波是否充分,或改用局部阈值方法。
  • 误区三:所有场景都用全局阈值。在光照不均匀、目标灰度变化大的场景中,全局阈值必然失效。应优先考虑 local_threshold 或 dyn_threshold。
  • 误区四:忽略预处理对检测速度的影响。中值滤波、双边滤波等计算量较大,在高速产线(如每秒检测50个工件)中可能成为瓶颈。应使用 count_seconds 测量各算子耗时,必要时用高斯滤波替代中值滤波。
复盘方法论:当检测结果不稳定时,不要直接修改阈值参数。建议按以下顺序排查:① 检查原始图像质量(是否过曝、欠曝);② 检查滤波是否有效抑制噪声;③ 检查增强是否过度放大噪声;④ 检查阈值分割方法是否匹配灰度分布;⑤ 检查形态学后处理是否合理。每一步都通过 dev_display 可视化中间结果,定位问题环节。