3. AE场景适配策略:背光/顺光/夜景/高动态场景的AE策略

AE(自动曝光)这东西,说白了就是帮摄像头找到那个「不亮不暗刚刚好」的曝光值。但现实世界哪有那么多「刚刚好」?背光人脸黑成剪影、夜景噪点满天飞、高动态场景亮部死白暗部死黑……这些都是AE要解决的硬骨头。

我刚开始调AE那会儿,总觉得算法能自动搞定一切。直到有一次在强背光会议室里,领导的脸完全看不见,我才意识到——场景适配策略才是AE的灵魂。

3.1 四大典型场景的AE策略

3.4.1 背光场景:人脸不能丢

背光,就是主体背后有强光源。人脸在画面中占比小、亮度低,全局测光很容易把背景曝得正常,人脸却黑成一团。

我的策略:

  • 人脸优先:检测到人脸时,强制把人脸区域作为曝光参考。权重至少占60%以上。
  • 局部提亮:AE计算目标亮度时,对人脸区域的目标亮度提高1~2档EV。
  • 防过曝裁剪:背景高亮区域不能完全不管。我会加一个「高亮保护」逻辑——如果背景亮度超过某个阈值(比如220/255),就适当降低整体曝光,避免背景死白。
实战技巧: 我在项目中遇到过一种情况——人脸检测偶尔会漏检侧脸。后来我加了一个「中心区域加权」作为兜底策略:即使没检测到人脸,画面中心区域也会获得更高的曝光权重。这样至少能保证主体不丢。

3.4.2 顺光场景:简单但别翻车

顺光是最「友好」的场景。光线均匀,动态范围小。但越简单越容易大意。

我的策略:

  • 全局平均测光:直接上全局平均,简单高效。
  • 目标亮度适中:一般设在18%灰附近(约120~128/255)。
  • 注意高光溢出:顺光下白色物体容易过曝。我会检查直方图最右端,如果像素堆积超过5%,就适当降0.3~0.5EV。
避坑: 我曾经在顺光场景下吃过亏——画面整体亮度正常,但人脸肤色偏黄。后来发现是AWB和AE的交互出了问题。AE把整体亮度压得太低,AWB为了补偿偏色,把色温调暖了。解决方案是:顺光场景下AE目标亮度不要低于110/255。

3.4.3 夜景场景:噪点与亮度的博弈

夜景是AE最难啃的骨头。亮度不够,噪点爆炸;亮度太高,画面假亮、运动模糊。

我的策略:

  • 曝光时间优先:先拉长曝光时间(上限30ms~60ms,视帧率而定),再提增益。
  • 增益上限控制:模拟增益不超过12dB,数字增益不超过6dB。超过这个范围,噪点就压不住了。
  • 目标亮度降低:夜景目标亮度设在80~100/255,比白天低一档。这样能保留夜景氛围,同时减少噪点。
  • 防闪烁:50Hz/60Hz光源下,曝光时间必须是10ms的整数倍(50Hz)或8.33ms的整数倍(60Hz)。
核心原则: 夜景AE不是追求「亮」,而是追求「看得清且噪点可接受」。我一般用「信噪比优先」策略——宁可暗一点,也不要满屏噪点。

3.4.4 高动态场景:HDR是救星

高动态场景(HDR)就是亮的地方特别亮、暗的地方特别暗。比如逆光窗户、日落天空、车灯夜景。单帧曝光根本搞不定。

我的策略:

  • 多帧合成HDR:拍2~3帧不同曝光的图像(短曝、中曝、长曝),然后合成。
  • AE控制曝光帧:AE负责决定每帧的曝光参数。短曝帧保护高光,长曝帧提亮暗部。
  • 动态范围目标:合成后的目标动态范围达到100dB以上。
  • 运动物体处理:多帧之间如果有运动,会产生鬼影。我会在AE层面控制帧间隔尽量短(< 16ms),同时配合去鬼影算法。
场景类型 测光模式 目标亮度 特殊处理
背光 人脸/中心加权 人脸区域140~160 高亮保护
顺光 全局平均 120~128 防高光溢出
夜景 全局平均+降噪 80~100 曝光时间优先,增益限制
高动态 多帧HDR 合成后100~120 防鬼影,帧间隔控制

3.2 AE权重矩阵与区域测光

全局平均测光太「笨」了。它把画面每个像素一视同仁,但实际场景中,不同区域的重要性完全不同。比如人脸区域的重要性远高于背景。

权重矩阵就是给画面不同区域分配不同的「话语权」。权重高的区域,对最终曝光值的影响更大。

3.2.1 权重矩阵的设计

我一般把画面分成15x15或17x17的网格。每个网格有一个权重值。权重值范围0~15。

