4、AE工作模式:自动模式、手动模式、快门优先、光圈优先在RK上的实现
AE的四种工作模式,说白了就是曝光三角(快门、增益、光圈)的三种控制权分配方式。再加上一个全自动,一共四种。
我在RK平台上调过不少项目,发现很多工程师对这几种模式的理解停留在「能用就行」的层面。但实际调试中,模式选错了,后面再怎么调也调不出好效果。今天咱们就把这四种模式在RK上的实现细节掰开揉碎讲清楚。
4.1 四种模式的核心区别
先看一张对比表,快速建立整体认知:
| 模式 | 用户控制 | 算法控制 | 典型场景 |
|---|---|---|---|
| 自动模式 | 无(仅曝光补偿) | 快门、增益、光圈全控 | 日常拍照、点按即用 |
| 手动模式 | 快门、增益、光圈全控 | 无(算法仅做参考) | 专业摄影、固定亮度场景 |
| 快门优先 | 快门速度固定 | 增益、光圈自动调节 | 运动抓拍、防抖需求 |
| 光圈优先 | 光圈值固定 | 快门、增益自动调节 | 景深控制、固定进光量 |
关键认知:RK平台的AE引擎本质上是一个「曝光参数仲裁器」。无论哪种模式,最终都要映射到ISP寄存器里的三组值:曝光时间(sensor_exp)、模拟增益(sensor_gain)、数字增益(isp_dgain)。模式只是决定了这三组值中哪些由用户锁定,哪些由算法动态计算。
4.2 自动模式(AE_AUTO)—— 全权委托
这是最常用的模式。用户只管按快门,算法包办一切。
在RK的AE算法里,自动模式走的是标准曝光流程:
- 统计采集:从ISP硬件获取当前帧的亮度直方图和分区统计值。
- 目标亮度计算:根据预设的目标亮度(通常是18%灰)和当前亮度偏差,算出需要调整的曝光量。
- 参数分配:按照优先级策略,把曝光量分配到快门、增益、光圈上。
- 参数下发:通过V4L2或RK私有API写入sensor和ISP寄存器。
这里有个坑,我踩过好几次。RK的自动模式默认的参数分配策略是「先调快门,再调增益,最后调光圈」。为什么?因为快门调整对画质影响最小(只影响运动模糊),增益会引入噪声,光圈会改变景深。但如果你用的sensor在低快门下有flicker问题(比如50Hz工频下快门不能低于10ms),这个默认策略就会出问题。
我的建议:在RK平台上,自动模式的参数分配策略一定要根据sensor特性做定制。我习惯在AE初始化时,通过rk_ae_set_exp_priority()接口设置优先级权重数组。比如对于有flicker问题的sensor,我会把快门下界锁在10ms,优先调增益。
4.3 手动模式(AE_MANUAL)—— 用户说了算
手动模式在RK上的实现,说白了就是「算法闭嘴,用户指挥」。
代码层面,手动模式的处理逻辑非常简单:
// RK AE手动模式核心逻辑(伪代码)
void ae_manual_process(ae_ctx *ctx) {
// 1. 直接使用用户设定的参数
ctx->sensor_exp = ctx->user_exp;
ctx->sensor_gain = ctx->user_gain;
ctx->isp_dgain = ctx->user_dgain;
// 2. 跳过所有自动计算
// 不调用 ae_calc_target()
// 不调用 ae_assign_params()
// 3. 只做参数合法性检查
if (ctx->sensor_exp > ctx->max_exp) {
ctx->sensor_exp = ctx->max_exp;
// 打印警告
}
// 4. 直接下发
ae_apply_params(ctx);
}
但实际项目中,手动模式有个容易被忽略的问题:参数边界保护。用户可能设置一个sensor根本不支持的曝光时间,或者增益超出硬件范围。RK的驱动层会做一次clamp,但如果你不做上层校验,用户看到的画面可能和预期完全不同。
我曾经遇到过一个案例:客户在手动模式下把曝光时间设为1秒,但sensor最大只支持500ms。驱动层直接截断到500ms,用户发现画面比预期暗,以为是AE算法有问题,查了两天。最后发现是上层没做参数范围提示。所以,手动模式一定要在UI上显示当前sensor的硬件极限值。
4.4 快门优先(AE_SHUTTER_PRIORITY)—— 锁定时间,其他随意
快门优先在RK上的实现,核心逻辑是:快门固定,增益和光圈作为自由变量。
算法流程是这样的:
- 用户设定快门值(比如1/120秒)。
- AE算法计算当前亮度与目标亮度的偏差。
- 如果画面偏暗,先调模拟增益,再调数字增益,最后调光圈(如果有)。
- 如果画面偏亮,先降模拟增益,再降数字增益,最后缩光圈。
在RK的AE驱动中,快门优先模式通过一个标志位来控制:
// RK AE模式配置结构体
struct rk_ae_mode_config {
enum rk_ae_mode mode; // AUTO, MANUAL, SHUTTER_PRI, APERTURE_PRI
uint32_t fixed_shutter; // 快门优先时,固定快门值(单位:us)
uint32_t fixed_aperture; // 光圈优先时,固定光圈值
uint32_t min_gain; // 增益下限
uint32_t max_gain; // 增益上限
};
这里有个细节:增益上限的设定。快门优先模式下,如果环境光很暗,算法会拼命拉增益。如果不设上限,画面噪点会爆炸。我一般建议在快门优先模式下,把模拟增益上限设为sensor最大值的80%,数字增益上限设为2x(6dB)。
实战经验:在RK3588平台上调试运动相机项目时,客户要求快门优先模式必须保证1/240秒以上。但室内光线不足时,增益拉到极限画面还是暗。最后我通过动态调整目标亮度解决了这个问题——当增益达到上限时,自动降低目标亮度值,保证画面可用但不保证准确。
4.5 光圈优先(AE_APERTURE_PRIORITY)—— 固定进光口径,其他自适应
光圈优先在RK平台上的实现,比快门优先要复杂一些。原因很简单:很多RK项目的sensor不带可变光圈。
对于固定光圈模组(比如手机摄像头),光圈优先模式其实退化为「快门+增益自动模式」。但对于带可变光圈的模组(比如某些安防球机),RK的AE算法需要额外处理光圈控制。
实现逻辑:
- 用户设定光圈值(F-number)。
- AE算法根据当前亮度,先调快门,再调增益。
- 如果快门已经降到最低(比如1/10000秒),画面仍然过曝,则缩小光圈。
- 如果增益已经拉到最高,画面仍然欠曝,则开大光圈。
在RK的代码中,光圈控制通常通过I2C或PWM驱动iris电机:
// 光圈控制接口示例
int rk_ae_set_aperture(ae_ctx *ctx, float f_number) {
// 将F-number映射到电机步进值
uint16_t iris_step = (uint16_t)(f_number * 100);
// 通过I2C写入iris驱动芯片
int ret = i2c_write(ctx->iris_i2c_addr, 0x01, iris_step);
if (ret) {
printf("set aperture failed: %d\n", ret);
return -1;
}
// 更新内部状态
ctx->current_aperture = f_number;
return 0;
}
我个人的习惯:光圈优先模式下,我会把快门范围设得比自动模式更宽。因为光圈固定后,曝光调节的灵活性降低了,必须给快门和增益留出足够的调整空间。比如自动模式下快门范围是1/30~1/1000,光圈优先模式下我会扩展到1/15~1/2000。
4.6 四种模式的切换与优先级
实际项目中,用户经常会在四种模式之间切换。RK的AE引擎需要处理好模式切换时的参数平滑过渡。
举个例子:从自动模式切换到手动模式时,如果用户设定的手动参数和当前自动参数差异很大,画面会突然跳变。我处理这个问题的方法是:
- 在切换瞬间,把用户设定的手动参数与当前自动参数做一次线性插值,分3~5帧逐步过渡。
- 在UI上显示当前参数和用户设定参数的差异,让用户有心理预期。
下面这张图展示了四种模式在RK AE引擎中的整体关系:
4.7 模式切换的避坑指南
最后,总结几个我在项目中踩过的坑:
- 切换瞬间画面闪烁:模式切换时,新旧参数差异大导致。解决方案是加入3~5帧的渐变过渡。
- 手动模式下参数越界:用户设了sensor不支持的值。一定要在UI上显示硬件极限,并在驱动层做clamp。
- 快门优先下增益过高:环境太暗,算法拼命拉增益。建议设增益上限,并考虑动态调整目标亮度。
- 光圈优先下快门溢出:光圈固定后,快门范围不够用。记得在光圈优先模式下扩展快门范围。
我曾经在RK3399项目上犯过一个低级错误:把快门优先和光圈优先的配置结构体搞反了,导致快门优先模式下算法去调光圈(而sensor根本没有光圈),画面一直过曝。查了两天才发现是mode枚举值定义错了。所以,写代码时一定要仔细核对rk_ae_mode_config结构体里的每个字段。