4、YUV域去噪基础:空域去噪与时域去噪

各位好,欢迎来到第四章。这一章我们聊聊去噪——ISP 流水线里最吃经验、也最见功力的环节之一。噪点这东西,你想想看,它就像照片里的沙子,不处理不行,处理过了又容易把细节磨平。我刚开始做 ISP 的时候,就吃过这个亏,后面会跟大家细说。

YUV 域的去噪,说白了就是在亮度(Y)和色度(UV)上分别做文章。为什么不在 RGB 域做?因为人眼对亮度的敏感度远高于色度,分开处理可以更精细地控制。好,我们直接进入正题。

4.1 空域去噪:三种经典方法

空域去噪,就是只利用当前帧的像素信息,不考虑前后帧。优点是实现简单、延迟低;缺点是容易丢细节。我个人的习惯是,在低光场景下优先考虑空域去噪,因为运动场景下时域去噪容易拖影。

4.1.1 均值滤波

均值滤波是最朴素的方法。它用一个窗口(比如 3x3)内的像素平均值,替换中心像素的值。

// 3x3 均值滤波核
[1/9, 1/9, 1/9]
[1/9, 1/9, 1/9]
[1/9, 1/9, 1/9]

效果呢?噪点被抹平了,但边缘也糊了。我在一个低端手机项目里试过,拍文字的时候,边缘直接变成一团。所以均值滤波现在基本只用在预处理阶段,或者对画质要求不高的场景。

注意:均值滤波会破坏边缘的高频信息。如果你发现图像边缘出现“晕影”,大概率是均值滤波窗口开太大了。

4.1.2 高斯滤波

高斯滤波比均值滤波聪明一点。它根据像素到中心点的距离,分配不同的权重——越近权重越大,越远权重越小。这样能保留更多边缘信息。

// 3x3 高斯滤波核 (sigma ≈ 0.85)
[1/16, 2/16, 1/16]
[2/16, 4/16, 2/16]
[1/16, 2/16, 1/16]

高斯滤波在 YUV 域用得很多,尤其是对 Y 分量做轻度去噪。我建议 sigma 值不要超过 1.0,否则边缘会开始模糊。高通平台里,高斯滤波经常作为 MCTF 的前置处理,用来降低时域匹配的噪声干扰。

经验之谈:如果你需要保留纹理细节,可以试试双边滤波——它同时考虑空间距离和像素值差异。但计算量会翻倍,移动端要谨慎。

4.1.3 中值滤波

中值滤波是椒盐噪声的克星。它取窗口内所有像素的中位数,而不是平均值。这样,一个孤立的噪点(比如 255 或 0)会被直接忽略。

// 3x3 窗口示例
[10, 12, 11]
[13, 255, 14]  // 255 是噪点
[11, 12, 10]

// 排序后:10,10,11,11,12,12,13,14,255
// 中位数:12

中值滤波的缺点是计算量大——每次都要排序。高通平台有硬件加速,但软件实现的话,3x3 窗口还能接受,5x5 以上就有点吃力了。我一般只在 UV 分量上用中值滤波,因为色度噪声通常是孤立的彩色噪点,中值滤波效果很好。

4.2 时域去噪原理

时域去噪,就是利用前后帧的信息来降噪。核心思想是:如果某个像素在连续几帧里位置不变,那它的平均值就是真实值;如果变了,那就是运动,不能平均。

时域去噪的公式很简单:

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

其中 α 是融合系数。α 越大,当前帧的权重越大,去噪效果越弱,但运动拖影越少。α 越小,去噪效果越强,但运动拖影越明显。

这里有个关键问题:怎么判断像素是否在运动?

答案是运动检测。通常的做法是计算当前帧和参考帧的像素差值,如果差值大于某个阈值,就认为发生了运动,此时增大 α 值,减少时域融合。

核心矛盾:时域去噪的强度与运动拖影是一对天生的矛盾。去噪越强,拖影越明显;去噪越弱,噪点又压不下去。这个平衡点,就是 ISP 调优师的价值所在。

4.3 高通 MCTF 模块

MCTF(Motion Compensated Temporal Filtering)是高通平台上的时域去噪模块。它比普通的时域去噪多了一步——运动补偿。

什么意思呢?普通的时域去噪假设像素位置不变,但实际场景中物体是运动的。MCTF 会先做运动估计,找到当前帧像素在参考帧中的对应位置,然后再做时域融合。这样即使物体在运动,也能正确地进行时域去噪,不会产生拖影。

MCTF 的流程大致如下:

  1. 运动估计:将当前帧分成小块(比如 16x16),在参考帧中搜索最匹配的位置,得到运动矢量。
  2. 运动补偿:根据运动矢量,将参考帧的像素“搬”到当前帧的位置。
  3. 时域滤波:对运动补偿后的参考帧和当前帧做加权平均。
  4. 后处理:对滤波结果做边缘保护,防止过度平滑。

MCTF 的参数配置非常关键。我列一个常用的参数表:

参数 说明 推荐值
Search Range 运动搜索范围 ±4 ~ ±16 像素
Block Size 运动估计的块大小 8x8 或 16x16
Alpha (融合系数) 当前帧权重 0.1 ~ 0.5
Motion Threshold 运动检测阈值 10 ~ 30 (8-bit)
Edge Protection 边缘保护强度 0 ~ 255
避坑指南:我曾经在一个夜景项目里,把 MCTF 的 Search Range 设成了 ±32,结果运动估计的计算量直接翻倍,帧率掉了一半。后来我改成 ±8,效果差别不大,但帧率稳住了。记住,不是越大越好。

MCTF 还有一个重要的变体——MCTF with Overlap。它让相邻块之间有重叠区域,可以减少块效应。但代价是计算量增加 20% 左右。我个人建议,在 4K 以上的分辨率场景开启,1080p 以下可以关掉。

调优技巧:MCTF 的 Alpha 值不要固定。我习惯根据场景亮度动态调整——低光下用 0.1~0.2,正常光下用 0.3~0.5。这样既能保证低光去噪效果,又能避免正常光下的拖影。

最后,我们来看一张 MCTF 的整体流程图,帮助大家理解各个模块的关系:

高通 MCTF 模块流程图 高通 MCTF 模块流程图 当前帧 (YUV) 运动估计 (ME) 运动补偿 (MC) 时域滤波 (TF) 去噪后帧 关键说明 • ME 输出运动矢量 • MC 根据矢量对齐像素 • TF 做加权平均 • 边缘保护在后处理 参考帧更新

这张图把 MCTF 的核心流程串起来了。从当前帧输入,到运动估计、运动补偿、时域滤波,最后输出去噪后的帧。虚线表示参考帧的更新路径——每一帧处理完后,都会作为下一帧的参考。