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) 亮度偏高,适合高亮场景
我的习惯: 直接用OpenCV的 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。

它把图像分成一个个小块,在每个小块内做均衡化,然后用插值消除块与块之间的边界。效果比全局均衡化好得多,尤其适合光照不均匀的场景。

避坑指南: 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 三者串联:一个完整的预处理流程

在实际项目中,这三个操作通常是串联使用的。我一般按这个顺序来:

  1. 灰度化:彩色图转单通道。
  2. 高斯滤波:先降噪,避免后续均衡化放大噪声。
  3. 直方图均衡化:增强对比度,让缺陷更明显。

顺序为什么重要?

如果你先做均衡化,噪声会被放大,再做滤波虽然能压下去一点,但效果已经打了折扣。所以,先滤波,再增强,这是我在项目里踩过坑之后总结出来的经验。

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 本章知识体系

下面这张图,帮你把三个预处理操作的关系理清楚:

图像预处理基础:三大核心操作 原始图像 灰度化 高斯滤波 直方图均衡化 预处理完成 处理顺序 ① 灰度化 ② 高斯滤波 ③ 直方图均衡化 核心目的 减少数据量 抑制噪声 增强对比度
我的建议: 别把预处理当成固定套路。每个项目的光照、材质、缺陷类型都不一样。多试几组参数,找到最适合你数据的那一套。