降噪基础方法:均值滤波、高斯滤波、中值滤波的原理与实现
各位好,欢迎来到降噪基础这一章。HDR 图像处理中,降噪是个绕不开的坎。你想想看,多帧合成虽然能提升动态范围,但暗部区域的噪声往往也被放大了。我个人习惯把降噪比作「给图像做美容」——既要去掉瑕疵,又不能把五官磨没了。
这一章我们只聊三种最基础的滤波方法:均值滤波、高斯滤波、中值滤波。别看它们简单,实际项目中 80% 的降噪场景都能用它们搞定。嗯,咱们一个一个来。
4.1 均值滤波:最朴素的平滑器
均值滤波的原理,说白了就是「取平均」。用一个固定大小的窗口(比如 3×3),在图像上滑动,把窗口内所有像素的亮度值加起来除以像素个数,用这个平均值替换中心像素的值。
公式很简单:
g(x, y) = (1 / (m × n)) × Σ f(i, j)
其中 m×n 是窗口大小,f(i, j) 是窗口内各像素值。
实现要点:
- 窗口大小通常选奇数:3×3、5×5、7×7
- 窗口越大,平滑效果越强,但图像越模糊
- 边界处理:我一般用「补零」或「镜像扩展」
核心特点:均值滤波计算量小,实现简单,但会破坏边缘信息。说白了,它把噪声和细节一起抹平了。
我在项目中遇到过这样一个坑:用均值滤波处理星空 HDR 图像,结果星星全变成了模糊的光斑。为什么?因为星星本身是高频细节,均值滤波不分青红皂白全给平均了。
4.2 高斯滤波:带权重的平滑
高斯滤波是均值滤波的升级版。它不再简单取平均,而是根据高斯分布给窗口内的像素分配权重——离中心越近的像素权重越大,越远的权重越小。
二维高斯函数长这样:
G(x, y) = (1 / (2πσ²)) × exp(-(x² + y²) / (2σ²))
其中 σ(标准差)控制权重的衰减速度。σ 越大,权重分布越平坦,平滑效果越强。
实现步骤:
- 根据 σ 和窗口大小生成高斯核(权重矩阵)
- 归一化高斯核,使所有权重之和为 1
- 用高斯核与图像做卷积
我的经验:σ 取 0.8~1.2 时效果最自然。σ 太小(如 0.3)几乎没效果,σ 太大(如 3.0)图像会严重模糊。我曾经在夜景 HDR 合成中用过 σ=2.5,结果建筑边缘像涂了一层黄油。
高斯滤波比均值滤波好在哪里?它保留了更多边缘信息。因为离中心远的像素贡献小,边缘两侧的像素不会互相「污染」得太厉害。
4.3 中值滤波:边缘保护专家
中值滤波的思路完全不同。它不计算平均值,而是取窗口内所有像素的中位数作为输出值。
举个例子:一个 3×3 窗口内的像素值为 [12, 15, 18, 20, 22, 25, 28, 30, 255],排序后中位数是 22。那个 255 的椒盐噪声就被完美去掉了。
实现流程:
- 滑动窗口遍历每个像素
- 提取窗口内所有像素值
- 排序,取中位数
- 替换中心像素
注意:中值滤波对椒盐噪声(黑白点噪声)效果极好,但对高斯噪声效果一般。而且排序操作比均值计算慢得多,窗口越大性能开销越大。
我记得有一次处理工业相机拍摄的 HDR 图像,传感器坏点导致大量白点噪声。均值滤波和高斯滤波都试了,效果很差——白点虽然变暗了,但扩散成一片灰斑。换成中值滤波后,坏点直接消失,边缘还保持得干干净净。
4.4 三种滤波对比
| 特性 | 均值滤波 | 高斯滤波 | 中值滤波 |
|---|---|---|---|
| 计算复杂度 | 低 | 中 | 高(需排序) |
| 边缘保持 | 差 | 中 | 好 |
| 椒盐噪声 | 一般 | 一般 | 优秀 |
| 高斯噪声 | 一般 | 好 | 一般 |
| 实现难度 | 简单 | 中等 | 简单 |
| 适用场景 | 快速预览、低要求平滑 | 自然平滑、HDR 暗部降噪 | 椒盐噪声、边缘保护 |
4.5 代码实现示例
下面我用 Python 和 OpenCV 演示三种滤波的实现。你可以在自己的项目中直接套用。
import cv2
import numpy as np
# 读取图像(假设是 HDR 亮度图)
img = cv2.imread('hdr_luminance.png', cv2.IMREAD_GRAYSCALE)
# 均值滤波
mean_blur = cv2.blur(img, (3, 3))
# 高斯滤波
gaussian_blur = cv2.GaussianBlur(img, (3, 3), sigmaX=1.0)
# 中值滤波
median_blur = cv2.medianBlur(img, 3)
# 保存结果
cv2.imwrite('mean_result.png', mean_blur)
cv2.imwrite('gaussian_result.png', gaussian_blur)
cv2.imwrite('median_result.png', median_blur)
避坑指南:我曾经在 HDR 合成流程中直接用均值滤波处理 16bit 浮点亮度图,结果因为像素值范围太大(0~65535),均值计算时出现了整数溢出。后来我先把数据归一化到 0~1 再滤波,问题就解决了。
4.6 知识体系结构图
下面这张 SVG 图展示了三种滤波方法的核心逻辑和适用场景,方便你快速回顾。
4.7 实际项目中的选择策略
说了这么多理论,到底怎么选?我分享几个实战经验:
- HDR 暗部区域:暗部噪声通常是高斯型,优先用高斯滤波,σ 取 1.0~1.5,窗口 5×5
- 传感器坏点:这是典型的椒盐噪声,中值滤波 3×3 窗口一次搞定
- 实时预览:均值滤波最快,但我会配合边缘检测做条件滤波——平坦区域用均值,边缘区域保持原样
- 多帧合成前:我建议先对每帧做轻度高斯滤波(σ=0.5),再合成,能减少帧间噪声累积
重要提醒:滤波窗口大小不要超过图像尺寸的 5%。我曾经在 4K 图像上用 101×101 的高斯滤波,结果程序直接卡死——不是算法问题,是内存爆了。大窗口一定要考虑性能优化。