图像预处理之去噪方法(Python OpenCV入门)

一、为什么要去噪?

图像在采集或传输过程中,常常会受到各种噪声干扰,比如:
- 高斯噪声:类似“盐粒”般随机分布的亮点(高频噪声,常见于传感器);
- 椒盐噪声:黑白斑点(如相机传感器灰尘、传输错误导致的0或255像素值);
- 泊松噪声:与图像亮度相关的随机噪声(低光环境常见)。

噪声会模糊图像细节,影响后续任务(如目标检测、人脸识别)的准确性。去噪是图像预处理的核心步骤,目的是保留有用信息的同时去除干扰。

二、Python OpenCV基础准备

首先确保已安装OpenCV和NumPy:

pip install opencv-python numpy matplotlib

核心操作:
- 读取图像:cv2.imread()(默认BGR格式,可转RGB用于显示);
- 显示图像:cv2.imshow()(需配合cv2.waitKey()cv2.destroyAllWindows());
- 常用工具:np.array处理噪声生成,matplotlib可视化对比。

三、经典去噪方法及代码实现

1. 均值滤波(简单平均去噪)

原理:用一个小窗口(如3×3)覆盖图像,将窗口内所有像素的平均值作为中心像素值。
特点:简单快速,但会模糊边缘(因平均化),适合高斯噪声(高频随机噪声)。

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像(示例:假设图像路径为'input.jpg')
img = cv2.imread('input.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转RGB用于matplotlib显示

# 生成带高斯噪声的图像(模拟噪声)
noise = np.random.normal(0, 20, img.shape).astype(np.uint8)
noisy_img = cv2.add(img, noise)  # 叠加噪声

# 均值滤波(3×3窗口)
mean_denoised = cv2.blur(noisy_img, (3, 3))  # 核大小必须是整数

# 可视化对比
plt.figure(figsize=(12, 6))
plt.subplot(131), plt.imshow(img_rgb), plt.title('Original')
plt.subplot(132), plt.imshow(noisy_img), plt.title('Noisy')
plt.subplot(133), plt.imshow(mean_denoised), plt.title('Mean Filter')
plt.show()
2. 中值滤波(椒盐噪声克星)

原理:用窗口内像素的中值(排序后中间值)代替中心像素,对极端值(如0/255噪声点)不敏感。
特点:对椒盐噪声效果极佳,保留边缘能力强,核大小需为奇数(如3、5)。

# 生成带椒盐噪声的图像(手动制造噪声)
def add_salt_pepper_noise(img, prob=0.02):
    noisy = np.copy(img)
    h, w = noisy.shape[:2]
    for i in range(h):
        for j in range(w):
            if np.random.random() < prob:
                noisy[i, j] = 0 if np.random.random() < 0.5 else 255  # 50%概率黑/白
    return noisy

noisy_salt = add_salt_pepper_noise(img_rgb)  # 转换为RGB后处理
median_denoised = cv2.medianBlur(noisy_salt, 3)  # 3×3核

# 可视化
plt.figure(figsize=(12, 6))
plt.subplot(131), plt.imshow(img_rgb), plt.title('Original')
plt.subplot(132), plt.imshow(noisy_salt), plt.title('Salt & Pepper Noise')
plt.subplot(133), plt.imshow(median_denoised), plt.title('Median Filter')
plt.show()
3. 高斯滤波(更智能的加权平均)

原理:用高斯分布的卷积核(中心权重最高)加权平均像素值,既平滑噪声又保护边缘。
特点:比均值滤波更柔和,适合高斯噪声,需指定核大小(奇数)和标准差sigma

# 高斯滤波(核大小3×3,sigmaX=1)
gaussian_denoised = cv2.GaussianBlur(noisy_img, (3, 3), sigmaX=1)

# 可视化
plt.figure(figsize=(12, 6))
plt.subplot(131), plt.imshow(noisy_img), plt.title('Noisy')
plt.subplot(132), plt.imshow(cv2.cvtColor(gaussian_denoised, cv2.COLOR_BGR2RGB)), plt.title('Gaussian Filter')
plt.show()
4. 双边滤波(去噪+保边)

原理:结合空间距离(窗口内像素加权)和颜色相似性(颜色越近权重越高),保留边缘的同时去噪。
特点:计算量较大,但能处理“高频噪声”且边缘清晰,适合人脸、风景等需保边的场景。

# 双边滤波(直径=9,颜色标准差=75,空间标准差=75)
bilateral_denoised = cv2.bilateralFilter(noisy_img, 9, 75, 75)

# 可视化
plt.figure(figsize=(12, 6))
plt.subplot(131), plt.imshow(noisy_img), plt.title('Noisy')
plt.subplot(132), plt.imshow(cv2.cvtColor(bilateral_denoised, cv2.COLOR_BGR2RGB)), plt.title('Bilateral Filter')
plt.show()

四、方法选择指南

噪声类型 推荐方法 核大小建议 核心优势
高斯噪声 高斯滤波 3×3/5×5 加权平均,保护边缘
椒盐噪声 中值滤波 3×3/5×5 抗极端值,黑白斑点去噪
混合噪声 先高斯后中值 3×3→3×3 兼顾两种噪声特性
高频细节噪声 双边滤波 5×5/9×9 去噪同时保留轮廓、纹理边缘

五、总结

  • 均值滤波:简单快速,但模糊边缘;
  • 中值滤波:椒盐噪声“杀手”,保边能力强;
  • 高斯滤波:平衡噪声抑制与边缘保留;
  • 双边滤波:高级去噪保边,适合高精度场景。

初学者可从高斯滤波中值滤波入手,根据噪声类型选择(如照片偏暗→先高斯,监控画面有斑点→先中值),后续可尝试双边滤波优化细节!

练习:尝试不同核大小(如5×5)观察去噪效果,对比参数sigma对高斯滤波的影响~

小夜