3. HDR多帧捕获原理:曝光包围与帧序列设计

HDR(高动态范围)成像的核心在于通过多帧捕获扩展传感器的动态范围。本章深入剖析曝光包围(Exposure Bracketing)与帧序列(Frame Sequence)的设计原理,这是Android相机框架实现HDR模式的底层基础。

3.1 曝光包围(Exposure Bracketing)

曝光包围是指相机以不同的曝光参数(快门速度、ISO、增益)连续拍摄多帧图像,从而覆盖从暗部到亮部的完整亮度范围。每一帧捕获场景中不同亮度区间的细节,最终通过融合算法合成一张高动态范围图像。

3.1.1 曝光包围的核心参数

参数 说明 典型值
包围步长(EV Step) 相邻帧之间的曝光量差值,以EV(曝光值)为单位 1.0 EV、2.0 EV
包围帧数 一次HDR捕获中拍摄的总帧数 3帧、5帧、7帧
基准帧(Reference Frame) 以场景测光结果确定的中间曝光帧 0 EV
欠曝帧(Underexposed) 低于基准曝光,保留高光细节 -1 EV、-2 EV
过曝帧(Overexposed) 高于基准曝光,保留暗部细节 +1 EV、+2 EV
设计要点:步长过小(如0.5 EV)会导致帧间亮度重叠过多,融合增益有限;步长过大(如3.0 EV)则可能产生亮度断层,融合后出现伪影。Android Camera2框架推荐步长范围为1.0~2.0 EV。

3.1.2 对称包围与非对称包围

  • 对称包围:欠曝帧与过曝帧的EV绝对值相等,如[-2, 0, +2]。适用于光照均匀的场景。
  • 非对称包围:根据场景动态范围分布调整欠曝/过曝的步长,如[-3, 0, +1]。适用于高光区域远多于暗部或反之的场景。
实战建议:在移动设备上,由于传感器噪声和运动模糊的限制,3帧对称包围(-2 EV, 0 EV, +2 EV)是最常用的配置,兼顾了动态范围扩展与计算开销。

3.2 帧序列(Frame Sequence)设计

帧序列定义了多帧捕获的时序、顺序和同步策略。合理的帧序列设计能够最小化帧间运动、减少鬼影(Ghosting)并保证融合质量。

3.2.1 帧序列的三种典型模式

模式 描述 适用场景
顺序捕获(Sequential) 按曝光顺序逐帧拍摄,帧间存在时间间隔 静态场景、三脚架拍摄
交错捕获(Interleaved) 在预览流中插入HDR帧,与预览帧交替输出 实时取景、零快门延迟
突发捕获(Burst) 以最高帧率连续拍摄多帧,帧间间隔最小 手持拍摄、运动场景
注意:顺序捕获模式下,帧间时间差可达数十毫秒,容易因手抖或物体运动导致帧间错位。Android Camera2框架通过CAPTURE_INTENT和REQUEST_QUEUE机制控制帧序列的时序,开发者需合理设置TEMPLATE_STILL_CAPTURE与AE_MODE。

3.2.2 帧序列的曝光顺序策略

曝光顺序直接影响融合质量。常见的顺序策略包括:

  • 低→中→高(L→M→H):先拍欠曝帧,再拍基准帧,最后拍过曝帧。优点是传感器从低曝光开始,避免高曝光后的残留电荷影响后续帧。
  • 高→中→低(H→M→L):先拍过曝帧,再拍基准帧,最后拍欠曝帧。适用于暗部细节优先的场景。
  • 中→低→高(M→L→H):以基准帧为起点,向两侧扩展。适合运动场景,因为基准帧的曝光时间最接近用户预期。
推荐策略:在Android平台上,L→M→H顺序配合CONTROL_AE_MODE_ON自动曝光锁定,能够获得最佳的帧间一致性。基准帧通常作为融合的参考帧(Reference Frame),用于对齐和权重计算。

3.3 曝光包围与帧序列的协同设计

曝光包围决定了“拍什么”,帧序列决定了“怎么拍”。两者协同设计才能实现高效的多帧捕获。

3.3.1 协同设计流程

  1. 场景分析:通过预览帧的直方图分析场景动态范围,确定包围步长和帧数。
  2. 帧序列规划:根据场景运动程度选择突发或顺序模式,并确定曝光顺序。
  3. 参数下发:通过CaptureRequest.Builder设置每帧的SENSOR_EXPOSURE_TIME、SENSOR_SENSITIVITY和CONTROL_AE_MODE。
  4. 帧同步:利用CaptureCallback监听每帧的完成状态,确保所有帧在融合前全部就绪。
  5. 元数据记录:每帧携带曝光参数、时间戳、传感器增益等元数据,供融合算法使用。

3.3.2 帧序列设计中的关键约束

