4. 传统降噪方法回顾:BM3D、NLM、小波降噪

各位同学,咱们今天聊点“老本行”。

在深度学习把ISP降噪卷得飞起之前,我们这些做图像处理的,靠的就是BM3D、NLM、小波降噪这几板斧。说实话,直到现在,我在某些项目里还是会优先考虑它们——不是情怀,是真的好用。

这一章,我就带大家把这三种经典方法掰开揉碎,看看它们的底牌是什么,坑在哪里,以及什么时候该请它们出山。

4.1 为什么还要学“老方法”?

你可能会想:“都2025年了,直接上CNN不香吗?”

嗯,这个问题我当年也问过自己。后来在做一个低功耗IPC(网络摄像头)项目时,芯片的NPU算力只有0.5 TOPS,跑个轻量级UNet都卡成PPT。最后我硬着头皮上了BM3D,效果居然还不错,功耗还低。

说白了,传统方法有三大不可替代的优势:

  • 无需训练数据:拿来就用,不挑场景。
  • 计算可预测:没有推理延迟抖动,适合实时系统。
  • 理论透明:每个参数都知道在干什么,调试起来心里有底。

我的建议:在深度学习部署中,传统方法可以作为“保底方案”或“混合方案”的一部分。比如白天用轻量CNN,晚上光线差时切到BM3D——我在一个安防项目里就这么干过,效果很稳。

4.2 BM3D:降噪界的“瑞士军刀”

BM3D,全称Block-Matching and 3D Filtering。这名字听着复杂,其实核心思想就两步:找相似块 → 组团去噪。

4.2.1 核心流程

  1. 块匹配(Block Matching):在图像里滑动窗口,找到与当前块相似的图像块(比如纹理、边缘相似的区域)。
  2. 3D变换:把这些相似块堆成一个3D数组,然后做3D DCT或小波变换。
  3. 协同滤波:在变换域里做硬阈值或维纳滤波,把噪声系数砍掉。
  4. 逆变换与聚合:把滤波后的块变换回空间域,再加权平均放回原位置。

这个过程会做两轮:第一轮粗去噪,估计出噪声水平;第二轮用维纳滤波精细处理。我习惯把第一轮叫“探路”,第二轮叫“精修”。

避坑指南:我曾经在纹理丰富的区域(比如草地、布料)用过BM3D,结果把纹理也当成噪声去掉了,画面变得像塑料一样。后来我学乖了——块匹配的阈值要调松一点,让更多真实纹理保留下来。

4.2.2 优缺点与适用场景

维度 说明
优点 降噪效果极佳,PSNR提升明显;能保留边缘和细节;对高斯噪声效果最好。
缺点 计算量大(尤其是块匹配阶段);对非高斯噪声(如散粒噪声)效果一般;参数调优较繁琐。
适用场景 静态图像降噪、医学影像、天文图像、离线处理。

注意:BM3D在视频降噪里需要做帧间块匹配,计算量会翻倍。我在一个1080p@30fps的项目里试过,单帧处理时间超过200ms——根本跑不动。所以视频实时降噪慎用BM3D。

4.3 NLM:非局部平均的“温柔一刀”

NLM,Non-Local Means。它的想法很朴素:图像里有很多重复的图案(比如墙上的砖、衣服的纹理),把这些相似区域平均一下,噪声自然就消了。

4.3.1 核心思想

传统均值滤波只考虑邻域像素,NLM则在整个图像里搜索相似块。每个像素的最终值,是它所有相似块中心像素的加权平均。权重由块之间的相似度决定——越相似,权重越大。

你想想看,这其实是一种“全局自相似性”的利用。我在做老照片修复项目时,NLM对胶片颗粒噪声的效果特别好,因为那种噪声是随机的,而真实纹理是重复的,NLM正好能区分开。

4.3.2 优缺点与适用场景

维度 说明
优点 算法简单,容易实现;对纹理保留较好;适合处理周期性噪声。
缺点 计算量巨大(全局搜索);对边缘保持不如BM3D;容易产生“伪影”(类似油画效果)。
适用场景 纹理丰富的图像、老照片修复、医学超声图像。

我的经验:NLM的搜索窗口大小很关键。设太大,计算量爆炸;设太小,效果出不来。我一般建议搜索窗口21x21,相似块7x7,这是一个比较平衡的配置。如果算力紧张,可以缩小到15x15。

4.4 小波降噪:频域里的“手术刀”

小波降噪,说白了就是在小波域里做阈值处理。图像经过小波变换后,能量会集中在少数大系数上,而噪声则均匀分布在小系数上。我们只需要把小于某个阈值的小波系数置零,再逆变换回去,噪声就没了。

4.4.1 核心步骤

  1. 小波分解:对图像做多级小波分解,得到低频近似分量和高频细节分量。
  2. 阈值处理:对高频分量做软阈值或硬阈值处理。
  3. 小波重构:用处理后的系数重建图像。

这里有个关键点:阈值怎么选? 我早期做项目时,直接用固定阈值,结果要么去不干净,要么把细节抹掉了。后来我改用VisuShrink(通用阈值)和BayesShrink(贝叶斯自适应阈值),效果好了很多。

代码片段:小波降噪核心逻辑(Python + PyWavelets)

import pywt
import numpy as np

def wavelet_denoise(img, wavelet='db4', level=3, threshold=0.1):
    # 小波分解
    coeffs = pywt.wavedec2(img, wavelet, level=level)
    # 对每一层的高频分量做软阈值
    coeffs_thresh = list(coeffs)
    for i in range(1, len(coeffs_thresh)):
        coeffs_thresh[i] = tuple(
            pywt.threshold(detail, threshold, mode='soft')
            for detail in coeffs_thresh[i]
        )
    # 小波重构
    return pywt.waverec2(coeffs_thresh, wavelet)

4.4.2 优缺点与适用场景

维度 说明
优点 计算速度快(适合实时处理);对高斯噪声和脉冲噪声都有效;多尺度分析,能区分不同频率的噪声。
缺点 对纹理保留不如BM3D;阈值选择依赖经验;容易产生“振铃效应”(Gibbs现象)。
适用场景 实时视频降噪、嵌入式系统、信号处理。

注意:小波降噪的振铃效应在边缘附近特别明显。我曾经在一个文字识别项目里用过,结果文字边缘出现了“鬼影”,OCR准确率直接掉了5个点。后来我改用双树复小波(DTCWT),振铃问题才缓解。

4.5 三种方法对比与选择指南

好了,三种方法都讲完了。咱们来做个横向对比,方便你以后选型。

维度 BM3D NLM 小波降噪
降噪效果 ★★★★★ ★★★★ ★★★
计算速度 ★★ ★ ★★★★★
边缘保留 ★★★★★ ★★★★ ★★★
纹理保留 ★★★★ ★★★★★ ★★
实现难度 高 低 中
适用噪声类型 高斯噪声 高斯、散粒噪声 高斯、脉冲噪声

我的选择逻辑是这样的:

  • 离线处理、追求极致画质 → BM3D
  • 纹理丰富、需要保留细节 → NLM
  • 实时系统、算力受限 → 小波降噪

4.6 知识体系总览

下面这张图,我把三种方法的核心逻辑和适用场景串起来了。你可以把它当作一个“选型地图”。

传统降噪方法知识体系 传统降噪方法 BM3D 块匹配 + 3D协同滤波 适用:静态图像、高斯噪声 NLM 非局部均值 + 全局搜索 适用:纹理丰富、老照片 小波降噪 小波分解 + 阈值处理 适用:实时系统、嵌入式 选型建议:画质优先→BM3D / 纹理优先→NLM / 速度优先→小波