3. AE算法架构:从统计信息到曝光控制
AE算法,说白了就是一套「看天吃饭」的决策系统。摄像头看到什么场景,算法就根据场景亮度、目标亮度、用户偏好,算出一组曝光参数——快门、增益、光圈。我做了这么多年AE,最大的感受是:架构搭不好,后面调参全是补窟窿。
这一章,我们就把AE Pipeline从头到尾拆一遍。你跟着我走一遍流程,就知道每一块在干什么、为什么这么干。
3.1 AE Pipeline整体流程
先看整体。AE Pipeline通常跑在ISP的帧同步信号里,每来一帧,就跑一轮。我习惯把它分成5个阶段:
- 统计信息采集 —— 从RAW图里捞亮度数据
- 亮度计算 —— 把统计值换算成场景亮度
- 曝光策略 —— 根据场景类型选目标亮度和收敛方向
- 增益与快门控制 —— 算出具体的曝光参数
- 参数下发 —— 写入sensor寄存器,等下一帧生效
下面这张图,就是AE Pipeline的完整数据流。我建议你把它存下来,后面每一节都会对应到图上的某个模块。
3.2 统计信息采集
统计信息是AE的「眼睛」。眼睛瞎了,后面算得再准也没用。
采集通常在ISP的RAW域做,也就是在去马赛克、白平衡之前。为什么?因为RAW数据最原始,没被任何处理「污染」过。我见过有人拿YUV域的亮度做AE,结果白平衡一变,亮度也跟着跳,收敛抖得不行。
常用的统计信息包括:
| 统计项 | 含义 | 典型用途 |
|---|---|---|
| 亮度直方图 | 256 bins,统计每个亮度级的像素数 | 判断过曝/欠曝、场景动态范围 |
| 分区平均亮度 | 将画面分成M×N块,每块算平均亮度 | 权重计算、背光检测 |
| 最大/最小亮度 | 全图最亮和最暗的像素值 | 防饱和、防黑切 |
| 亮度统计矩 | 均值、方差、偏度 | 场景分类(顺光/逆光/夜景) |
3.3 亮度计算
有了统计信息,下一步就是算场景亮度。这里有个坑:统计值通常是0-1023的RAW域值,不是物理亮度。你需要一个映射关系。
我常用的亮度计算公式:
// 加权平均亮度
float calcSceneLuminance(uint16_t *hist, int bins, float *weights) {
float total = 0.0f;
float sum = 0.0f;
for (int i = 0; i < bins; i++) {
sum += hist[i] * i * weights[i];
total += hist[i];
}
return (total > 0) ? (sum / total) : 0.0f;
}
权重怎么设?这取决于你的目标。如果希望人脸亮,就把人脸区域的权重设高。如果希望整体均匀,就用平均权重。
3.4 曝光策略
曝光策略是AE的「大脑」。它决定了两件事:
- 目标亮度 —— 当前场景应该多亮
- 收敛方向 —— 应该增亮还是减暗
策略通常分几种:
| 策略类型 | 适用场景 | 目标亮度设定 |
|---|---|---|
| 全局平均策略 | 均匀光照、风景 | 固定值(如18%灰) |
| 人脸优先策略 | 人像、自拍 | 人脸区域亮度优先 |
| 背光补偿策略 | 逆光、窗边 | 主体亮度提升,背景可过曝 |
| 夜景策略 | 低照度 | 降低目标亮度,允许更多噪声 |
策略切换要小心。我遇到过一个问题:从室内走到室外,策略从「夜景」切到「全局平均」,目标亮度突然跳了30%,画面闪了一下。后来加了策略切换的渐变过渡,才解决。
3.5 增益与快门控制
这是AE的「手脚」。策略决定了「要多少亮度」,增益和快门负责「怎么达到这个亮度」。
控制逻辑的核心公式:
// 曝光参数计算
float targetLuminance = 120.0f; // 目标亮度
float currentLuminance = 80.0f; // 当前亮度
float exposureRatio = targetLuminance / currentLuminance; // 1.5
// 先调快门(优先保证帧率)
float newShutter = currentShutter * exposureRatio;
if (newShutter > maxShutter) {
newShutter = maxShutter;
// 剩余部分用增益补
float remainingRatio = exposureRatio / (newShutter / currentShutter);
float newGain = currentGain * remainingRatio;
}
为什么先调快门?因为快门影响运动模糊和帧率,增益影响噪声。我的优先级是:
- 先调快门 —— 在帧率允许范围内优先用快门
- 再调增益 —— 快门到上限后,用增益补
- 最后调光圈 —— 如果有光圈,最后动它
3.6 参数下发与帧同步
参数算好了,怎么给sensor?这里有个时序问题。
Sensor通常通过I2C/SPI写寄存器。写寄存器不是立即生效的,要等下一个VSYNC信号。所以:
- 第N帧采集统计信息
- 第N帧的VBLANK期间计算曝光参数
- 第N+1帧开始时写入sensor
- 第N+2帧才用新参数曝光
也就是说,从采集到生效,至少延迟2帧。如果帧率是30fps,就是66ms的延迟。这个延迟在快速变化场景下会出问题。
3.7 小结
AE Pipeline说复杂也复杂,说简单也简单。核心就是:
- 统计信息采集 —— 把RAW图变成数字
- 亮度计算 —— 把数字变成场景亮度
- 曝光策略 —— 决定要多少亮度
- 增益与快门控制 —— 决定怎么达到这个亮度
- 参数下发 —— 让sensor执行