3、多帧合成原理:短帧、中帧、长帧的曝光策略、帧对齐与运动补偿、权重映射与融合算法

多帧合成,说白了就是让摄像头像人眼一样,在不同亮度下各拍一张,然后挑最好的部分拼起来。我在RK平台上调过不少项目,发现很多工程师把精力全放在算法上,却忽略了最基础的东西——曝光策略。曝光策略没定好,后面帧对齐和融合做得再好,也是白搭。

这一章,我就把多帧合成的三个核心环节拆开来讲:曝光策略、帧对齐与运动补偿、权重映射与融合算法。你想想看,这三个环节任何一个出问题,最终HDR效果都会崩。

3.1 短帧、中帧、长帧的曝光策略

曝光策略,就是决定三帧分别用多少曝光时间、多少增益。我习惯把这三帧称为:短帧(S)、中帧(M)、长帧(L)。它们的核心任务很简单:

  • 短帧:保住高光细节,防止过曝。
  • 长帧:提亮暗部细节,防止欠曝。
  • 中帧:作为主帧,提供中间调的画质基准。

曝光时间的比例,我一般推荐 1:4:16 或 1:8:64。具体选哪个,取决于场景的动态范围。举个例子,在RK3588上调试一个户外逆光场景,我用的是1:4:16,短帧1ms,中帧4ms,长帧16ms。为什么是这个比例?因为传感器在16ms时信噪比还能接受,再长就出现热噪点了。

关键指标:曝光比

曝光比 = 长帧曝光时间 / 短帧曝光时间。这个值决定了HDR能覆盖的动态范围。曝光比越大,动态范围越宽,但帧对齐难度也越大。我个人建议,在运动场景中曝光比不要超过16倍,否则运动鬼影会很难处理。

增益策略上,我有个习惯:优先调曝光时间,再调增益。因为增益会放大噪声,尤其是长帧。我曾经在RK3399上踩过一个坑——为了省帧率,把长帧增益拉到12dB,结果暗部全是彩色噪点,降噪都救不回来。后来我改成延长曝光时间、降低增益,效果立竿见影。

参数 短帧 中帧 长帧
曝光时间 1x 4x 16x
模拟增益 1x (0dB) 1x~2x 1x~4x
数字增益 1x 1x 1x~2x
主要任务 保高光 主画质 提暗部

注意:数字增益尽量少用。它只是把信号放大,噪声也会被放大。我在项目中一般把数字增益限制在2x以内,超过这个值,暗部画质会明显劣化。

3.2 帧对齐与运动补偿

三帧曝光时间不同,拍摄时刻也不同。如果场景中有运动物体,比如行人、车辆,三帧中物体的位置会不一样。直接融合,就会出现鬼影——物体边缘出现半透明的重影。

帧对齐,就是把这些错位的像素找回来。我常用的方法是基于块匹配的运动估计。说白了,就是把图像分成16x16或32x32的小块,然后在相邻帧中搜索最匹配的位置。

具体流程是这样的:

  1. 参考帧选择:一般选中帧作为参考帧,因为它的曝光时间居中,画质最好。
  2. 块匹配:对每个块,在短帧和长帧中搜索最佳匹配位置。搜索范围一般是±32像素。
  3. 运动矢量计算:得到每个块的位移量(dx, dy)。
  4. 运动补偿:根据运动矢量,对短帧和长帧进行重采样,对齐到参考帧。

嗯,这里要注意。块匹配有个问题——遮挡。比如一个行人走过,他在短帧中出现在位置A,在长帧中出现在位置B,但位置B在短帧中被背景挡住了。这种情况下,匹配会失败。我一般会加一个置信度判断:如果匹配误差太大,就标记为“不可靠区域”,在融合时降低权重。

我的经验:在RK平台上,运动估计的搜索范围不要设太大。搜索范围越大,计算量越大,而且容易匹配到错误位置。我一般设±16像素,配合多分辨率金字塔,效果和性能都能兼顾。

运动补偿还有一个变种——光流法。光流法比块匹配更精细,能计算每个像素的运动矢量,但计算量也大得多。在RK3588的NPU上,我试过用光流法做帧对齐,效果确实好,但帧率从30fps掉到了15fps。所以,移动端还是优先用块匹配。

