3. 经典去噪算法(一):均值滤波、高斯滤波、中值滤波的原理与OpenCV实现

图像去噪,说白了就是给图片「洗脸」。

我刚开始做图像处理那会儿,最头疼的就是噪声。一张好好的照片,拍出来全是雪花点,你说烦不烦?后来慢慢摸清了门道,发现去噪这事儿,其实就三板斧:均值滤波、高斯滤波、中值滤波。

今天咱们就把这三兄弟掰开揉碎了讲清楚。

3.1 均值滤波:简单粗暴的平均主义

均值滤波的思路特别朴素——用周围像素的平均值代替中心像素。

你想想看,如果某个像素是噪声点,它跟周围邻居肯定不一样。那我把周围一圈的像素值加起来取个平均,噪声就被「稀释」了。

3.1.1 原理

假设我们有一个3×3的窗口,中心像素是噪声点。均值滤波的做法是:

  • 把窗口内9个像素的灰度值加起来
  • 除以9,得到平均值
  • 把这个平均值赋给中心像素

用数学公式表达就是:

g(x,y) = (1/(m×n)) × Σ f(i,j)

其中m×n是窗口大小,f(i,j)是原始像素值。

核心要点:窗口越大,平滑效果越强,但图像也会越模糊。这是个典型的「鱼和熊掌不可兼得」的问题。

3.1.2 OpenCV实现

import cv2
import numpy as np

# 读取图像
img = cv2.imread('noisy_image.jpg')

# 均值滤波,窗口大小5×5
blurred = cv2.blur(img, (5, 5))

# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Blurred', blurred)
cv2.waitKey(0)

个人经验:我建议窗口大小选奇数,比如3、5、7。为什么?因为奇数窗口有明确的中心像素,处理起来更自然。偶数窗口虽然也能用,但边界处理会麻烦一些。

3.2 高斯滤波:给邻居们分个亲疏远近

均值滤波有个明显的问题——它把窗口内所有像素一视同仁。但你想啊,离中心越近的像素,按理说应该越「靠谱」才对。

高斯滤波就是来解决这个问题的。它给每个像素分配一个权重,距离中心越近,权重越大。

3.2.1 原理

高斯滤波的核心是高斯核。这个核长什么样呢?

一个3×3的高斯核(σ=0.8):
[1, 2, 1]
[2, 4, 2]
[1, 2, 1]

你看,中心像素的权重是4,四个角上的像素权重只有1。这就是「近朱者赤,近墨者黑」的数学表达。

高斯核的生成公式:

G(x,y) = (1/(2πσ²)) × exp(-(x²+y²)/(2σ²))

其中σ是标准差,控制着权重的分布范围。

避坑指南:我曾经在项目里把σ设得太大,结果图像糊成一团。记住,σ越大,平滑效果越强,但细节丢失也越严重。一般建议σ取0.8到1.5之间。

3.2.2 OpenCV实现

# 高斯滤波,窗口5×5,σ=1.0
gaussian = cv2.GaussianBlur(img, (5, 5), 1.0)

# 也可以只指定σ,让OpenCV自动计算窗口大小
gaussian_auto = cv2.GaussianBlur(img, (0, 0), 1.0)

小技巧:如果你不确定窗口大小该设多少,可以只传σ值,把窗口设为(0,0)。OpenCV会根据σ自动计算合适的窗口大小。我个人习惯用这种方法,省心。

3.3 中值滤波:专治椒盐噪声的猛药

前面两种滤波都是线性滤波,说白了就是做加减乘除。但有些噪声,比如椒盐噪声(黑白点),用线性滤波效果很差。

为什么?因为椒盐噪声的值要么是0(黑),要么是255(白),取平均之后会把周围的像素也带偏。

中值滤波的思路完全不同——它取窗口内所有像素的中位数。

3.3.1 原理

假设窗口内有9个像素值:

[12, 15, 18, 20, 255, 22, 25, 28, 30]

排序后:

[12, 15, 18, 20, 22, 25, 28, 30, 255]

中位数是22,用它代替中心像素。你看,那个255的噪声点直接被跳过了。

核心优势:中值滤波对椒盐噪声有奇效,而且能很好地保留边缘信息。这是线性滤波做不到的。

3.3.2 OpenCV实现

# 中值滤波,窗口大小3
median = cv2.medianBlur(img, 3)

# 对于椒盐噪声严重的图像,可以加大窗口
median_strong = cv2.medianBlur(img, 5)

注意:中值滤波的窗口大小必须是奇数。我见过有人传了偶数进去,结果程序直接报错。嗯,这个坑我踩过。

3.4 三种滤波的对比

说了这么多,咱们来做个对比总结:

滤波类型 原理 适用场景 优点 缺点
均值滤波 取平均值 高斯噪声 简单快速 边缘模糊严重
高斯滤波 加权平均 高斯噪声 边缘保留较好 计算量稍大
中值滤波 取中位数 椒盐噪声 边缘保留最好 对高斯噪声效果一般

3.5 知识体系总览

下面这张图,是我梳理的本章知识结构。你看一眼就能明白三种滤波的关系和区别:

经典去噪算法知识体系 图像去噪 均值滤波 高斯滤波 中值滤波 取平均值 边缘模糊 加权平均 σ控制权重 取中位数 抗椒盐噪声 选择建议: 高斯噪声 → 高斯滤波 | 椒盐噪声 → 中值滤波 | 快速处理 → 均值滤波

3.6 实战建议

最后,分享几个我在项目中积累的经验:

  1. 先看噪声类型——如果是椒盐噪声,直接上中值滤波;如果是高斯噪声,高斯滤波更合适。
  2. 窗口从小试起——我习惯从3×3开始,效果不够再加大。一上来就用大窗口,容易把细节搞丢。
  3. 边界要处理好——OpenCV默认的边界处理方式是复制边缘像素,但如果你有特殊需求,可以用borderType参数调整。
  4. 别迷信单一滤波——有时候把两种滤波组合起来用,效果反而更好。比如先中值滤波去椒盐噪声,再高斯滤波平滑细节。

一个小测试:你可以找一张带噪声的图片,分别用三种滤波处理一下,看看效果差异。我保证,亲手试过之后,你对它们的理解会深很多。

专注资料整理