3、时域降噪原理:帧间平均法、运动补偿时域滤波(MC-TNF)、3D降噪架构

时域降噪,说白了就是利用视频帧与帧之间的冗余信息来压制噪声。你想想看,静态场景里,像素位置的真实信号是固定的,但噪声是随机抖动的。多帧一平均,噪声就被“抹平”了。这个思路很朴素,但落地时坑不少。我早年调一个IPC项目,晚上画面全是闪烁的颗粒,空域降噪一开细节全糊,后来才发现是时域参数没配好。

3.1 帧间平均法:最朴素的时域降噪

帧间平均法是最基础的时域降噪手段。它的数学表达式很简单:

Output(n) = α * Input(n) + (1 - α) * Output(n-1)

其中 α 是融合系数,范围 0~1。α 越小,时域平滑越强,但运动拖尾也越严重。

关键参数:

  • α = 0.1~0.3:强降噪,适合静态场景(如监控空走廊)
  • α = 0.5~0.7:中等降噪,适合轻微运动场景
  • α = 0.8~1.0:弱降噪,适合快速运动场景

我在项目中遇到过一个问题:帧间平均法对静态场景效果极好,但一旦画面里有人走动,立刻出现“鬼影”。说白了,就是运动区域被错误地平均了。所以帧间平均法必须配合运动检测来使用。

实战技巧:帧间平均法适合作为3D降噪的“底层平滑器”,但不要单独使用。我一般只在场景切换后的前几帧用高α快速收敛,之后切换到低α保持平滑。

3.2 运动补偿时域滤波(MC-TNF):解决运动拖尾

运动补偿时域滤波(Motion Compensated Temporal Noise Filtering)是帧间平均法的升级版。它的核心思路是:先估计运动矢量,然后沿着运动轨迹做时域滤波。

为什么需要运动补偿?你想想看,如果画面里一辆车在移动,直接做帧间平均,车的位置会模糊。但如果我们知道车往哪个方向移动了多少像素,就可以把前一帧的车“搬”到当前帧的位置再平均——这样既降噪又不模糊。

MC-TNF 的典型流程:

  1. 运动估计:计算当前块与参考帧对应块的运动矢量(MV)
  2. 运动补偿:根据MV从参考帧中取出补偿后的像素块
  3. 时域滤波:对当前块和补偿块做加权平均
  4. 后处理:对运动估计不准的区域做保护

注意:运动估计的精度直接影响MC-TNF效果。我见过不少方案用全搜索做运动估计,结果算力爆炸,帧率掉到15fps。实际工程中,我建议用三步搜索法或菱形搜索法,精度够用,算力可控。

运动补偿的权重分配也很讲究。我个人的习惯是:

运动强度 当前帧权重 补偿帧权重 说明
静止(MV=0) 0.2 0.8 强时域平滑
微动(MV≤2) 0.4 0.6 适度平滑
中动(MV≤8) 0.6 0.4 减少拖尾
快动(MV>8) 0.9 0.1 几乎不做时域

我曾经在一个低照度项目中,MC-TNF 的参数调了整整两周。问题出在运动估计的块大小上——块太大,运动边界模糊;块太小,运动矢量噪声大。最后我用了 8x8 块做运动估计,配合 4x4 子块做运动补偿细化,效果才满意。

3.3 3D降噪架构:空域+时域的协同

3D降噪不是指三维空间,而是“空域(2D)+时域(1D)”的联合降噪。说白了,就是先做空域降噪(去噪点),再做时域降噪(去闪烁),或者反过来。

典型的 3D 降噪架构有两种:

  • 串行架构:空域降噪 → 时域降噪。优点是实现简单,缺点是空域过度平滑会损失细节,时域无法恢复。
  • 并行架构:空域和时域同时处理,结果融合。优点是细节保留好,缺点是计算量大,需要做运动自适应融合。

我个人更倾向于并行架构。为什么?因为串行架构里,空域降噪一旦把纹理磨没了,时域再怎么补偿也救不回来。并行架构可以保留空域的高频细节,同时利用时域压制噪声。

3D降噪并行架构 输入帧 空域降噪(2D NR) 时域降噪(MC-TNF) 运动估计(ME) 运动自适应融合 输出帧 运动自适应融合:根据运动强度动态调整空域/时域权重 运动小 → 时域权重高;运动大 → 空域权重高

运动自适应融合是3D降噪的核心。它的逻辑是:

  • 运动小(静止区域):时域权重高,空域权重低。因为时域对静态场景降噪效果更好,且不损失细节。
  • 运动大(快速运动区域):空域权重高,时域权重低。因为时域在运动区域容易产生鬼影,不如靠空域。
  • 中等运动:两者折中,通常用运动强度做线性插值。

实战经验:运动自适应融合的阈值设置很关键。我一般设置两个阈值:T_low 和 T_high。运动强度低于 T_low 时全时域,高于 T_high 时全空域,中间做线性过渡。T_low 通常取 2~4 像素,T_high 取 8~12 像素。

3.4 3D降噪的工程实现要点

在实际芯片或DSP上实现3D降噪,有几个坑必须注意:

  1. 帧缓存管理:3D降噪至少需要缓存1~2帧。对于4K@30fps的码流,一帧RAW图约12MB,两帧就是24MB。如果芯片内部SRAM不够,就得走DDR,延迟和带宽都要考虑。
  2. 场景切换检测:当监控画面从室内切到室外,或者有人突然开灯,前后帧内容完全不相关。此时如果还做时域平均,画面会长时间停留在过渡状态。我一般会检测帧间直方图差异,差异超过阈值就重置时域滤波器。
  3. 噪声水平自适应:不同光照下噪声水平不同。低照度时噪声大,需要强时域;高照度时噪声小,可以弱时域甚至关闭时域。我习惯用ISO值或亮度统计来动态调整α系数。

避坑指南:我曾经在一个项目中,3D降噪的时域强度调得太大,结果画面看起来像“果冻”——运动物体后面拖着长长的尾巴。后来发现是运动补偿的搜索范围太小,大运动时匹配不到正确位置。解决方案是增大搜索范围,同时增加运动矢量可信度检测。

3.5 不同场景的3D降噪策略

场景类型 空域强度 时域强度 运动补偿 典型参数
室内静态(办公室) 弱 强 关闭 α=0.15, 空域半径=1
室内动态(商场) 中 中 开启 α=0.4, 搜索范围=8
室外白天(道路) 弱 弱 开启 α=0.7, 搜索范围=16
室外夜晚(低照度) 强 强 开启 α=0.1, 空域半径=3

嗯,这里要注意:上面的参数只是起点,实际调优时还得看具体sensor的噪声特性。不同sensor的时域噪声分布不一样,有的偏白噪声,有的偏闪烁噪声,调参思路完全不同。

我个人习惯是先固定空域参数,单独调时域;时域调稳了再联合调优。这样能减少变量,定位问题也快。