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)
其中 α 是融合系数。α 越大,当前帧的权重越大,去噪效果越弱,但运动拖影越少。α 越小,去噪效果越强,但运动拖影越明显。
这里有个关键问题:怎么判断像素是否在运动?
答案是运动检测。通常的做法是计算当前帧和参考帧的像素差值,如果差值大于某个阈值,就认为发生了运动,此时增大 α 值,减少时域融合。
4.3 高通 MCTF 模块
MCTF(Motion Compensated Temporal Filtering)是高通平台上的时域去噪模块。它比普通的时域去噪多了一步——运动补偿。
什么意思呢?普通的时域去噪假设像素位置不变,但实际场景中物体是运动的。MCTF 会先做运动估计,找到当前帧像素在参考帧中的对应位置,然后再做时域融合。这样即使物体在运动,也能正确地进行时域去噪,不会产生拖影。
MCTF 的流程大致如下:
- 运动估计:将当前帧分成小块(比如 16x16),在参考帧中搜索最匹配的位置,得到运动矢量。
- 运动补偿:根据运动矢量,将参考帧的像素“搬”到当前帧的位置。
- 时域滤波:对运动补偿后的参考帧和当前帧做加权平均。
- 后处理:对滤波结果做边缘保护,防止过度平滑。
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 还有一个重要的变体——MCTF with Overlap。它让相邻块之间有重叠区域,可以减少块效应。但代价是计算量增加 20% 左右。我个人建议,在 4K 以上的分辨率场景开启,1080p 以下可以关掉。
最后,我们来看一张 MCTF 的整体流程图,帮助大家理解各个模块的关系:
这张图把 MCTF 的核心流程串起来了。从当前帧输入,到运动估计、运动补偿、时域滤波,最后输出去噪后的帧。虚线表示参考帧的更新路径——每一帧处理完后,都会作为下一帧的参考。