4、经典去噪算法(一):均值滤波、高斯滤波、中值滤波的原理与HDR适用性分析
说到图像去噪,很多新手第一反应就是「模糊一下」。嗯,这话对了一半。经典滤波算法确实是去噪的基石,但用在HDR图像上,稍不注意就会把好不容易保住的暗部细节给抹掉。
我个人习惯把这三兄弟放在一起讲,因为它们代表了两种完全不同的思路:线性滤波(均值、高斯)和非线性滤波(中值)。搞懂了它们的脾性,你才知道什么时候该用谁。
4.1 均值滤波:最朴素,但也最「暴力」
均值滤波的原理,说白了就是拿一个窗口在图像上滑动,把窗口内所有像素的亮度值加起来求个平均,然后用这个平均值替换中心像素的值。
数学表达式:
g(x, y) = (1 / (m × n)) × Σ f(i, j) (i, j ∈ 窗口W)
其中 m×n 是窗口大小,f(i,j) 是原始像素值。
举个例子: 一个 3×3 的窗口,里面有9个像素值分别是 [10, 12, 11, 13, 100, 12, 11, 10, 12]。均值滤波会把中心像素(假设是那个100的噪点)替换成 (10+12+11+13+100+12+11+10+12)/9 ≈ 21.2。你看,噪点被「拉」下来了,但周围正常的像素也被「拉」高了。
HDR适用性分析:
| 维度 | 评价 | 原因 |
|---|---|---|
| 去噪能力 | 中等 | 对高斯噪声有一定效果,但对椒盐噪声几乎无效 |
| 边缘保留 | 极差 | 所有边缘都会被模糊,HDR中的高对比边缘会「化开」 |
| 暗部细节 | 差 | 暗部噪声被平均后,细节被噪声淹没 |
| 计算速度 | 快 | 只有加法和除法,适合实时预览 |
| HDR推荐度 | ★☆☆☆☆ | 基本不推荐单独使用 |
4.2 高斯滤波:给邻居「打分」的聪明版
高斯滤波和均值滤波最大的区别在于:它不再一视同仁,而是根据像素距离中心点的远近,分配不同的权重。离得越近,权重越大;离得越远,权重越小。这个权重分布服从高斯函数(也就是正态分布)。
为什么叫「高斯」? 因为权重模板(卷积核)就是由高斯函数生成的。你想想看,图像中一个像素和它周围的像素,相关性肯定是随着距离衰减的,高斯滤波正好模拟了这个特性。
数学表达式:
G(x, y) = (1 / (2πσ²)) × exp(-(x² + y²) / (2σ²))
其中 σ(sigma)是标准差,控制了权重的衰减速度。σ 越大,权重分布越平坦,滤波效果越接近均值滤波;σ 越小,中心像素的权重越大,滤波效果越弱。
HDR适用性分析:
| 维度 | 评价 | 原因 |
|---|---|---|
| 去噪能力 | 良好 | 对高斯噪声效果很好,是经典的高斯噪声滤波器 |
| 边缘保留 | 一般 | 比均值滤波好,但边缘仍然会被平滑 |
| 暗部细节 | 中等 | 通过调节σ可以部分保留暗部纹理 |
| 计算速度 | 中等 | 需要计算权重乘法,但可分离加速 |
| HDR推荐度 | ★★★☆☆ | 可作为预处理步骤,但需配合其他算法 |
4.3 中值滤波:专治「椒盐噪声」的猛药
中值滤波的思路完全不一样。它不再做加权平均,而是把窗口内的所有像素值排序,然后取中间那个值(中位数)作为输出。
举个例子: 还是刚才那个窗口 [10, 12, 11, 13, 100, 12, 11, 10, 12]。排序后是 [10, 10, 11, 11, 12, 12, 12, 13, 100],中位数是 12。你看,那个100的噪点直接被「踢」出去了,而周围的正常值几乎没受影响。
为什么会这样?因为中位数对极端值不敏感。100这个值再大,只要它排在两端,就不会影响中间那个数的选取。
HDR适用性分析:
| 维度 | 评价 | 原因 |
|---|---|---|
| 去噪能力 | 椒盐噪声极好,高斯噪声一般 | 对孤立噪点非常有效,但对连续噪声乏力 |
| 边缘保留 | 良好 | 不会产生线性滤波的模糊效应,边缘相对清晰 |
| 暗部细节 | 中等偏上 | 对暗部孤立噪点去除效果好,但窗口太大会抹掉纹理 |
| 计算速度 | 慢 | 排序操作比较耗时,窗口越大越慢 |
| HDR推荐度 | ★★★★☆ | 适合去除HDR合成中产生的异常像素点 |
4.4 三种算法对比与HDR选型指南
好了,我们把三兄弟拉出来遛遛。下面这张SVG图帮你理清思路:
4.5 实战建议:HDR图像中怎么选?
讲完了原理,咱们来点实际的。HDR图像和普通图像最大的区别是什么?动态范围大。亮部可能到1000尼特,暗部可能只有0.1尼特。噪声在暗部被放大,在亮部几乎看不见。
所以,我的建议是:
- 不要全局使用同一种滤波。亮部和暗部应该区别对待。暗部用弱滤波(小窗口、小σ),亮部可以适当加强。
- 均值滤波基本可以放弃。在HDR场景下,它的缺点被放大了。除非你只是做快速预览。
- 高斯滤波作为基础。我习惯先用σ=1.2的高斯滤波做一次轻量去噪,把大部分高斯噪声压下去。
- 中值滤波做「清道夫」。在HDR合成过程中,如果出现了明显的异常像素(比如合成算法导致的边缘伪影),用3×3或5×5的中值滤波局部处理。
4.6 代码示例:OpenCV实现与效果对比
光说不练假把式。下面用OpenCV演示三种滤波的效果,你可以直接跑跑看。
import cv2
import numpy as np
# 读取HDR图像(假设已经是线性数据)
img = cv2.imread('hdr_scene.hdr', cv2.IMREAD_ANYDEPTH)
# 均值滤波
mean_blur = cv2.blur(img, (5, 5))
# 高斯滤波
gaussian_blur = cv2.GaussianBlur(img, (5, 5), 1.2)
# 中值滤波
median_blur = cv2.medianBlur(img, 5)
# 保存结果(使用EXR格式保留HDR数据)
cv2.imwrite('mean_filter.exr', mean_blur)
cv2.imwrite('gaussian_filter.exr', gaussian_blur)
cv2.imwrite('median_filter.exr', median_blur)
print("三种滤波结果已保存,请用HDR查看器对比暗部区域。")
关键参数说明:
cv2.blur(img, (5,5)):5×5窗口的均值滤波。窗口越大,模糊越强。cv2.GaussianBlur(img, (5,5), 1.2):5×5窗口,σ=1.2的高斯滤波。窗口大小和σ要匹配,一般窗口大小取 2×ceil(2σ)+1。cv2.medianBlur(img, 5):5×5窗口的中值滤波。窗口大小必须是奇数。
好了,这一章的内容就到这里。三种经典滤波算法,各有各的脾气。均值滤波简单但粗暴,高斯滤波灵活但需要调参,中值滤波专治「刺头」噪点。在HDR场景下,我的建议是:以高斯滤波为基底,以中值滤波为补充,千万别指望一种算法打天下。