第四节:图像预处理——给机器视觉“擦亮眼睛”

各位工程师朋友,大家好。今天我们来聊聊视觉定位里最基础、也最容易被忽视的一环——图像预处理。

说实话,我见过不少刚入行的朋友,拿到图像就直接丢给算法。结果呢?定位不准、匹配失败,最后怀疑算法有问题。其实很多时候,问题出在“眼睛没擦干净”。

图像预处理,说白了就是让原始图像变得更“友好”。让特征更明显,噪声更少,对比度更合适。这样后续的定位算法才能发挥出真实水平。

核心观点:预处理做得好,定位成功一半。这不是夸张,是我在产线上摔过跟头后的真实体会。

4.1 灰度化:从彩色到单色的“减法”

工业相机拍出来的大多是彩色图像。但视觉定位算法,其实不需要颜色信息。为什么?因为颜色会引入大量冗余数据,增加计算量,而且光照变化时颜色还容易漂移。

灰度化就是把RGB三通道变成单通道。常用的方法有三种:

  • 平均值法:R、G、B三个通道取平均。简单,但效果一般。
  • 加权平均法:人眼对绿色最敏感,对蓝色最不敏感。所以常用公式:Gray = 0.299R + 0.587G + 0.114B。这是OpenCV默认的方式。
  • 最大值法:取三个通道的最大值。适合某些特殊场景。

我个人习惯用加权平均法。有一次在手机屏幕定位项目中,客户要求速度极快。我试了平均值法,结果边缘模糊了,定位精度下降。换成加权平均法后,问题就解决了。你看,一个简单的灰度化,选错了方法也会出问题。

import cv2

# 读取彩色图像
img = cv2.imread('product.jpg')

# 灰度化 - 使用OpenCV内置函数
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 或者手动实现加权平均法
# gray = 0.299 * img[:,:,2] + 0.587 * img[:,:,1] + 0.114 * img[:,:,0]

4.2 直方图均衡化:让对比度“拉满”

你有没有遇到过这种情况?产线上光照不均匀,有的地方太亮,有的地方太暗。这时候直接做定位,特征根本提取不出来。

直方图均衡化就是解决这个问题的。它把图像的灰度分布“拉伸”开,让暗的地方变亮,亮的地方变暗,整体对比度更均匀。

嗯,这里要注意:直方图均衡化对整体偏暗或偏亮的图像效果很好。但如果图像本身对比度已经不错,再用它反而会引入噪声。我曾在一次PCB板定位中吃过这个亏——均衡化后,原本清晰的焊盘边缘反而变得模糊了。

# 直方图均衡化
equalized = cv2.equalizeHist(gray)

# 效果对比
cv2.imshow('Original', gray)
cv2.imshow('Equalized', equalized)

小技巧:如果图像有局部光照不均的问题,试试自适应直方图均衡化(CLAHE)。它能分区域处理,效果更细腻。我在芯片引脚定位项目中用过,定位成功率从82%提升到了97%。

4.3 高斯滤波:温柔的“磨皮”

工业现场难免有噪声。传感器噪声、电磁干扰、灰尘……这些都会让图像出现随机噪点。如果不处理,定位算法可能会把这些噪点当成特征。

高斯滤波是一种线性平滑滤波。它用高斯核与图像做卷积,每个像素的值被周围像素的加权平均替代。权重由高斯分布决定——离中心越近,权重越大。

说白了,就是给图像“磨皮”,但磨得比较温柔,边缘保留得相对好。

# 高斯滤波,核大小5x5,标准差1.5
blurred = cv2.GaussianBlur(gray, (5, 5), 1.5)

核大小怎么选?我一般从3x3开始试。如果噪声还明显,就加大到5x5或7x7。但别太大,否则图像会变得太模糊,细节丢失。有一次在精密零件定位中,我用了9x9的核,结果边缘模糊了0.3个像素,定位精度直接超标。后来改成5x5,刚刚好。

4.4 中值滤波:专治“椒盐噪声”

高斯滤波对高斯噪声效果好,但对椒盐噪声(黑白点噪声)效果一般。这时候中值滤波就派上用场了。

中值滤波的原理很简单:把像素邻域内的所有值排序,取中间值作为新像素值。这样,那些孤立的噪点(特别亮或特别暗)就会被“剔除”。

我在一个螺丝拧紧视觉引导项目中遇到过这种情况:相机旁边有个电机,每次启动都会产生电磁干扰,图像上出现大量白点。高斯滤波根本搞不定,换成中值滤波后,噪点全没了。这就是选对工具的重要性。

# 中值滤波,核大小5x5
median = cv2.medianBlur(gray, 5)

避坑指南:中值滤波的核大小必须是奇数。我曾经手误写成4,程序没报错,但结果完全不对。排查了半天才发现是这个问题。另外,核越大,计算越慢,实时性要求高的产线要谨慎。

4.5 图像增强:让特征“跳出来”

预处理最后一步,是图像增强。目的是让目标特征更明显,背景更干净。

常用的方法有:

  • 锐化:增强边缘和细节。可以用拉普拉斯算子或Sobel算子。
  • 伽马校正:调整图像亮度。伽马值小于1,暗部变亮;大于1,亮部变暗。
  • 形态学操作:膨胀、腐蚀、开运算、闭运算。适合二值图像。
# 拉普拉斯锐化
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
sharpened = cv2.addWeighted(gray, 1.5, laplacian, -0.5, 0)

# 伽马校正
gamma = 0.8  # 让暗部更亮
gamma_corrected = np.power(gray / 255.0, gamma) * 255.0
gamma_corrected = gamma_corrected.astype(np.uint8)

锐化要适度。我见过有人把锐化参数调得特别高,结果图像上全是“光晕”,定位反而更差了。记住:增强的目的是让特征更清晰,不是让图像更“好看”。

知识体系总览

下面这张图,是我自己总结的图像预处理流程。每次做项目前,我都会对照着走一遍,确保没有遗漏。

图像预处理知识体系 原始图像 步骤1:灰度化 步骤2:直方图均衡化 步骤3:滤波(高斯/中值) 步骤4:图像增强(锐化/伽马) 关键参数 • 灰度化:加权平均法 • 均衡化:CLAHE效果更佳 • 高斯滤波:核3x3~7x7 • 中值滤波:核必须奇数 • 锐化:拉普拉斯算子 • 伽马:0.5~1.5常用 避坑提醒: 1. 滤波过度会丢失细节 2. 锐化过度产生光晕 3. 均衡化不适用所有场景

实战建议:预处理流程怎么搭?

说了这么多,到底怎么用?我一般按这个顺序走:

  1. 先灰度化——减少数据量,为后续处理打基础。
  2. 看直方图——如果灰度分布集中,做均衡化;如果分布已经很好,跳过。
  3. 评估噪声类型——高斯噪声用高斯滤波,椒盐噪声用中值滤波。不确定的话,两个都试一下,看效果。
  4. 最后增强——锐化或伽马校正,让特征更突出。

记住:没有万能的预处理流程。每个项目、每张图像都不一样。我的习惯是写一个参数配置文件,把预处理步骤做成可开关的模块。这样调试时,可以快速切换组合,找到最优方案。

最后说一句:预处理不是越复杂越好。有时候,一个简单的灰度化加中值滤波,就能解决80%的问题。别为了炫技而过度处理,产线要的是稳定和速度。


专注资料整理