2. 图像预处理基础
做缺陷检测,不管是传统算法还是深度学习,第一步都是把图像“伺候”好。
我见过不少新手,拿到图像就直接扔给模型。结果呢?光照一变,检测就崩。说白了,预处理做不好,后面全是白忙活。
这一章,咱们就聊聊三个最基础、也最常用的预处理操作:灰度化、直方图均衡化、高斯滤波。它们就像炒菜前的洗菜切菜,看似简单,但火候不对,整盘菜就毁了。
2.1 灰度化:扔掉颜色,保留结构
工业相机拍出来的大多是彩色图。但很多缺陷检测任务,其实不关心颜色。
你想想看,检测划痕、脏污、裂纹,这些缺陷在灰度图上一样明显。去掉颜色,数据量直接降到原来的三分之一,计算速度嗖嗖快。
2.1.1 为什么做灰度化?
- 减少计算量:三通道变单通道,处理速度翻倍。
- 消除光照色温干扰:不同批次的工件可能有色差,灰度化后只看亮度,更稳定。
- 算法兼容性:很多传统算子(如Canny边缘检测)只接受单通道输入。
2.1.2 常用方法
| 方法 | 公式 | 特点 |
|---|---|---|
| 平均值法 | Gray = (R+G+B)/3 | 简单,但丢失细节 |
| 加权平均法 | Gray = 0.299R + 0.587G + 0.114B | 符合人眼感知,最常用 |
| 最大值法 | Gray = max(R,G,B) | 亮度偏高,适合高亮场景 |
cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)。它内部用的就是加权平均法,效果最稳。
import cv2
# 读取彩色图
img = cv2.imread('defect_sample.jpg')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 保存结果
cv2.imwrite('gray_output.jpg', gray)
2.2 直方图均衡化:让对比度“支棱”起来
有时候拍出来的图像灰蒙蒙的,像蒙了一层雾。划痕和背景的灰度值挨得太近,肉眼都看不清,算法就更难了。
这时候就该直方图均衡化上场了。它的原理很简单:把原本集中在狭窄区域的灰度值,拉伸到整个0-255范围。
2.2.1 全局直方图均衡化
适合整体偏暗或偏亮的图像。但有个坑——它会放大噪声。
我曾经在一个金属表面检测项目里,直接用全局均衡化,结果划痕是清楚了,但原本不明显的纹理噪声也被放大了,导致误检率飙升。
# 全局直方图均衡化
equ = cv2.equalizeHist(gray)
2.2.2 自适应直方图均衡化(CLAHE)
为了解决噪声放大问题,我后来改用CLAHE。
它把图像分成一个个小块,在每个小块内做均衡化,然后用插值消除块与块之间的边界。效果比全局均衡化好得多,尤其适合光照不均匀的场景。
clipLimit 参数别设太大。我一般从2.0开始调,太大反而会出现“鬼影”一样的伪影。
# CLAHE 自适应直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahe_img = clahe.apply(gray)
2.3 高斯滤波:去噪但不模糊边缘
工业现场环境复杂,图像里难免有噪声。椒盐噪声、高斯噪声……如果不处理,后续的边缘检测、阈值分割都会受影响。
高斯滤波是去噪的“万金油”。它用高斯核与图像做卷积,每个像素的值被它周围像素的加权平均替代。权重由高斯分布决定——离中心越近,权重越大。
2.3.1 高斯核大小怎么选?
| 核大小 | 效果 | 适用场景 |
|---|---|---|
| 3×3 | 去噪弱,保留细节好 | 噪声轻微的场景 |
| 5×5 | 去噪适中,细节损失可接受 | 大多数通用场景 |
| 7×7及以上 | 去噪强,但边缘模糊明显 | 噪声严重,且不关心小细节 |
# 高斯滤波
# (5,5) 是核大小,0 是标准差(自动计算)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
2.4 三者串联:一个完整的预处理流程
在实际项目中,这三个操作通常是串联使用的。我一般按这个顺序来:
- 灰度化:彩色图转单通道。
- 高斯滤波:先降噪,避免后续均衡化放大噪声。
- 直方图均衡化:增强对比度,让缺陷更明显。
顺序为什么重要?
如果你先做均衡化,噪声会被放大,再做滤波虽然能压下去一点,但效果已经打了折扣。所以,先滤波,再增强,这是我在项目里踩过坑之后总结出来的经验。
def preprocess_pipeline(img_path):
# 1. 读取图像
img = cv2.imread(img_path)
# 2. 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 3. 高斯滤波(去噪)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 4. CLAHE 增强对比度
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(blurred)
return enhanced
2.5 本章知识体系
下面这张图,帮你把三个预处理操作的关系理清楚: