2. 多帧降噪(MFNR)原理
多帧降噪,说白了就是拍多张照片,然后合成一张干净的。听起来简单,但里面的门道不少。我在高通平台调了这么多年,踩过的坑能写满一本笔记本。
这一章我们重点聊四个核心模块:时域滤波、空域滤波、运动补偿和帧选择策略。它们就像四根柱子,缺一根房子就塌。
2.1 时域滤波:让时间帮你降噪
时域滤波的核心思想很简单——同一场景拍多帧,像素值取平均。噪声是随机的,信号是稳定的,平均之后噪声自然就弱了。
公式长这样:
I_out(x,y) = (1/N) * Σ I_i(x,y) (i = 1 to N)
但实际项目里没人这么干。为什么?因为帧与帧之间一定有运动。哪怕是三脚架固定拍摄,树叶也会动,云也会飘。
关键点:时域滤波的强度取决于两帧之间的相关性。相关性越高,降噪效果越好。
我习惯把时域滤波分成两种模式:
| 模式 | 适用场景 | 帧数 | 降噪强度 |
|---|---|---|---|
| 简单平均 | 静态场景(夜景、文档拍摄) | 4~8帧 | 高 |
| 加权平均 | 轻微运动场景(手持夜景) | 3~5帧 | 中 |
加权平均里,权重怎么给?我一般用帧间差异图来算。差异大的像素权重低,差异小的权重高。这样能避免运动区域糊掉。
我的经验:高通平台里有个叫 MCTF(Motion Compensated Temporal Filter)的硬件模块,专门做这个。你只需要配好权重表和搜索窗口大小,剩下的硬件帮你算。
2.2 空域滤波:在单帧里下功夫
时域滤波搞不定所有噪声。比如运动区域,时域滤波基本不敢动,一动就糊。这时候就得靠空域滤波。
空域滤波的本质是利用像素邻域信息来估计当前像素的真实值。常见的算法有:
- 高斯滤波:简单,但会模糊边缘
- 双边滤波:保边效果好,但计算量大
- NLM(非局部均值):效果好,但慢得离谱
- 小波阈值去噪:频域方法,适合特定噪声类型
在高通平台上,我推荐用改进的双边滤波。为什么?因为硬件里有专门的 BF 模块,支持可配置的空间核和范围核。
// 双边滤波伪代码
for each pixel (x,y):
w_sum = 0
result = 0
for each neighbor (i,j) in window:
w_spatial = exp(-((i-x)^2 + (j-y)^2) / (2 * σ_s^2))
w_range = exp(-(|I(i,j) - I(x,y)|^2) / (2 * σ_r^2))
w = w_spatial * w_range
result += I(i,j) * w
w_sum += w
I_out(x,y) = result / w_sum
注意:σ_s 和 σ_r 这两个参数非常敏感。σ_s 太大,边缘会糊;σ_r 太大,噪声去不干净。我一般先用 σ_s = 2~3,σ_r = 10~20(8-bit 图像),然后根据实际效果微调。
2.3 运动补偿:让时域滤波真正可用
没有运动补偿的时域滤波,就是耍流氓。你想想看,手持拍摄时手会抖,拍出来的帧之间肯定有偏移。直接平均,画面就重影了。
运动补偿的核心是估计帧间运动矢量,然后把参考帧对齐到当前帧。高通平台用的是块匹配法:
- 把图像分成 16x16 或 8x8 的块
- 在参考帧的搜索窗口内找最匹配的块
- 计算运动矢量 (dx, dy)
- 用运动矢量做 warp 变换
我遇到过一个问题:运动矢量太粗糙。块匹配只能给出整像素精度,但实际运动可能是亚像素级的。怎么办?
解决方案:在块匹配之后,再做一次亚像素插值。高通平台的 MEC(Motion Estimation and Compensation)模块支持 1/4 像素精度,效果比整像素好很多。
运动补偿的流程我画了张图,你看一眼就明白了:
2.4 帧选择策略:不是所有帧都值得保留
多帧降噪不是帧数越多越好。我见过有人拍 10 帧合成,结果还不如 4 帧的效果好。为什么?因为帧质量参差不齐。
帧选择策略要解决三个问题:
- 哪些帧能用?——剔除模糊帧、过曝帧、欠曝帧
- 哪些帧优先?——质量高的帧给更高权重
- 帧数不够怎么办?——降级策略,用更少的帧合成
我在项目中常用的帧质量评价指标:
| 指标 | 计算方法 | 阈值参考 |
|---|---|---|
| 拉普拉斯方差 | 对帧做拉普拉斯变换,求方差 | > 100(清晰) |
| 平均亮度 | 像素值求和取平均 | 80~180(正常曝光) |
| 帧间差异 | 与参考帧的差求和 | < 20%(运动小) |
我曾经踩过的坑:有一次把拉普拉斯方差的阈值设得太低,结果把轻微模糊的帧也放进去了。合成出来的照片边缘发虚,怎么看都不对劲。后来我把阈值从 50 调到 100,问题就解决了。
帧选择的具体流程:
- 拍完 N 帧后,先做快速质量评估
- 剔除质量不合格的帧
- 对剩余帧按质量排序
- 取前 M 帧(M ≤ N)参与合成
- 质量高的帧给高权重
我的建议:高通平台的 ISP 里有个 AFM(Auto Focus Metric)寄存器,可以直接读出每帧的清晰度评分。用这个做帧选择,比你自己算拉普拉斯方差快得多。
2.5 三者如何协同工作
时域滤波、空域滤波、运动补偿、帧选择,这四个模块不是各自为战的。它们需要紧密配合:
- 帧选择在最前面,把烂帧挡在门外
- 运动补偿把好帧对齐到同一坐标系
- 时域滤波在对齐后的帧上做平均
- 空域滤波在时域滤波之后,处理残留噪声
这个顺序不能乱。我曾经试过先做空域滤波再做时域滤波,结果噪声是去掉了,但细节也丢了不少。嗯,后来老老实实按顺序来。