// 15x15权重矩阵示例(中心区域权重高)
// 数值越大,权重越高
int weight_matrix[15][15] = {
    {1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1},
    {1, 1, 2, 2, 3, 4, 4, 4, 4, 4, 3, 2, 2, 1, 1},
    {1, 2, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 2, 1},
    {2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 5, 4, 3, 2, 2},
    {2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2},
    {3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3},
    {3, 4, 5, 6, 7, 8, 9, 9, 9, 8, 7, 6, 5, 4, 3},
    {3, 4, 5, 6, 7, 8, 9, 10,9, 8, 7, 6, 5, 4, 3},
    {3, 4, 5, 6, 7, 8, 9, 9, 9, 8, 7, 6, 5, 4, 3},
    {3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3},
    {2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2},
    {2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 5, 4, 3, 2, 2},
    {1, 2, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 2, 1},
    {1, 1, 2, 2, 3, 4, 4, 4, 4, 4, 3, 2, 2, 1, 1},
    {1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1}
};

这个矩阵的中心权重最高(10),边缘最低(1)。这样画面中心的主体对曝光的影响最大。

3.2.2 区域测光的计算

区域测光的最终曝光值计算公式很简单:

// 加权平均亮度计算
float total_weight = 0;
float weighted_sum = 0;

for (int i = 0; i < 15; i++) {
    for (int j = 0; j < 15; j++) {
        float block_luma = get_block_luma(i, j);  // 获取该区域平均亮度
        weighted_sum += block_luma * weight_matrix[i][j];
        total_weight += weight_matrix[i][j];
    }
}

float target_luma = weighted_sum / total_weight;

嗯,这里要注意:权重矩阵不是一成不变的。检测到人脸时,我会动态调整权重——把人脸所在区域的权重提高3~5倍。

我的习惯: 我会准备3套权重矩阵——「中心优先」「人脸优先」「全局均匀」。根据场景检测结果动态切换。这样既灵活又稳定。

3.3 AE Flicker抑制

Flicker(闪烁)是AE最烦人的问题之一。在50Hz或60Hz的交流光源下,如果曝光时间不是光源周期的整数倍,画面就会出现明暗交替的条纹或闪烁。

为什么会这样?

交流光源的亮度以100Hz(50Hz电源)或120Hz(60Hz电源)的频率波动。如果曝光时间不是波动周期的整数倍,每帧捕获的光能量就不一致,导致帧间亮度跳变。

3.3.1 Flicker检测

我一般用两种方法检测Flicker:

  • 帧间亮度波动检测:连续采集N帧的亮度值,计算方差。如果方差超过阈值,说明有Flicker。
  • 频域分析:对亮度序列做FFT,看100Hz/120Hz分量是否突出。

3.3.2 Flicker抑制策略

策略一:曝光时间锁定

最简单粗暴的方法——把曝光时间锁定为光源周期的整数倍。

// 50Hz光源:周期10ms,曝光时间必须是10ms的整数倍
// 60Hz光源:周期8.33ms,曝光时间必须是8.33ms的整数倍

int flicker_free_exposure(int target_exposure_us, int freq_hz) {
    int period_us = (freq_hz == 50) ? 10000 : 8333;
    int n = target_exposure_us / period_us;
    if (n < 1) n = 1;
    return n * period_us;
}

策略二:增益补偿

如果曝光时间不能锁定(比如夜景需要长曝光),可以用增益做动态补偿。检测到亮度波动时,实时调整增益来抵消波动。

策略三:帧率调整

调整帧率,使帧间隔是光源周期的整数倍。比如50Hz光源下,帧率设为25fps或50fps。

光源频率 周期 安全曝光时间(整数倍) 安全帧率
50Hz 10ms 10ms, 20ms, 30ms, 40ms... 25fps, 50fps
60Hz 8.33ms 8.33ms, 16.67ms, 25ms, 33.33ms... 30fps, 60fps
避坑: 我曾经在混合光源场景下翻过车——室内既有50Hz的日光灯,又有60Hz的显示器。单一频率的Flicker抑制策略完全失效。后来我加了一个「自适应频率检测」模块,实时分析亮度波动的主频,动态切换抑制策略。

3.4 知识体系总览

下面这张图总结了本章的核心逻辑:

AE场景适配策略知识体系 AE场景适配策略知识体系 AE场景适配策略 背光场景 顺光场景 夜景场景 高动态场景 权重矩阵与区域测光 Flicker抑制 人脸优先 高亮保护 曝光时间锁定 增益补偿 核心原则 场景适配不是「一刀切」,而是根据场景特征动态调整测光策略 权重矩阵 + Flicker抑制是AE稳定性的两大基石

3.5 本章小结

AE场景适配,说白了就是「看人下菜碟」。背光场景保人脸,顺光场景求稳定,夜景场景压噪点,高动态场景上HDR。权重矩阵让测光更智能,Flicker抑制让画面不闪。

我个人觉得,AE调试最考验的不是算法能力,而是对场景的理解。你想想看,同一个算法在不同场景下表现天差地别。所以我的建议是:多收集真实场景数据,多分析失败案例,慢慢积累自己的「场景库」。

一句话总结: 好的AE策略,不是让画面「最亮」,而是让画面「最合适」。