2、多帧HDR原理:曝光序列、对齐、鬼影与权重计算

好,咱们正式开始啃多帧HDR的核心原理。这部分你要是搞懂了,后面工程落地就是水到渠成的事。我个人习惯把多帧HDR拆成四个关键环节:怎么拍、怎么对齐、怎么防鬼影、怎么融合。一个一个来。

2.1 多帧曝光序列的获取

说白了,多帧HDR的第一步就是让相机拍一组不同亮度的照片。为什么要这么干?因为单张照片的动态范围有限,亮的地方过曝,暗的地方死黑,你后期怎么拉都拉不回来。

我见过不少新手直接用手动曝光拍三张:-2EV、0EV、+2EV。这方法简单,但不够灵活。实际工程中,我更推荐用自动包围曝光(AEB)模式。你只需要设定步长和帧数,相机自动帮你搞定。

关键参数:

  • 帧数:3帧是入门,5帧是主流,7帧以上用于极端场景(比如夜景逆光)。
  • 步长:1EV步长适合大多数场景,2EV步长适合高对比度场景。
  • 曝光顺序:建议从暗到亮拍,或者从亮到暗拍,不要乱序。

这里有个坑。我曾经在项目中遇到一个问题:手机连拍三帧,结果因为手抖,三张图的偏移量超过了10个像素。你想想看,这种数据喂给融合算法,出来的图全是重影。所以,帧间对齐就成了绕不开的一步。

2.2 帧间对齐的必要性

多帧曝光序列是在不同时间点拍的。手持拍摄、物体运动、甚至风吹草动,都会导致帧与帧之间出现偏移。如果不做对齐,直接融合,结果就是边缘模糊、细节丢失。

对齐算法有很多种,我简单列一下常见的:

对齐方法 原理 适用场景 计算量
全局平移 假设整张图只有平移 三脚架固定拍摄 低
仿射变换 支持旋转+缩放+平移 手持轻微抖动 中
光流法 逐像素计算运动矢量 有局部运动(如行人) 高
特征匹配 提取SIFT/ORB特征点 大视角变化 高

我个人习惯在移动端用分层光流。先降采样,在低分辨率上算一个粗略的运动场,再上采样到原图做精细调整。这样既保证了精度,又控制了计算量。嗯,这里要注意:光流法对纹理少的区域(比如白墙)效果很差,这时候要回退到全局仿射。

2.3 鬼影问题的来源

鬼影,是多帧HDR最头疼的问题。没有之一。

鬼影怎么来的?很简单:场景中有运动物体。比如一个人从镜头前走过,他在暗帧里出现在位置A,在亮帧里出现在位置B。融合的时候,算法把两个位置的信息叠加在一起,结果就是半透明的重影。

鬼影的典型场景:

  • 行人、车辆移动
  • 树叶被风吹动
  • 水面波纹
  • 灯光闪烁(LED屏幕、车灯)

我曾经在一个安防项目中吃过亏。监控摄像头拍夜间车牌,结果因为旁边有棵树被风吹动,融合出来的车牌全是树叶的鬼影。后来我加了一个运动区域检测的步骤,只对静态区域做多帧融合,动态区域直接用单帧数据。效果立竿见影。

为什么会这样?因为传统HDR假设所有帧都是静态的。一旦这个假设不成立,鬼影就来了。所以,现代HDR算法必须引入运动检测和鬼影抑制机制。

2.4 融合权重计算逻辑

权重计算,是HDR融合的核心。说白了,就是决定每一帧的每个像素,在最终结果里占多大比重。

常见的权重计算策略有三种:

  1. 基于曝光度的权重:中间曝光的权重最高,过曝和欠曝的权重低。简单,但效果一般。
  2. 基于对比度的权重:纹理丰富的区域权重高,平坦区域权重低。能保留更多细节。
  3. 基于饱和度的权重:颜色饱和的区域权重高,过曝/欠曝区域权重低。防止颜色失真。

实际工程中,我通常把三种权重结合起来。给你看一个我常用的权重计算公式:

// 伪代码:多帧HDR权重计算
float computeWeight(float exposure, float contrast, float saturation) {
    float w_exposure = exp(-pow((exposure - 0.5) / 0.2, 2));
    float w_contrast  = pow(contrast, 2);
    float w_saturation = 1.0 - abs(saturation - 0.5) * 2;
    return w_exposure * w_contrast * w_saturation;
}

这个公式的核心思想是:中间曝光、纹理丰富、颜色适中的像素,权重最高。过曝和欠曝的像素,权重被指数压低。

避坑指南:

我曾经在权重计算后忘记做归一化,结果融合出来的图整体偏暗。后来我加了一步:weight_sum = sum(weights); output = sum(weighted_pixels) / weight_sum;。归一化是必须的,别偷懒。

最后,我把整个多帧HDR的流程画成了一张图,方便你理解各个环节的关系。

多帧HDR融合流程 多帧曝光序列 -2EV / 0EV / +2EV 帧间对齐 光流 / 仿射变换 鬼影检测 运动区域标记 权重计算 曝光/对比度/饱和度 鬼影抑制 动态区域权重置零 加权融合输出 HDR图像 核心逻辑:先对齐 → 再检测鬼影 → 计算权重 → 最后融合。鬼影区域权重置零,避免重影。

这张图把整个流程串起来了。你注意看,鬼影检测和权重计算是并行的,但鬼影抑制的结果会直接影响权重。说白了,检测到运动区域,就把那部分的权重直接清零,不让它参与融合。