3、图像预处理与增强:去噪算法对比(高斯/中值/双边)、直方图均衡化、数据增强策略

各位同学好,我是老张。今天咱们聊聊图像预处理这块硬骨头。说实话,在缺陷检测项目里,预处理做得好不好,直接决定了后面算法的上限。我见过太多人一上来就扔模型,结果效果不好,回头才发现是图像质量本身就有问题。

嗯,咱们今天重点讲三个方向:去噪、直方图均衡化、数据增强。每个我都会结合实战经验来讲。

3.1 去噪算法对比:高斯、中值、双边滤波

先说说去噪。工业场景下,噪声来源五花八门——传感器热噪声、光照波动、传输干扰等等。选对去噪算法,能省掉后面很多麻烦。

3.1.1 高斯滤波

高斯滤波是最基础的。它的原理说白了就是加权平均——离中心像素越近,权重越大。我习惯用它处理高斯噪声,比如传感器在弱光下产生的噪声。

import cv2
import numpy as np

# 高斯滤波
img = cv2.imread('defect_sample.jpg')
gaussian = cv2.GaussianBlur(img, (5, 5), 1.5)

这里有个坑:核大小必须是奇数,而且sigma值要跟核大小匹配。我一般用sigma=1.5配合5x5核,效果比较均衡。

注意:高斯滤波会模糊边缘。如果你的缺陷本身就是边缘特征(比如划痕、裂纹),高斯滤波可能会把缺陷一起抹掉。我曾经在一个划痕检测项目里吃过这个亏,后来换成了双边滤波。

3.1.2 中值滤波

中值滤波对付椒盐噪声特别管用。什么是椒盐噪声?就是图像上随机出现的黑白点,像撒了盐和胡椒一样。

它的原理很简单:把窗口内的像素排序,取中间值替换中心像素。你想想看,一个孤立的噪声点,排序后肯定在两端,取中间值就把它干掉了。

# 中值滤波
median = cv2.medianBlur(img, 5)

我个人习惯在PCB焊点检测中用中值滤波。因为焊点图像经常有反光造成的椒盐噪声,中值滤波能干净地去掉,同时保留焊点的轮廓。

小技巧:中值滤波的核大小一般取3、5、7。核越大,去噪越强,但图像细节损失也越大。我建议从3开始试,不够再加。

3.1.3 双边滤波

双边滤波是去噪算法里的「高材生」。它同时考虑空间距离和像素值差异,所以能去噪的同时保留边缘。

为什么能做到?因为它有两个权重:一个是空间高斯权重(距离越近权重越大),另一个是像素值高斯权重(像素值越接近权重越大)。边缘处的像素值差异大,所以边缘不会被模糊。

# 双边滤波
bilateral = cv2.bilateralFilter(img, 9, 75, 75)

参数说明:第一个是核大小,第二个是像素值域sigma,第三个是空间域sigma。我一般把后两个设成相同值,从50开始调。

实战对比:在手机屏幕划痕检测中,高斯滤波会把划痕边缘模糊掉,中值滤波对细划痕保留不够好,而双边滤波能在去噪的同时清晰保留划痕边缘。我最终选的就是双边滤波。

3.1.4 三种算法对比表

算法 适用噪声 边缘保留 速度 典型场景
高斯滤波 高斯噪声 均匀光照下的表面检测
中值滤波 椒盐噪声 中等 中等 PCB焊点、金属表面
双边滤波 混合噪声 精密零件、屏幕检测

3.2 直方图均衡化

直方图均衡化,说白了就是把图像的灰度分布拉开。有些图像整体偏暗或偏亮,细节都挤在一起看不清,均衡化之后就能看清楚了。

3.2.1 全局直方图均衡化

# 全局直方图均衡化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
equalized = cv2.equalizeHist(gray)

这个方法简单粗暴,但有个问题:它会增强噪声。如果原图噪声多,均衡化后噪声会更明显。我一般在去噪之后再做均衡化。

3.2.2 自适应直方图均衡化(CLAHE)

CLAHE是改进版。它把图像分成小块,每块单独做均衡化,然后用插值拼接。这样能避免全局均衡化带来的局部过亮或过暗问题。

# CLAHE
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahe_img = clahe.apply(gray)

clipLimit参数控制对比度限制,我一般设2.0到3.0。tileGridSize是分块大小,8x8是常用值。

我的经验:在纺织物缺陷检测中,布料纹理不均匀,全局均衡化效果很差。改用CLAHE后,纹理变得均匀,缺陷(断纱、污渍)一目了然。这个坑我踩过,所以特别推荐CLAHE。

3.3 数据增强策略

数据增强是深度学习时代的必修课。说白了就是「无中生有」——用有限的样本生成更多变体,让模型见过更多情况。

3.3.1 几何变换

  • 旋转:±15°以内,太大可能失真
  • 翻转:水平翻转、垂直翻转
  • 缩放:0.8~1.2倍
  • 裁剪:随机裁剪后resize回原尺寸

3.3.2 颜色变换

  • 亮度调整:±20%
  • 对比度调整:±20%
  • 饱和度调整:±20%
  • HSV扰动:在HSV空间随机偏移

3.3.3 噪声模拟

  • 高斯噪声:模拟传感器噪声
  • 椒盐噪声:模拟传输干扰
  • 模糊:模拟对焦不准
# 使用imgaug库做数据增强
import imgaug.augmenters as iaa

seq = iaa.Sequential([
    iaa.Fliplr(0.5),  # 水平翻转
    iaa.Affine(rotate=(-15, 15)),  # 旋转
    iaa.Multiply((0.8, 1.2)),  # 亮度调整
    iaa.AdditiveGaussianNoise(scale=(0, 0.05*255))  # 高斯噪声
])

augmented_images = seq(images=images)

注意:数据增强不是越多越好。我见过有人把图像旋转90度、180度,结果模型把倒立的缺陷当成了正常样本。增强策略要跟实际场景匹配——你的产品在产线上会倒着放吗?不会就别做这种增强。

3.3.4 实战策略建议

我个人习惯用「三步走」策略:

  1. 第一步:先做几何变换(翻转、小角度旋转)
  2. 第二步:再做颜色变换(亮度、对比度微调)
  3. 第三步:最后加少量噪声(模拟真实环境)

顺序很重要。先做几何变换,再做颜色变换,最后加噪声。为什么?因为几何变换后插值会引入伪影,颜色变换和噪声可以掩盖这些伪影。

核心总结:预处理不是流水线作业,而是「对症下药」。去噪选对算法、均衡化用CLAHE、增强要贴合场景。这三板斧练好了,你的缺陷检测模型至少能提升5-10个点的准确率。

好了,这一章就讲到这里。下一章咱们聊聊特征提取——怎么从预处理后的图像里找到真正的缺陷特征。到时候我会分享一个我踩过的坑,关于特征维度爆炸的问题,挺有意思的。