圖像預處理之去噪方法(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對高斯濾波的影響~

小夜