4. AE工程实现

AE(自动曝光)这东西,说简单也简单,说复杂也复杂。简单版本就是调一下曝光时间、增益、光圈,让画面亮度合适。但真正落地到芯片上,你会发现一堆坑等着你踩。

我个人习惯把AE分成四个核心模块来看:状态机、收敛曲线、防闪烁、以及与AWB的交互。今天咱们一个一个聊。

4.1 AE算法状态机设计

AE状态机,说白了就是告诉芯片“你现在该干嘛”。我见过不少团队,上来就写一个巨大的if-else,结果调试的时候改一处崩三处。嗯,这里还是老老实实用状态机。

我常用的AE状态机分四个阶段:

状态 触发条件 行为
AE_IDLE 上电/复位/场景切换 等待触发,不调整参数
AE_RUNNING 帧同步信号到来 计算当前亮度,调整曝光参数
AE_CONVERGED 亮度误差小于阈值 停止大幅调整,进入微调模式
AE_LOCKED 用户锁定/场景稳定 冻结参数,只做统计不调整

你想想看,为什么要有AE_LOCKED?我在项目中遇到过,用户拍一张照片,结果AE还在那里来回跳,画面忽明忽暗,用户体验极差。所以拍照前必须锁住AE。

关键点:状态切换的时机要精确到帧边界。我建议在VSYNC(帧同步)中断里做状态判断,不要在ISP pipeline中间乱切,否则会出现半帧参数不一致的问题。

4.2 AE收敛曲线平滑

收敛曲线平滑,这活儿看着不起眼,但做不好画面就会“呼吸”。什么叫呼吸?就是画面一亮一暗,像有人在喘气。

我曾经在一个低端平台上调试,AE收敛步长设得太大,结果画面从暗到亮直接“闪”过去,用户投诉说“这摄像头是不是坏了”。后来我加了一个指数平滑滤波器,问题就解决了。

平滑的核心公式其实很简单:

// 指数平滑,alpha 取值 0.1 ~ 0.3
target_luma = get_target_luma(scene_mode);
current_luma = get_current_luma();
error = target_luma - current_luma;

// 平滑后的调整量
smooth_delta = error * alpha;

// 更新曝光参数
exposure_time += smooth_delta * gain_factor;

这里alpha怎么选?我个人的经验是:

  • 场景切换时:alpha取0.3~0.5,快速响应
  • 正常跟踪时:alpha取0.1~0.2,平滑过渡
  • 接近收敛时:alpha取0.05,防止过冲

小技巧:我习惯把alpha做成动态的,根据当前误差大小自动调整。误差大时alpha大,误差小时alpha小。这样既保证了响应速度,又避免了过冲。

4.3 AE防闪烁(Flicker)处理

防闪烁,这是AE落地里最头疼的问题之一。说白了,就是灯光在闪,你的摄像头也在闪,两个频率对不上,画面就出现明暗条纹。

为什么会这样?因为市电是50Hz或60Hz的交流电,灯光亮度会以100Hz或120Hz的频率波动。如果你的曝光时间不是这个周期的整数倍,就会拍到亮暗条纹。

我常用的防闪烁策略分两步:

  1. 检测闪烁频率:通过统计相邻帧的亮度差异,判断是50Hz还是60Hz环境
  2. 锁定曝光时间:将曝光时间限制为闪烁周期的整数倍

举个例子,50Hz环境下,闪烁周期是10ms(100Hz的两倍)。那么曝光时间只能取10ms、20ms、30ms……不能取15ms或25ms。

注意:锁定曝光时间后,AE的调节能力会受限。比如你想从10ms调到15ms,但15ms被禁用了,只能跳到20ms。这时候画面亮度会跳变。我建议在防闪烁模式下,用增益来微调亮度,不要只靠曝光时间。

我曾经在一个项目中,防闪烁模式打开后,画面亮度跳变严重。后来我加了一个“增益补偿”逻辑:当曝光时间跳变时,同步调整增益,让亮度变化平滑过渡。效果好了很多。

4.4 AE与AWB交互

AE和AWB(自动白平衡)是ISP里最“暧昧”的两个模块。为什么这么说?因为它们互相影响。

你想想看,AE调整曝光时间,会影响图像的色彩亮度;AWB调整白平衡增益,会影响图像的亮度统计。如果两个模块各调各的,很容易出现“震荡”——AE调亮了,AWB觉得色温变了,又去调增益,结果AE又觉得亮度变了……

我建议的交互策略是:

场景 AE行为 AWB行为
场景切换 快速收敛,允许大调整 冻结AWB,等待AE稳定
正常跟踪 平滑调整,步长较小 正常调整,但限制增益变化率
低照度 优先保证亮度,允许高增益 降低AWB灵敏度,防止偏色
高色温变化 保持曝光稳定 快速响应,但限制增益上限

我个人习惯的做法是:在AE收敛之前,AWB先“等一等”。等AE稳定了,AWB再开始调整。这样能避免两个模块互相打架。

核心原则:AE和AWB的调整周期要错开。比如AE每帧调整,AWB每两帧调整一次。或者AE调整后,AWB延迟一帧再响应。这个“时间差”能解决大部分震荡问题。

4.5 AE整体流程图

下面这张图是我自己总结的AE整体流程,包含了状态机、收敛、防闪烁和AWB交互。你可以把它当作一个参考框架。

AE算法整体流程图 AE算法整体流程图 帧同步信号 AE状态机判断 IDLE/LOCKED RUNNING 亮度统计计算 防闪烁检测 收敛曲线平滑 AWB交互协调 曝光参数输出 说明:状态机判断后,只有RUNNING状态才进入后续流程;IDLE和LOCKED状态直接跳过

这张图里,我把AE的核心流程串起来了。从帧同步开始,经过状态机判断,然后做亮度统计、防闪烁检测、收敛平滑,最后与AWB协调后输出参数。每一步都有它的作用,缺一不可。

落地建议:如果你刚开始做AE,建议先把状态机和收敛平滑做好。这两个是基础,基础打牢了,防闪烁和AWB交互才能稳定。我见过太多团队一上来就搞防闪烁,结果基础没做好,越调越乱。

好了,AE工程实现的这几个核心模块,今天就聊到这儿。每个模块都有很多细节,但掌握了这些核心思路,你至少不会走偏。下次调试AE的时候,记得先看看状态机对不对,再检查收敛曲线平不平,最后再处理防闪烁和AWB交互。按这个顺序来,能省不少时间。