3. AE算法实现:目标亮度设定、曝光时间与增益的分配策略、防闪烁处理与收敛控制
自动曝光(AE)是3A算法里最贴近用户体验的一环。说白了,就是让摄像头在不同光照下都能输出一张“看着舒服”的图像。目标亮度定多少?曝光时间和增益怎么分?遇到50Hz/60Hz频闪怎么躲?收敛快了会不会来回晃?这些坑我基本都踩过一遍。
3.1 目标亮度设定
目标亮度(Target Luminance)是AE的“靶心”。我个人习惯把亮度基准定在Y = 100~120(8bit,0~255范围)。但这不是死的,得看场景。
| 场景类型 | 推荐目标亮度 | 说明 |
|---|---|---|
| 室内/办公室 | 110 ~ 120 | 人脸肤色自然,背景不过曝 |
| 室外白天 | 100 ~ 110 | 保留高光细节,避免天空过曝 |
| 夜间/暗光 | 80 ~ 100 | 优先降噪,牺牲一点亮度 |
| 背光场景 | 130 ~ 150(人脸区域) | 需要配合WDR或局部AE |
你可能会问:为什么暗光反而目标亮度更低?因为增益拉上去之后噪声会爆炸,与其让画面全是噪点,不如稍微暗一点但干净。我在做一款低光IPC时试过把目标亮度设到120,结果画面亮是亮了,但全是雪花点——后来降到90,用户反馈反而更好。
3.2 曝光时间与增益的分配策略
这是AE里最核心的决策。给定一个目标亮度,曝光时间和增益怎么组合?
基本公式:亮度 ≈ 曝光时间 × 增益 × 场景照度
分配策略的核心原则:优先调曝光时间,再调增益。为什么?因为增益会放大噪声,而曝光时间只影响运动模糊。具体策略我总结成三步:
- 先调曝光时间:从最小值开始往上加,直到达到目标亮度,或者达到最大曝光时间(通常受帧率限制,比如30fps下最大33ms)。
- 再调模拟增益:曝光时间到顶了还不够亮?加模拟增益。模拟增益的噪声比数字增益小,优先用。
- 最后调数字增益:模拟增益也到上限了?只能上数字增益了。但数字增益超过2倍时,噪声会非常明显,建议配合降噪算法。
我曾经在一个项目里遇到一个问题:曝光时间调得太长,导致运动物体拖影严重。后来我加了一个运动检测模块,检测到运动时主动限制最大曝光时间,把亮度缺口用增益补上。效果立竿见影。
3.3 防闪烁处理(Flicker Detection)
防闪烁是AE里最容易被忽视但又最容易出问题的环节。50Hz和60Hz的灯光频闪,会让画面出现明暗条纹,非常影响体验。
闪烁的根本原因:曝光时间不是光源周期的整数倍。比如50Hz光源周期20ms,如果你曝光时间设成25ms,就会拍到半个周期的亮和半个周期的暗。
防闪烁策略我分两步走:
- 检测阶段:统计连续几帧的亮度变化,如果出现周期性波动,基本可以判定有频闪。我习惯用FFT做频域分析,看50Hz/60Hz分量是否突出。
- 消除阶段:将曝光时间锁定为光源周期的整数倍。50Hz下锁定为10ms、20ms、30ms... 60Hz下锁定为8.33ms、16.67ms、25ms...
| 光源频率 | 周期 | 推荐曝光时间(整数倍) |
|---|---|---|
| 50Hz | 20ms | 10ms, 20ms, 30ms, 40ms |
| 60Hz | 16.67ms | 8.33ms, 16.67ms, 25ms, 33.33ms |
3.4 AE收敛速度与稳定性
收敛速度和稳定性是一对矛盾。收敛太快容易过冲,画面会忽明忽暗;收敛太慢用户会觉得反应迟钝。
我常用的控制策略是分段PID:
- 大偏差阶段(亮度误差 > 30%):用大步长快速逼近,步长可以设到当前值的20%~30%。
- 中偏差阶段(亮度误差 10%~30%):用中等步长,5%~10%。
- 小偏差阶段(亮度误差 < 10%):用微调步长,1%~3%,同时加入死区防止抖动。
另外,我强烈建议加一个收敛完成标志。当连续3~5帧的亮度误差都在死区范围内,就认为AE已经稳定,可以降低调节频率,减少CPU开销。
- 死区(Dead Zone):±3 ~ ±5(8bit),防止微调导致来回跳
- 步长上限:单次调节不超过当前值的30%,防止过冲
- 稳定帧数:连续3帧在死区内才认为收敛完成
我记得有一次调试一个安防摄像头,AE总是在亮暗切换时来回震荡。查了半天发现是步长设得太大了,每次调节都过冲,然后反向调节又过冲。后来把步长上限从50%降到20%,问题解决。
3.5 AE算法整体流程
下面这张图是我自己总结的AE算法流程,基本覆盖了上面讲的所有环节:
3.6 工程实现要点
最后聊几个工程落地的细节:
- 帧率同步:AE调节最好在VBlank期间完成,避免在帧中间修改曝光参数导致画面撕裂。
- 平滑过渡:每次调节不要一步到位,而是分多步渐变。比如目标曝光时间从10ms变到20ms,中间插几帧15ms、18ms,用户几乎感觉不到变化。
- 异常保护:当场景发生剧烈变化(比如从室内走到室外),AE可能会瞬间过曝或过暗。我习惯加一个最大调节幅度限制,单帧调节不超过当前值的30%。
- 调试接口:一定要留log输出,把每一帧的Y_cur、Y_tgt、曝光时间、增益值都打出来。调试AE时这些数据比看图像直观得多。
AE算法说难不难,说简单也不简单。核心就是把握好目标亮度、曝光时间与增益的分配、防闪烁和收敛控制这四个维度。每个维度都有trade-off,没有银弹。多在实际场景里跑一跑,你自然就找到感觉了。