4、AE实战技巧:不同场景下的AE策略
AE(自动曝光)这东西,说简单也简单,不就是调曝光时间、增益、光圈嘛。但真到了项目里,你会发现——逆光人脸黑成一片、夜景闪烁得像迪厅、高动态场景亮部死白暗部死黑……嗯,这些坑我基本都踩过。今天就把我这些年积累的实战策略掰开揉碎讲给你。
4.1 逆光场景:人脸不能黑
逆光,是AE最头疼的场景之一。背景亮、主体暗,如果按全局平均测光,人脸直接变剪影。我早期做手机摄像头项目时,用户反馈最多的就是“逆光拍照人脸看不清”。
我的策略:不要死磕全局统计,要引入人脸ROI权重。
| 测光模式 | 适用场景 | 逆光表现 |
|---|---|---|
| 全局平均测光 | 均匀光照 | 人脸过暗 |
| 中央重点测光 | 主体居中 | 略有改善 |
| 人脸ROI加权 | 逆光/人像 | 人脸亮度正常 |
| 局部区域测光 | 点光源/特写 | 需手动选区 |
还有一个细节——逆光场景下,曝光补偿要联动。我个人习惯在逆光检测触发时,自动加0.3~0.7EV的补偿。但注意,补偿量不能太大,否则背景高光区域会溢出。
4.2 夜景场景:低光不闪烁
夜景AE的难点在于:曝光时间长了会手抖,增益高了噪声爆炸,帧率低了画面闪烁。我记得有一次做安防摄像头项目,晚上画面一卡一卡的,客户差点退货。
核心原则:在信噪比和流畅度之间找平衡。
- 曝光时间上限:手持设备建议不超过1/30s,三脚架模式可以放宽到1/2s。我一般设两套阈值,根据陀螺仪数据动态切换。
- 增益控制:模拟增益优先于数字增益。模拟增益每增加6dB,信噪比下降约3dB。数字增益能不用就不用,它只是放大噪声。
- 帧率保持:夜景下帧率不能低于15fps,否则人眼能感知到闪烁。如果曝光时间已经到上限,亮度还不够,那就只能提增益了。
// 夜景AE策略伪代码
if (lux < 50) { // 低照度场景
max_exposure = is_handheld ? 33ms : 500ms; // 手持 vs 三脚架
target_brightness = 80; // 目标亮度值(0-255)
analog_gain = min(analog_gain_max, target_brightness / current_brightness);
if (analog_gain > analog_gain_max) {
digital_gain = target_brightness / (current_brightness * analog_gain_max);
digital_gain = clamp(digital_gain, 1.0, 4.0);
}
// 帧率保护:如果曝光时间超过33ms,降低帧率但不低于15fps
frame_interval = max(exposure_time + 5ms, 66ms); // 约15fps
}
4.3 高动态场景:亮部不爆,暗部不黑
高动态场景,说白了就是同一帧画面里既有大太阳又有阴影。普通传感器的动态范围也就60-70dB,而真实场景可能超过120dB。怎么办?
我的方案:多帧融合(HDR) + 自适应曝光分配。
| HDR模式 | 帧数 | 曝光组合 | 适用场景 |
|---|---|---|---|
| 2帧HDR | 2 | 长曝光 + 短曝光 | 一般逆光 |
| 3帧HDR | 3 | 长 + 中 + 短 | 强逆光/大光比 |
| 交错HDR | 连续 | 逐行交替曝光 | 运动场景 |
高动态AE的关键在于曝光分配。不是随便拍三帧然后融合就完事了。我习惯的做法是:
- 先拍一帧正常曝光(参考上一帧的AE结果)
- 统计这一帧的直方图,找到过曝和欠曝的像素比例
- 如果过曝像素超过10%,增加一帧短曝光(曝光时间减半)
- 如果欠曝像素超过15%,增加一帧长曝光(曝光时间加倍)
- 三帧的曝光时间比例建议为 1:4:16 或 1:8:64,具体看传感器动态范围
4.4 AE闪烁抑制与防抖
闪烁,是AE的顽疾。50Hz/60Hz的灯光下,曝光时间如果没对齐,画面就会一亮一暗地闪。防抖则是另一个维度——曝光时间长了,手一抖画面就糊。
闪烁抑制:
- 检测:连续采集10帧亮度值,做FFT分析。如果在50Hz或60Hz处有峰值,说明有频闪。
- 抑制:曝光时间必须锁定为光源周期的整数倍。50Hz对应20ms周期,60Hz对应16.67ms周期。曝光时间设为20ms、40ms、60ms……或者16.67ms、33.33ms、50ms……
- 自适应:如果同时存在50Hz和60Hz光源(比如混合照明),我建议用50Hz的周期,因为50Hz的闪烁人眼更敏感。
// 闪烁抑制曝光时间锁定
int flicker_freq = detect_flicker(); // 返回50或60
int base_period = (flicker_freq == 50) ? 20 : 16; // 单位ms
int target_exposure = calculate_target_exposure(); // 正常AE算出的曝光时间
// 锁定到最近的整数倍
int locked_exposure = round(target_exposure / base_period) * base_period;
locked_exposure = clamp(locked_exposure, min_exposure, max_exposure);
防抖策略:
防抖不只是OIS(光学防抖)的事,AE也要配合。我总结了几条经验:
- 陀螺仪数据接入AE:当检测到角速度超过0.5°/s时,自动缩短曝光时间到1/60s以内
- 曝光时间与ISO联动:缩短曝光时间后,用提高ISO来补偿亮度,但ISO上限设为800(超过800噪声不可接受)
- 多帧降噪替代长曝光:如果场景太暗,与其用1/15s的长曝光(大概率糊),不如用4帧1/60s的短曝光+时域降噪
4.5 AE与AWB的交互耦合问题
AE和AWB(自动白平衡)不是独立的。你调整曝光,色温统计会变;你调整白平衡,亮度统计也会变。这个耦合问题,处理不好就是灾难。
耦合的本质:
AWB依赖RGB通道的统计值来做色温估计。当你改变曝光时间或增益时,RGB三个通道的增益是同步变化的,但不同通道的噪声特性不同,导致色温估计偏移。反过来,AWB调整了R/B增益后,整体亮度也会变化,AE又要重新收敛。
| 耦合场景 | AE变化 | AWB变化 | 连锁反应 |
|---|---|---|---|
| 场景变暗 | 增加增益 | 色温偏移(偏蓝) | AWB调回色温,亮度再变 |
| 场景变暖 | 亮度不变 | 降低R增益 | 整体亮度下降,AE再调 |
| HDR切换 | 曝光组合变化 | 多帧色温不一致 | 融合后色温异常 |
我的解耦方案:
- 时序错开:AE和AWB不要在同一帧同时调整。我习惯让AE每帧调整,AWB每3帧调整一次。这样AWB调整时,AE已经稳定了。
- 统计域分离:AE用亮度统计(Y通道),AWB用色度统计(R/G、B/G比值)。两者用不同的统计窗口,避免互相干扰。
- 增益补偿:当AWB调整了R/B增益后,AE要检测亮度变化,并在一帧内补偿回来。补偿量 = (原R增益 × 原R像素 + 原B增益 × 原B像素 + 原G增益 × 原G像素) / (新R增益 × 原R像素 + 新B增益 × 原B像素 + 原G增益 × 原G像素)。
- HDR场景的特殊处理:多帧HDR时,每帧的AWB增益要统一,不能每帧独立算。我一般用上一帧正常曝光的AWB结果,应用到所有HDR帧上。
嗯,AE的实战技巧就这些。每个场景都有它的脾气,但核心思路是一致的——理解场景、对症下药、平滑过渡。你把这些策略吃透了,再遇到奇葩场景也能快速找到解法。