4、去噪 (Denoise):空间域去噪 (Bilateral/BM3D)、时间域去噪 (3DNR)、RK 自研降噪算法特点

去噪这块,说实话是ISP Pipeline里最考验功力的环节之一。你想想看,传感器出来的原始数据,信噪比就那么点,后面还要做各种增益、Gamma、锐化,噪声一旦没压住,后面全给你放大了。我这些年调过不少平台的降噪模块,RK的方案给我印象最深的是——它不跟你玩花活,但每个模块都切中要害。

4.1 空间域去噪:Bilateral Filter 与 BM3D

空间域去噪,说白了就是在单帧图像里做文章。它的核心矛盾是:既要抹掉噪声,又不能把边缘细节给糊了。这个平衡点,找起来挺费劲的。

4.1.1 Bilateral Filter(双边滤波)

Bilateral Filter 是我个人非常喜欢的一个基础算子。它不像高斯滤波那样一视同仁地模糊所有像素,而是引入了「像素值差异」这个权重。

公式其实不复杂:

I_filtered(x) = (1/W_p) * Σ I(x_i) * G_s(||x - x_i||) * G_r(|I(x) - I(x_i)|)

这里有两个关键参数:

  • 空间域sigma(σ_s):控制空间邻近度权重,越大则模糊范围越广
  • 值域sigma(σ_r):控制像素值差异权重,越大则边缘保留能力越弱

我在项目中遇到过一个问题:σ_r设得太小,平坦区域噪声纹丝不动;设得太大,边缘又糊了。后来我总结出一个经验——σ_r应该跟当前区域的噪声标准差挂钩。噪声大的地方,σ_r适当放大;噪声小的地方,收紧它。RK的Bilateral实现里,其实就内置了这种自适应机制,它会根据局部亮度统计动态调整权重。

避坑指南: 我曾经在低照度场景下把σ_s设到15以上,结果整张图像像蒙了一层雾。后来发现,Bilateral更适合做轻度降噪,重度噪声还是得上非局部均值类算法。

4.1.2 BM3D(三维块匹配滤波)

BM3D 是空间域去噪的天花板,但也是计算量的天花板。它的思路很有意思:先在图像里找相似的块,把它们叠成一个三维数组,然后在变换域(DCT或小波)里做阈值收缩。

流程大致分两步:

  1. 基础估计:硬阈值滤波,得到初步去噪结果
  2. 最终估计:用维纳滤波做二次增强

嗯,这里要注意——BM3D在RK平台上通常不会全分辨率跑。我见过一个方案是:在Y通道上做BM3D,UV通道用Bilateral。这样既保住了亮度细节,又控制了带宽。毕竟BM3D的复杂度是O(N log N)级别的,4K分辨率下实时处理,对DDR带宽是个不小的考验。

算法 PSNR提升(典型值) 计算开销 适用场景
Bilateral 2-4 dB 实时预览、轻度噪声
BM3D 5-8 dB 高画质拍照、低照度

4.2 时间域去噪:3DNR(三维降噪)

空间域去噪有个天然瓶颈——它只能利用单帧信息。但视频场景下,相邻帧之间有大量冗余信息。3DNR就是吃这碗饭的。

3DNR的核心思想是:运动区域用空间域,静止区域用时间域。怎么判断运动?这就涉及到运动补偿(Motion Compensation, MC)了。

RK的3DNR架构里,我印象最深的是它的运动检测模块。它不是简单做帧差,而是结合了块匹配和局部梯度信息:

// 伪代码示意
motion_level = f(block_sad, local_gradient, texture_complexity)
if motion_level < TH_LOW:
    // 静止区域,强时间滤波
    blend_ratio = 0.8
elif motion_level > TH_HIGH:
    // 运动区域,退化为空间滤波
    blend_ratio = 0.0
else:
    // 过渡区域,自适应混合
    blend_ratio = linear_interp(motion_level)

我个人习惯把时间滤波的强度跟场景亮度挂钩。暗光下噪声大,时间滤波可以开猛一点;白天光线好,稍微意思一下就行。否则容易拖出鬼影——嗯,鬼影是3DNR最头疼的问题。

注意: 3DNR的帧缓存会引入延迟。如果你在做实时取景,建议把时间滤波控制在2-3帧以内。我曾经见过一个方案用了8帧累积,结果取景延迟肉眼可见,用户反馈「画面像慢动作」。

4.3 RK 自研降噪算法特点

RK的自研降噪,不是简单把Bilateral和3DNR拼在一起。它有几个让我觉得挺有意思的设计:

  • 多尺度分解:RK把图像分解成低频、中频、高频三个层次。低频做轻度平滑,中频做边缘保护降噪,高频做细节保留。每个频段的降噪参数独立可配。
  • 亮度自适应阈值:暗区的噪声是泊松分布的,亮区是高斯分布的。RK的降噪模块会根据像素亮度动态切换噪声模型,这个细节很多平台没做到。
  • 纹理保护机制:RK在降噪前会先做一次纹理检测。如果当前区域是草地、布料这类高频纹理,它会降低降噪强度,防止纹理被抹成一片。

我记得有一次调一个室内监控场景,天花板上的纹理细节总是被磨平。后来发现是纹理检测的阈值设得太保守了。把纹理检测的灵敏度从0.3调到0.5之后,效果立竿见影。

核心优势总结: RK的降噪方案在「实时性」和「画质」之间找到了一个不错的平衡点。它不像高通那样激进地堆算力,也不像MTK那样保守地做减法。如果你手头有RK的SDK,建议重点关注 isp_denoise_config 结构体里的 dnr_leveltexture_protect 两个参数,调好了能省不少事。

最后说一句——降噪这件事,没有银弹。Bilateral快但糊,BM3D好但慢,3DNR强但有鬼影。RK的做法是把这些工具组合起来,让它们在各自擅长的场景里发挥作用。你想想看,这其实跟做菜一个道理——没有万能调料,关键看你怎么搭配。

RK ISP 降噪算法体系 RAW 图像输入 空间域去噪 时间域去噪 (3DNR) RK 自研算法 Bilateral Filter BM3D 运动检测 时间滤波 多尺度分解 自适应阈值 降噪融合引擎(自适应权重混合) 最终去噪图像输出 图:RK ISP 降噪算法体系架构图
调参建议: 如果你刚开始调RK的降噪,建议先从 dnr_level 入手,把它从0调到100,观察噪声和细节的变化曲线。找到拐点之后,再微调 texture_protect。我一般会把 texture_protect 设在0.4-0.6之间,太低纹理容易丢,太高噪声压不住。
专注资料整理