4. 曝光策略设计:短/中/长曝光帧的确定、曝光时间与增益计算

HDR多帧合成的核心在于通过不同曝光参数的帧捕获同一场景的不同亮度区域,最终融合为一张高动态范围图像。曝光策略直接决定了合成质量:过曝或欠曝的帧会导致细节丢失,而曝光间隔不合理则会产生鬼影或噪声放大。本节将系统讲解三帧HDR的曝光帧确定方法、曝光时间与增益的计算模型,以及在实际Camera HAL中的实现要点。

核心原则:短帧保护高光细节,长帧提亮暗部细节,中帧作为主参考帧保证信噪比与色彩还原。三帧的曝光量通常以EV(Exposure Value)步进为基准,步进值一般取1.0~2.0 EV。

4.1 短/中/长曝光帧的确定策略

曝光帧的确定需要综合考虑传感器动态范围、场景亮度分布以及合成算法的鲁棒性。以下是业界通用的三帧HDR曝光帧确定流程:

  1. 场景亮度评估:通过AE(自动曝光)统计直方图,获取当前场景的亮度分布,确定中值亮度Lmid与动态范围跨度ΔL。
  2. 中帧(参考帧)设定:中帧曝光量Emid以场景平均亮度为目标,保证主体区域曝光正常,通常作为合成的主参考帧。
  3. 短帧(高光保护帧)设定:短帧曝光量Eshort = Emid / 2EV_step,确保高光区域(如天空、灯源)不饱和。
  4. 长帧(暗部提亮帧)设定:长帧曝光量Elong = Emid × 2EV_step,确保暗部区域(如阴影、背光面)有足够信噪比。
  5. 边界检查:检查短帧曝光时间是否大于传感器最小曝光行时间,长帧曝光时间是否小于最大帧时长(通常受帧率限制)。
实战建议:在Camera HAL实现中,曝光帧的确定通常放在AE算法模块的HDR分支中。建议将EV步进值作为可调参数(如1.5 EV),通过vendor tag暴露给上层应用,便于不同场景的调优。

下表总结了三种曝光帧的典型特征与适用场景:

曝光帧类型 曝光量相对中帧 典型EV步进 主要作用 适用场景
短帧(Short) Emid / 2EV_step -1.0 ~ -2.0 EV 保护高光细节,防止过曝 逆光、强光源、天空
中帧(Middle) Emid(基准) 0 EV 主参考帧,保证主体曝光与色彩 一般场景、人脸、主体
长帧(Long) Emid × 2EV_step +1.0 ~ +2.0 EV 提亮暗部,提升信噪比 阴影、背光面、夜景
避坑提示:EV步进值并非越大越好。步进超过2.0 EV时,短帧与长帧之间的亮度差异过大,合成时容易出现鬼影、色彩断层或噪声放大。建议在1.0~1.5 EV范围内进行初始调优。
三帧HDR曝光帧确定流程图 场景亮度评估 中帧(参考帧)设定 短帧(高光保护) 长帧(暗部提亮) 边界检查与调整 说明:EV步进值通常取1.0~2.0,步进过大会导致鬼影与噪声;边界检查确保帧时长在传感器能力范围内。

4.2 曝光时间与增益计算模型

曝光量E由曝光时间T和模拟增益G共同决定:E = T × G。在HDR多帧合成中,我们需要为每一帧分配独立的(T, G)组合,使得三帧的曝光量满足预设的EV步进关系,同时保证帧率稳定和噪声可控。

4.2.1 基础计算公式

设中帧的曝光时间为Tmid,模拟增益为Gmid,则中帧曝光量Emid = Tmid × Gmid。短帧与长帧的曝光量计算如下:

// 短帧曝光量计算
E_short = E_mid / (1 << EV_step)   // EV_step为整数步进值
// 长帧曝光量计算
E_long  = E_mid * (1 << EV_step)

// 实际分配时,优先调整曝光时间,增益作为辅助调节
// 短帧:先减小曝光时间,若时间过短则降低增益
T_short = min(T_mid / (1 << EV_step), T_min_sensor)
G_short = E_short / T_short

// 长帧:先增加曝光时间,若时间过长则提高增益
T_long  = min(T_mid * (1 << EV_step), T_max_frame)
G_long  = E_long / T_long
关键约束:模拟增益G通常有上限(如ISO 1600对应增益约32x),超过上限需启用数字增益(DG),但数字增益会放大噪声,应尽量避免。在HDR长帧中,优先使用模拟增益,数字增益仅作为最后手段。

4.2.2 实际分配策略

