3、降噪算法基础理论:双边滤波、非局部均值、小波阈值去噪、BM3D原理简介
各位好,我是负责ISP图像质量调优的工程师。今天咱们聊聊降噪算法的四大金刚:双边滤波、非局部均值、小波阈值去噪和BM3D。
说实话,刚入行那会儿,我总觉得算法原理是算法工程师的事。直到有一次,我在调试高通平台的夜景模式时,发现某个场景的噪声死活压不下去,换了好几个参数都不行。后来一查,原来是算法选型出了问题——双边滤波对那种高频细节丰富的区域根本不适合。从那以后,我就老老实实把每个算法的脾气摸了个透。
这四种算法,说白了就是四种不同的「去噪哲学」。咱们一个一个来看。
3.1 双边滤波:保边去噪的入门选手
双边滤波(Bilateral Filter)是我最早接触的空间域降噪算法。它的核心思想很简单:既要看空间距离,也要看像素值差异。
传统的均值滤波或高斯滤波,只考虑像素之间的空间距离。离中心越近,权重越大。但这样会带来一个问题——边缘处的像素也被平均了,边缘就糊了。
双边滤波加了一个「值域核」。如果两个像素的亮度差太大,就算离得近,权重也会很小。这样一来,平坦区域的噪声被平滑了,边缘却被保留了下来。
双边滤波公式(简化版)
输出像素 = (1/W) * Σ [ 空间权重(i) × 值域权重(i) × 输入像素(i) ]
空间权重 = exp(-(距离²) / (2 * σ_s²))
值域权重 = exp(-(像素差²) / (2 * σ_r²))
这里有两个关键参数:σ_s(空间标准差)和 σ_r(值域标准差)。
| 参数 | 作用 | 调大后的效果 | 调小后的效果 |
|---|---|---|---|
| σ_s | 控制空间邻域范围 | 平滑更强,但细节丢失 | 保留细节,但降噪不足 |
| σ_r | 控制像素值敏感度 | 边缘保留变弱,容易模糊 | 边缘保留强,但噪声残留 |
我的调优经验
在高通平台上调双边滤波时,我习惯先固定 σ_s 为图像尺寸的 2%-3%,然后慢慢调 σ_r。σ_r 太小,噪声压不住;σ_r 太大,边缘就糊了。我一般从 0.1 开始,每次加 0.05,直到噪声和细节达到平衡。
双边滤波的缺点也很明显:计算量大。每个像素都要计算邻域内所有像素的权重,复杂度是 O(N·r²)。而且它对椒盐噪声效果不好——因为椒盐噪声的像素值差异太大,值域核直接把它当成边缘给保留了。
3.2 非局部均值:找相似块来去噪
非局部均值(Non-Local Means, NLM)是我个人比较喜欢的一种算法。它的思路很有意思:图像中总有很多相似的局部块。
你想想看,一片天空区域,虽然像素位置不同,但它们的纹理结构是相似的。NLM 就是利用这种「非局部」的自相似性来做降噪。
具体做法是:对于当前像素点,在图像中搜索所有与它周围小块相似的块,然后把这些块的中心像素加权平均。权重由块之间的相似度决定。
NLM 核心思想
输出像素(p) = Σ [ w(p,q) × 输入像素(q) ]
w(p,q) = exp(-||块(p) - 块(q)||² / h²) / Z(p)
这里的 h 是滤波强度参数,控制权重的衰减速度。块大小一般取 5×5 或 7×7,搜索窗口取 21×21 或 31×31。
我在项目中遇到过一个问题:NLM 对纹理丰富的区域效果很好,但对平坦区域反而容易产生「伪纹理」——因为搜索到的相似块不够多,权重分布不均匀。后来我加了一个预处理步骤,先对平坦区域做一次高斯滤波,再跑 NLM,效果就好多了。
注意:NLM 的计算量非常大
搜索窗口 21×21,块大小 7×7,每个像素要计算 441 个块的相似度。在 1080p 图像上,纯软件实现基本跑不动。高通平台一般会用硬件加速或降采样搜索策略。我在调试时,会把搜索窗口缩小到 11×11,牺牲一点效果换取实时性。
3.3 小波阈值去噪:频域里的「砍小留大」
小波阈值去噪(Wavelet Thresholding)是频域方法的代表。它的原理我可以用一句话概括:噪声在小波域里是高频小系数,信号是低频大系数。
具体步骤分三步:
- 小波分解:把图像分解成不同尺度和方向的小波系数(LL、LH、HL、HH)。
- 阈值处理:对高频子带(LH、HL、HH)的系数做阈值处理,小于阈值的置零或收缩。
- 小波重构:用处理后的系数重建图像。
阈值的选择是关键。常用的有硬阈值和软阈值两种:
| 类型 | 公式 | 特点 |
|---|---|---|
| 硬阈值 | if |x| > T then x else 0 | 保留边缘锐利,但可能产生振铃 |
| 软阈值 | sign(x) × max(|x|-T, 0) | 图像更平滑,但边缘会变模糊 |
阈值 T 一般用 T = σ × √(2 × log(N)) 来估计,其中 σ 是噪声标准差,N 是像素数。这个公式来自 Donoho 的通用阈值法,我在实际项目中用它做初始值,然后手动微调。
我曾经踩过的坑
有一次我用小波阈值去噪处理一张星空照片,结果星星全被当成噪声去掉了。后来才发现,星星在图像中也是高频成分,阈值设得太高,把信号也砍了。解决办法是:对不同的子带用不同的阈值,或者先做一次边缘检测,保护高频信号区域。
3.4 BM3D:目前最强的空间-频域混合算法
BM3D(Block-Matching and 3D Filtering)是目前公认的降噪效果最好的算法之一。它结合了 NLM 的块匹配思想和小波变换的频域处理能力。
BM3D 的工作流程分两大步:
第一步:基础估计
- 对图像做块匹配,找到相似块组成三维数组。
- 对三维数组做 3D 变换(通常是 DCT + 小波)。
- 用硬阈值滤波去除噪声。
- 逆变换得到基础估计图像。
第二步:最终估计
- 在基础估计图像上重新做块匹配。
- 对原始图像和基础估计图像分别做 3D 变换。
- 用维纳滤波(Wiener Filter)做联合滤波。
- 逆变换得到最终结果。
BM3D 为什么效果好?
因为它同时利用了空间域的自相似性和频域的稀疏性。块匹配找到了冗余信息,3D 变换把信号和噪声在频域里分得更开,维纳滤波又做了最优估计。三个环节环环相扣。
BM3D 的缺点是计算量巨大。在手机上做实时 BM3D 基本不可能。高通平台一般用简化版或只在后处理阶段用。我调试时,会把块大小设为 8×8,搜索步长设为 3,这样能在效果和速度之间找到平衡。
3.5 四种算法对比总结
咱们用一张表来对比这四种算法:
| 算法 | 域 | 核心思想 | 保边能力 | 计算量 | 适用场景 |
|---|---|---|---|---|---|
| 双边滤波 | 空间域 | 空间+值域双权重 | 中 | 低 | 实时预处理、轻度噪声 |
| NLM | 空间域 | 非局部块匹配 | 高 | 高 | 纹理丰富场景、中等噪声 |
| 小波阈值 | 频域 | 小波系数阈值处理 | 中高 | 中 | 高斯噪声、可控场景 |
| BM3D | 混合域 | 块匹配+3D变换+维纳滤波 | 极高 | 极高 | 高质量后处理、离线处理 |
下面这张图展示了四种算法的核心逻辑关系:
在实际的高通 ISP 调优中,我一般这样选:
- 实时预览:用双边滤波或它的加速变体,参数调好后效果够用。
- 拍照后处理:用 BM3D 或 NLM,效果最好,但要注意功耗。
- 视频降噪:用小波阈值去噪,计算量适中,帧率能稳住。
嗯,这四种算法是降噪领域的基础。理解了它们,后面再学更复杂的深度学习降噪方法时,你会发现很多思路都是相通的。