自动曝光(AE)核心原理:曝光三角与亮度统计
自动曝光,说白了就是让摄像头自己找到那个「不亮不暗刚刚好」的曝光值。我刚开始做ISP的时候,总觉得AE不就是调调亮度嘛,后来才发现,这里面的门道比想象中深得多。
咱们先搞清楚一个基础问题:曝光到底由什么决定?
曝光三角:光圈、快门、ISO
这三个参数就像三根绳子,共同拉着最终的图像亮度。你想想看,任何一根绳子松了紧了,画面都会变样。
| 参数 | 物理含义 | 对图像的影响 | AE中能否调节 |
|---|---|---|---|
| 光圈(Aperture) | 镜头通光孔径大小 | F值越小进光越多,景深越浅 | 手机固定光圈,相机可调 |
| 快门(Shutter) | 传感器感光时间 | 时间越长越亮,但运动物体容易模糊 | 通常作为AE主控变量 |
| ISO(增益) | 模拟/数字信号放大倍数 | 增益越高越亮,但噪声也越明显 | AE中常用来补光 |
关键认知:AE算法本质上就是在做「曝光三角的平衡」。你不可能既要暗光下画面亮,又要没噪声,还要不模糊——这三者永远在打架。
我在项目中遇到过一种典型场景:室内暗光下,AE算法拼命拉高ISO,结果画面亮是亮了,但满屏噪点。后来我调整了策略,优先保证快门不低于1/30s,再提ISO,最后实在不行才降帧率。效果好了不少。
亮度统计直方图:AE的眼睛
AE怎么知道当前画面是亮是暗?靠的就是亮度统计直方图。这东西说白了就是把画面里每个像素的亮度值做个统计,横轴是亮度(0~255),纵轴是像素数量。
我的习惯:做AE调试时,我第一件事就是打开直方图窗口。看一眼直方图的分布,基本就知道当前场景的问题出在哪。
直方图能告诉我们三件事:
- 整体亮度水平——直方图偏左说明画面暗,偏右说明画面亮
- 动态范围——直方图宽度越宽,场景的动态范围越大
- 过曝/欠曝区域——左右两端堆积说明有细节丢失
实际AE算法里,我们不会直接用全图的平均亮度来做决策。为什么?因为如果画面里有大面积天空或黑色背景,平均亮度会骗人。我一般会做分区统计,把画面分成多个块,给中心区域更高的权重。
// 简化的分区权重统计示例
uint32_t zone_weight[5][5] = {
{1, 2, 3, 2, 1},
{2, 4, 6, 4, 2},
{3, 6, 9, 6, 3},
{2, 4, 6, 4, 2},
{1, 2, 3, 2, 1}
};
uint32_t calc_weighted_brightness(uint8_t* frame, int width, int height) {
uint32_t total = 0, weight_sum = 0;
int block_w = width / 5, block_h = height / 5;
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
uint32_t block_avg = get_block_avg(frame, x*block_w, y*block_h, block_w, block_h);
total += block_avg * zone_weight[y][x];
weight_sum += zone_weight[y][x];
}
}
return total / weight_sum;
}
避坑指南:我曾经在某个项目中直接用全图平均亮度做AE反馈,结果遇到「一半天空一半地面」的场景时,AE来回震荡,画面忽明忽暗。后来改成中心加权统计,问题才解决。
目标亮度设定:AE的「靶心」
AE算法有了直方图这个「眼睛」,还得知道往哪个方向调。这个方向就是目标亮度(Target Luminance)。
目标亮度通常用一个数值表示,比如18%灰对应的亮度值。但实际项目中,这个值不是固定的。我一般会根据以下几个因素动态调整:
- 场景类型——夜景、逆光、普通场景,目标亮度不同
- 人脸检测——如果有人脸,优先保证人脸区域达到目标亮度
- 用户偏好——有些人喜欢亮一点,有些人喜欢暗一点
举个例子,我做过一个安防摄像头项目,白天目标亮度设在120(0~255范围),晚上自动降到80。为什么?因为晚上场景本身暗,强行拉到120会引入大量噪声,得不偿失。
AE的核心控制逻辑
搞清楚了曝光三角和直方图,AE的控制逻辑其实就三步:
- 测量——从直方图算出当前亮度
- 比较——当前亮度 vs 目标亮度,算出误差
- 调整——根据误差调整曝光三角的参数
这里面最核心的就是第三步。调整顺序怎么定?我个人的经验是:
调整优先级:先调快门 → 再调ISO → 最后调光圈(如果可调)。快门对画质影响最小,ISO次之,光圈会影响景深,所以优先级最低。
但这里有个坑:快门不能无限制调低。低于1/30s时,手持拍摄就会模糊。所以当快门到极限后,就该ISO上场了。ISO也有上限,超过某个值噪声就不可接受了。这时候才考虑降帧率或者补光。
嗯,说到这,我想起一个经典案例。有一次做手机摄像头调试,发现AE在暗光下总是优先提ISO,导致噪点严重。后来我改了策略:先提快门到1/15s(因为有OIS防抖),再提ISO,最后才考虑降帧率。效果立竿见影。
这张图把AE的闭环控制逻辑画清楚了。从传感器数据进来,到直方图统计,再到误差计算,最后调整参数,形成一个完整的反馈回路。这个回路每帧都在跑,所以AE才能实时响应场景变化。
一个小技巧:AE的收敛速度不能太快也不能太慢。太快了画面会闪烁,太慢了用户能感觉到延迟。我一般把步长控制在每帧调整不超过曝光量的1/3档,这样既平滑又快速。