在实际Camera HAL中,曝光时间与增益的分配需要遵循以下优先级规则:

  • 时间优先:优先调整曝光时间,因为时间变化不影响信噪比(SNR),而增益会放大噪声。
  • 增益约束:模拟增益不超过传感器最大模拟增益(通常为16x~32x),数字增益不超过2x。
  • 帧率约束:三帧的总采集时间不能超过目标帧率的周期。例如30fps下,三帧总时间需小于33ms。
  • 最小时间约束:短帧曝光时间不能小于传感器最小曝光行时间(通常为1~2行扫描时间)。

下表展示了一个典型场景下的曝光参数分配示例(传感器最大模拟增益32x,最小曝光时间0.1ms,目标帧率30fps):

参数 短帧 中帧 长帧
EV步进 -1.5 EV 0 EV +1.5 EV
曝光时间 (ms) 1.0 8.0 22.0
模拟增益 (ISO) 100 100 200
数字增益 1.0 1.0 1.0
曝光量 (相对值) 0.35 1.0 2.83
注意:上表中长帧曝光时间22ms + 中帧8ms + 短帧1ms = 31ms,刚好满足30fps(33ms周期)的帧率要求。如果长帧时间超过22ms,则需要降低增益或减小EV步进,否则帧率会下降。
曝光时间与增益分配策略图 目标EV步进与帧率 时间优先分配 模拟增益 ≤ 上限? 是:直接使用 否:调整时间/增益 输出(T, G)组合 说明:时间优先原则保证信噪比;模拟增益超限时,需减小EV步进或增加数字增益(慎用)。

4.3 Camera HAL中的实现要点

在Camera HAL层实现HDR曝光策略时,需要关注以下关键点:

  • 帧同步机制:三帧必须连续采集,帧间间隔尽量小(通常<1ms),避免场景变化导致鬼影。HAL需通过驱动层设置帧间延迟为0或最小值。
  • 曝光参数切换:在每一帧的VBLANK(垂直消隐)期间切换曝光时间和增益,确保帧与帧之间参数不冲突。
  • AE算法集成:HDR曝光策略作为AE算法的一个分支,在检测到高动态场景时自动切换。HAL需提供HDR使能开关和EV步进配置接口。
  • 传感器能力查询:通过sensor HAL接口获取最小/最大曝光时间、模拟增益范围、数字增益范围,用于边界检查。
代码片段示例:以下为Camera HAL中HDR曝光参数计算的简化实现(C++风格伪代码):
struct HdrExposureParams {
    int64_t exposure_time_ns[3];  // 短、中、长帧曝光时间(纳秒)
    float analog_gain[3];         // 短、中、长帧模拟增益
    float digital_gain[3];        // 短、中、长帧数字增益
};

HdrExposureParams CalculateHdrExposure(
    int64_t mid_exposure_time_ns,
    float mid_analog_gain,
    int ev_step,                  // EV步进值(如1表示1EV)
    const SensorCapability& cap)  // 传感器能力
{
    HdrExposureParams params;
    float ev_factor = powf(2.0f, ev_step);

    // 中帧参数直接赋值
    params.exposure_time_ns[1] = mid_exposure_time_ns;
    params.analog_gain[1] = mid_analog_gain;
    params.digital_gain[1] = 1.0f;

    // 短帧:时间优先,增益辅助
    int64_t short_time = mid_exposure_time_ns / ev_factor;
    if (short_time < cap.min_exposure_time_ns) {
        short_time = cap.min_exposure_time_ns;
    }
    params.exposure_time_ns[0] = short_time;
    float short_gain = (mid_exposure_time_ns * mid_analog_gain) /
                       (short_time * ev_factor);
    // 增益分配:优先模拟增益
    if (short_gain <= cap.max_analog_gain) {
        params.analog_gain[0] = short_gain;
        params.digital_gain[0] = 1.0f;
    } else {
        params.analog_gain[0] = cap.max_analog_gain;
        params.digital_gain[0] = short_gain / cap.max_analog_gain;
    }

    // 长帧:时间优先,增益辅助
    int64_t long_time = mid_exposure_time_ns * ev_factor;
    if (long_time > cap.max_exposure_time_ns) {
        long_time = cap.max_exposure_time_ns;
    }
    params.exposure_time_ns[2] = long_time;
    float long_gain = (mid_exposure_time_ns * mid_analog_gain * ev_factor) /
                      long_time;
    if (long_gain <= cap.max_analog_gain) {
        params.analog_gain[2] = long_gain;
        params.digital_gain[2] = 1.0f;
    } else {
        params.analog_gain[2] = cap.max_analog_gain;
        params.digital_gain[2] = long_gain / cap.max_analog_gain;
    }

    return params;
}
实战调优建议:在HAL层实现时,建议将EV步进值、模拟增益上限、数字增益上限作为可调参数,通过vendor tag暴露给相机服务层。不同传感器(如IMX586 vs OV64B)的增益特性差异较大,需要针对每个模组单独标定。