4、AE高级策略:多帧合成HDR、局部曝光调整、防闪烁(Flicker)检测、背光场景处理

各位好,我是老周。上一章我们把AE的基础框架聊透了,这一章咱们来点硬核的——AE的高级策略。说白了,就是那些让普通相机变成“智能相机”的算法。

你想想看,一个手机对着大逆光拍人,人脸黑成剪影,背景亮成一片白,这能忍吗?或者晚上拍路灯,画面一闪一闪的,看着就头晕。这些场景,光靠基础的AE算法根本搞不定。我这些年调过的项目里,至少有一半的“疑难杂症”都出在这几个高级策略上。

4.1 多帧合成HDR:动态范围的终极武器

先聊聊HDR。HDR不是啥新鲜词了,但多帧合成HDR和那种简单的“拍三张合成”完全是两码事。

我个人的习惯是,把多帧HDR分成两个流派:曝光融合(Exposure Fusion)和高动态范围重建(HDR Reconstruction)。

流派 核心思路 输出格式 适用场景
曝光融合 多帧直接融合,不生成HDR中间图 8-bit SDR 预览、实时取景
HDR重建 先合成高位深HDR图,再Tone Mapping 10/12-bit HDR 拍照、专业模式

曝光融合的好处是快,适合实时预览。但缺点也很明显——它没法保留真正的HDR信息,后期调不了。HDR重建就不一样了,它先合成一张高位深的RAW图,然后再做色调映射。嗯,这里要注意,HDR重建的瓶颈往往不在AE,而在后面的Tone Mapping。

我在项目中遇到过一个问题:三帧曝光(-2EV, 0EV, +2EV)合成后,中间调总是有鬼影。后来发现是运动物体对齐没做好。多帧HDR最怕的就是运动物体,尤其是手抖和行人。

核心流程:

  1. 帧选择:从连拍序列里挑出曝光质量最好的3-5帧
  2. 运动对齐:基于光流或块匹配,把非参考帧对齐到参考帧
  3. 权重计算:根据像素的对比度、饱和度、曝光良好度分配融合权重
  4. 融合合成:拉普拉斯金字塔融合,避免接缝
  5. Tone Mapping:把高动态范围压缩到显示设备能接受的范围内

这里有个避坑指南:我曾经在权重计算上踩过坑。直接用像素亮度算权重,结果高光区域权重太高,暗部细节全丢了。后来改成用局部对比度加饱和度的联合权重,效果才正常。

// 伪代码:权重计算
float weight_contrast = compute_local_contrast(pixel, window_size);
float weight_saturation = compute_saturation(pixel);
float weight_well_exposed = gaussian_weight(pixel.luminance, target_luminance);

float final_weight = weight_contrast * 0.4 + weight_saturation * 0.3 + weight_well_exposed * 0.3;

4.2 局部曝光调整:告别“一刀切”

全局AE有个硬伤——它只能照顾到画面的大部分区域。遇到背光人脸、夜景霓虹灯这种场景,全局曝光就是“顾头不顾腚”。

局部曝光调整,说白了就是把画面分成若干区域,每个区域独立算曝光。我常用的方法是基于网格的局部AE。

具体做法是这样的:

  • 把画面分成16x16或32x32的网格
  • 每个网格独立计算目标亮度
  • 网格之间做平滑过渡,避免出现“马赛克”
  • 最终生成一张局部增益图(Local Gain Map)

你想想看,人脸区域的目标亮度是120,背景天空的目标亮度是80,那增益图在这两个区域的值就不一样。增益图本身是一张低分辨率的灰度图,然后上采样到原图大小,逐像素乘上去。

我的经验:局部增益图的分辨率不要太高。我试过32x32的网格,效果已经足够好。分辨率太高反而容易引入噪声,而且计算量翻倍。16x16是个不错的起点。

局部曝光调整还有个好处——它可以和人脸检测联动。检测到人脸后,直接把人脸区域的权重拉高,让AE优先保证人脸曝光正确。这个在手机拍照里几乎是标配了。

4.3 防闪烁(Flicker)检测:让画面不再“抽风”

防闪烁这个话题,说实话,挺烦人的。但你又不得不处理。

闪烁的根源是什么?是光源的交流电频率。50Hz的电网,灯光每秒闪烁100次(因为交流电一个周期闪两次)。60Hz的电网,每秒闪120次。相机的曝光时间如果和这个频率不同步,画面就会忽明忽暗。

我遇到过最头疼的情况是:室内混合光源——一半是LED灯,一半是日光灯。LED的闪烁频率和日光灯不一样,防闪烁算法直接懵了。

防闪烁检测的核心步骤:

  1. 频闪检测:连续采集多帧的亮度值,做FFT分析,看有没有50Hz/60Hz的峰值
  2. 频率锁定:检测到闪烁后,锁定闪烁频率
  3. 曝光时间约束:把曝光时间限制为闪烁周期的整数倍

举个例子,50Hz的灯光,闪烁周期是10ms。那曝光时间就只能设为10ms、20ms、30ms……不能设成15ms或25ms。否则画面一定会闪。

注意:曝光时间约束会牺牲一部分曝光精度。比如你算出来目标曝光时间是23ms,但为了防闪烁,只能取20ms或30ms。这时候需要配合增益(ISO)来补偿。我曾经因为没处理好这个补偿,导致画面亮度跳变,比闪烁还难看。

防闪烁还有一个变种——滚动快门下的条纹消除。这个在拍屏幕或LED广告牌时特别明显。解决办法是调整曝光时间,让每行像素的积分时间对齐到光源的亮周期。

4.4 背光场景处理:逆光也不怕

背光场景,说白了就是大光比。人脸暗、背景亮,或者反过来。这种场景下,全局AE基本是废的。

我处理背光场景的思路是分三步走:

  • 场景检测:先判断是不是背光。看直方图,如果暗部区域和亮部区域都有大量像素,中间调很少,那大概率是背光。
  • 策略选择:根据光比大小,决定用局部曝光调整还是多帧HDR。光比小于3:1,局部调整就够了;光比大于3:1,上HDR。
  • 后处理补偿:如果硬件来不及做多帧,那就用数字增益把暗部拉起来,同时做降噪。

这里有个关键参数——背光因子(Backlight Factor)。我习惯用这个公式:

backlight_factor = (average_luminance_of_face_region) / (average_luminance_of_background_region)
if backlight_factor < 0.3:
    trigger_backlight_mode()

当背光因子小于0.3时,说明人脸比背景暗了3倍以上,必须启动背光模式。

我在项目中遇到过一个问题:背光检测太灵敏,稍微有点逆光就触发HDR,结果正常场景也被拍成了“假HDR”风格。后来加了一个置信度阈值,只有连续3帧都检测到背光,才真正切换模式。这个“防抖”逻辑在很多场景下都管用。

背光场景处理流程总结:

步骤 操作 输出
1 直方图分析 + 人脸检测 背光因子、人脸位置
2 光比计算 是否需要HDR
3 局部增益图生成 16x16增益图
4 增益应用 + 降噪 最终RAW图