约束项 说明 影响
帧间隔(Frame Interval) 相邻帧之间的最小时间差,由传感器帧率决定 帧间隔越小,运动伪影越少
曝光时间总和 所有帧的曝光时间之和不能超过用户可接受的延迟 通常限制在200ms以内
传感器读出时间 每帧曝光结束后传感器读出数据所需时间 影响帧序列的总耗时
ISP管线延迟 图像信号处理(ISP)处理每帧的时间 影响帧序列的吞吐量

3.4 曝光包围与帧序列的SVG架构图

下图展示了3帧对称曝光包围与突发捕获帧序列的协同工作流程:

曝光包围与帧序列协同架构图 曝光包围与帧序列协同架构 场景直方图分析 包围参数决策:步长/帧数/顺序 帧序列规划:突发/交错/顺序 帧1:欠曝 (-2 EV) 曝光时间: 5ms 帧2:基准 (0 EV) 曝光时间: 20ms 帧3:过曝 (+2 EV) 曝光时间: 80ms 帧间隔 8ms 帧间隔 8ms 元数据收集:时间戳 / 曝光参数 / 传感器增益 / AE状态 多帧融合算法输入 总捕获时间 = 5ms + 8ms + 20ms + 8ms + 80ms = 121ms(满足200ms约束)

3.5 帧序列设计中的运动补偿策略

手持拍摄时,帧间运动不可避免。帧序列设计需要为后续的运动补偿(Motion Compensation)提供支持:

  • 时间戳对齐:每帧记录硬件时间戳(SensorTimestamp),用于运动估计算法计算帧间位移。
  • 参考帧选择:通常选择基准帧(0 EV)作为对齐参考,因为其信噪比最高。
  • 帧间重叠区域:设计帧序列时预留10%~20%的视场重叠,便于特征匹配和配准。
工程实践:在Android Camera2框架中,通过CaptureRequest.CONTROL_ENABLE_ZSL启用零快门延迟(ZSL)模式时,帧序列会自动插入到预览流中。此时需要特别注意CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION的逐帧设置,避免预览帧与HDR帧的曝光冲突。

3.6 曝光包围与帧序列的代码示例

以下代码展示了如何使用Android Camera2 API配置3帧曝光包围的帧序列:

// 构建3帧曝光包围的CaptureRequest序列
List<CaptureRequest> hdrRequestList = new ArrayList<>();

// 帧1:欠曝帧 (-2 EV)
CaptureRequest.Builder builder1 = cameraDevice.createCaptureRequest(
    CameraDevice.TEMPLATE_STILL_CAPTURE);
builder1.set(CaptureRequest.CONTROL_AE_MODE, 
    CaptureRequest.CONTROL_AE_MODE_OFF);
builder1.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 5_000_000L); // 5ms
builder1.set(CaptureRequest.SENSOR_SENSITIVITY, 100);
builder1.addTarget(surface);
hdrRequestList.add(builder1.build());

// 帧2:基准帧 (0 EV)
CaptureRequest.Builder builder2 = cameraDevice.createCaptureRequest(
    CameraDevice.TEMPLATE_STILL_CAPTURE);
builder2.set(CaptureRequest.CONTROL_AE_MODE, 
    CaptureRequest.CONTROL_AE_MODE_OFF);
builder2.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 20_000_000L); // 20ms
builder2.set(CaptureRequest.SENSOR_SENSITIVITY, 200);
builder2.addTarget(surface);
hdrRequestList.add(builder2.build());

// 帧3:过曝帧 (+2 EV)
CaptureRequest.Builder builder3 = cameraDevice.createCaptureRequest(
    CameraDevice.TEMPLATE_STILL_CAPTURE);
builder3.set(CaptureRequest.CONTROL_AE_MODE, 
    CaptureRequest.CONTROL_AE_MODE_OFF);
builder3.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 80_000_000L); // 80ms
builder3.set(CaptureRequest.SENSOR_SENSITIVITY, 400);
builder3.addTarget(surface);
hdrRequestList.add(builder3.build());

// 通过CaptureSession按顺序提交帧序列
for (CaptureRequest request : hdrRequestList) {
    captureSession.capture(request, hdrCaptureCallback, null);
}
关键注意:上述代码中CONTROL_AE_MODE_OFF表示完全手动控制曝光参数。在实际产品中,建议使用CONTROL_AE_MODE_ON配合CONTROL_AE_EXPOSURE_COMPENSATION实现自动曝光包围,这样传感器可以自动调整增益和曝光时间,同时保持AE算法的稳定性。

3.7 本章小结

曝光包围与帧序列设计是HDR多帧捕获的基石。曝光包围通过合理的步长和帧数选择扩展动态范围,帧序列通过时序和顺序策略保证帧间一致性。两者协同设计时,需要综合考虑场景动态范围、运动程度、传感器能力和用户延迟容忍度。在Android Camera2框架中,开发者通过CaptureRequest的精细配置和CaptureCallback的帧同步机制,可以实现高效、鲁棒的HDR多帧捕获管线。