3.3 权重映射与融合算法

帧对齐之后,三帧已经对齐到同一个坐标系了。接下来就是融合——把三帧中最好的部分挑出来,合成一张HDR图像。

权重映射,就是给每个像素分配一个权重,告诉融合算法“这个像素值不值得信”。权重一般基于三个指标:

  • 曝光度:像素值越接近中间调(比如128/255),权重越高。过曝或欠曝的像素权重低。
  • 对比度:局部对比度高的区域,权重高。这能保留纹理细节。
  • 饱和度:颜色饱和度高的区域,权重高。防止融合后颜色变灰。

我常用的权重函数是这样的:

// 基于曝光度的权重
float weight_exposure(float pixel_value) {
    // 像素值归一化到0~1
    float v = pixel_value / 255.0f;
    // 高斯型权重,峰值在0.5
    return exp(-pow((v - 0.5f) * 4.0f, 2.0f));
}

融合算法,最经典的是多尺度融合(Laplacian Pyramid)。为什么用多尺度?因为不同尺度下,图像的特征不一样。大尺度(低频)决定整体亮度,小尺度(高频)决定纹理细节。多尺度融合能分别处理,效果更自然。

流程是这样的:

  1. 对三帧分别构建拉普拉斯金字塔(一般4~6层)。
  2. 对权重图也构建高斯金字塔(平滑权重图)。
  3. 每层金字塔中,用权重图加权融合三帧的系数。
  4. 从顶层到底层,逐层重建,得到最终HDR图像。

核心公式:

融合后的第l层系数 = Σ (权重图第l层 × 帧的第l层系数) / Σ 权重图第l层

说白了,就是加权平均,但权重和系数都在金字塔域中处理。

还有一种更轻量的方法——单尺度加权融合。直接对原始图像做加权平均,不做金字塔。优点是速度快,缺点是容易产生光晕(halo)。我在RK3566上做过对比,单尺度融合在边缘处会出现明显的亮度跳变,而多尺度融合就平滑得多。

我曾经在RK3588上调试一个室内暗光场景,长帧曝光时间到了32ms,短帧只有2ms。融合时发现,长帧的暗部噪声被带到了最终图像中。后来我在权重映射中加了一个噪声估计项——如果某个像素的局部方差太大(说明噪声多),就降低它的权重。这样,噪声区域主要由中帧和短帧贡献,暗部画质明显提升。

避坑指南:我曾经在RK3399上遇到一个鬼影问题,怎么调都调不好。后来发现,问题出在帧对齐的搜索范围上——我设了±64像素,结果运动矢量经常匹配到错误位置。改成±16像素后,鬼影消失了。所以,搜索范围不是越大越好,要根据实际运动幅度来定。

3.4 本章知识体系

下面这张图,我把多帧合成的核心流程画出来了。你可以对照着看,每个环节的输入输出是什么,以及它们之间的依赖关系。

多帧合成核心流程 多帧合成核心流程 短帧 (S) 中帧 (M) 长帧 (L) 曝光策略 (1:4:16 或 1:8:64) 帧对齐与运动补偿 (块匹配/光流) 权重映射 (曝光度/对比度/饱和度) 融合算法 (多尺度/单尺度) HDR 合成图像 关键参数 • 曝光比:4x~64x • 搜索范围:±16~±32像素 • 金字塔层数:4~6层 常见问题 • 鬼影:帧对齐失败 • 光晕:单尺度融合 • 噪声:长帧增益过高

从这张图你可以看到,整个流程是串行的。曝光策略决定了输入质量,帧对齐解决了运动问题,权重映射决定了融合的优先级,融合算法最终合成结果。任何一个环节出问题,都会影响最终效果。

我个人觉得,初学者最容易忽略的是权重映射。很多人以为帧对齐做好了,直接平均就行。但实际项目中,权重映射才是决定画质的关键。你想想看,如果长帧的暗部噪声很大,你还给它高权重,那融合结果肯定一团糟。所以,权重映射一定要结合噪声估计和运动置信度,不能只看曝光度。