3. AE算法目标:理解18%灰板与目标亮度
做AE控制这么多年,我越来越觉得一个道理很朴素——曝光的目标不是让画面“看起来亮”,而是让画面“还原准确”。说白了,就是让场景中18%反射率的物体,在图像里呈现出中灰亮度。这个基准,就是整个AE算法的锚点。
3.1 18%灰板到底是个啥?
你可能在摄影器材店见过那种灰色卡片,一面灰一面白。那个灰色面,反射率就是18%。为什么是18%?不是20%也不是15%?
嗯,这其实跟人眼对亮度的感知曲线有关。人眼对暗部更敏感,对亮部不那么敏感。18%这个值,恰好落在人眼感知的中间区域。相机测光系统都是以这个为基准设计的——你测哪里,系统就默认那里应该是18%灰。
核心概念:AE算法的本质,就是通过调整曝光参数,让场景中18%反射率的区域,在输出图像中映射到128(8bit)或512(10bit)附近的中灰值。
我在项目中遇到过一个问题:一个用户拍雪景,结果画面总是灰蒙蒙的。为什么?因为相机测光系统“以为”雪是18%灰,拼命压低曝光,雪就变成了灰色。这就是典型的测光欺骗。所以后来我们在AE里加了场景分类,遇到高反射场景就自动补偿。
3.2 目标亮度怎么定?
目标亮度不是拍脑袋定的。它取决于三件事:
- 传感器特性:不同sensor的线性区、饱和点不一样
- 输出位深:8bit还是10bit,目标值不同
- 场景意图:人脸、风景、文档,各有各的偏好
我一般这样设目标:
| 场景类型 | 目标亮度(8bit) | 目标亮度(10bit) | 说明 |
|---|---|---|---|
| 通用场景 | 100~120 | 400~480 | 以18%灰为基准 |
| 人脸优先 | 140~160 | 560~640 | 人脸偏亮一点更讨喜 |
| 夜景/低照 | 60~80 | 240~320 | 保留暗部细节 |
| 文档扫描 | 180~200 | 720~800 | 文字清晰优先 |
我的习惯:在调试阶段,我会先固定目标亮度为120(8bit),等AE收敛稳定了,再根据场景微调。不要一上来就搞复杂策略,容易翻车。
3.3 AE的统计信息——亮度直方图
AE算法怎么知道当前画面亮不亮?靠的就是亮度直方图。说白了,就是把画面里每个像素的亮度值做个统计,看看分布情况。
直方图的横轴是亮度(0~255),纵轴是像素数量。我每次调试AE,第一件事就是拉出直方图看。它能告诉你很多信息:
- 左偏:画面偏暗,欠曝
- 右偏:画面偏亮,过曝
- 两边撞墙:有细节丢失(暗部裁切或高光溢出)
- 中间集中:对比度低,画面发灰
在ISP里,直方图统计一般分两步:
- 分bin统计:把0~255分成256个bin,每个bin统计像素个数
- 加权计算:不同区域可以给不同权重(比如人脸区域权重更高)
我曾经踩过一个坑:直方图统计的bin数太少,导致AE在低照场景下抖动。后来把bin从64改成256,问题就解决了。你想想看,bin太少,亮度分辨率不够,AE就像瞎子摸象,当然稳不住。
3.4 从直方图到曝光调整
有了直方图,AE算法就能算出一个当前平均亮度,然后跟目标亮度比较。差值就是曝光误差。
伪代码大概是这样的:
// 简化版AE核心逻辑
uint8_t target_luma = 120; // 目标亮度
uint8_t current_luma = get_average_luma(histogram); // 从直方图算当前亮度
int error = target_luma - current_luma; // 曝光误差
if (abs(error) < threshold) {
// 曝光OK,不动
return;
}
// 根据误差调整曝光参数
if (error > 0) {
// 画面偏暗,增加曝光
increase_exposure(error);
} else {
// 画面偏亮,减少曝光
decrease_exposure(-error);
}
实际工程里,不会直接用这个error一步到位。我会加一个低通滤波,防止AE来回跳。比如:
// 平滑处理,防止抖动
static int filtered_error = 0;
filtered_error = filtered_error * 0.7 + error * 0.3;
注意:滤波系数不能太大,否则AE反应太慢;也不能太小,否则画面会闪烁。我一般从0.7开始调,根据实际效果微调。
3.5 本章知识体系
下面这张图,把AE算法从目标到统计再到调整的链路画清楚了:
从图上你能看到,整个AE是一个闭环反馈系统。18%灰板是理论基准,目标亮度是工程设定,直方图是实时反馈,误差计算是决策依据,参数调整是执行动作。每一环都缺一不可。
3.6 避坑指南
最后分享几个我踩过的坑:
- 直方图bin数别太少:64bin以下,AE在低照场景容易抖动。建议至少128bin,256bin更稳。
- 目标亮度别死板:不同场景用同一个目标值,效果一定差。我习惯在AE模块里预置3~5组目标值,根据场景切换。
- 滤波系数要调:0.7是个好起点,但遇到快速变化的场景(比如从室内走到室外),系数要动态调整。
- 别忘了权重:画面中心区域、人脸区域,权重应该更高。否则背景亮了,人脸黑了,用户肯定骂娘。
一句话总结:AE算法的核心,就是用直方图这把尺子,量出画面亮度,然后把它拉到18%灰这个锚点附近。理解了这一点,你就抓住了AE的魂。