4. AE工作模式

AE的四种工作模式,说白了就是曝光三角(快门、增益、光圈)的三种控制权分配方式。再加上一个全自动,一共四种。

我在RK平台上调过不少项目,发现很多工程师对这几种模式的理解停留在「能用就行」的层面。但实际调试中,模式选错了,后面再怎么调也调不出好效果。今天咱们就把这四种模式在RK上的实现细节掰开揉碎讲清楚。

4.1 四种模式的核心区别

先看一张对比表,快速建立整体认知:

模式 用户控制 算法控制 典型场景
自动模式 无(仅曝光补偿) 快门、增益、光圈全控 日常拍照、点按即用
手动模式 快门、增益、光圈全控 无(算法仅做参考) 专业摄影、固定亮度场景
快门优先 快门速度固定 增益、光圈自动调节 运动抓拍、防抖需求
光圈优先 光圈值固定 快门、增益自动调节 景深控制、固定进光量

关键认知:RK平台的AE引擎本质上是一个「曝光参数仲裁器」。无论哪种模式,最终都要映射到ISP寄存器里的三组值:曝光时间(sensor_exp)、模拟增益(sensor_gain)、数字增益(isp_dgain)。模式只是决定了这三组值中哪些由用户锁定,哪些由算法动态计算。

4.2 自动模式(AE_AUTO)—— 全权委托

这是最常用的模式。用户只管按快门,算法包办一切。

在RK的AE算法里,自动模式走的是标准曝光流程:

  1. 统计采集:从ISP硬件获取当前帧的亮度直方图和分区统计值。
  2. 目标亮度计算:根据预设的目标亮度(通常是18%灰)和当前亮度偏差,算出需要调整的曝光量。
  3. 参数分配:按照优先级策略,把曝光量分配到快门、增益、光圈上。
  4. 参数下发:通过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. 用户设定快门值(比如1/120秒)。
  2. AE算法计算当前亮度与目标亮度的偏差。
  3. 如果画面偏暗,先调模拟增益,再调数字增益,最后调光圈(如果有)。
  4. 如果画面偏亮,先降模拟增益,再降数字增益,最后缩光圈。

在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算法需要额外处理光圈控制。

实现逻辑:

  1. 用户设定光圈值(F-number)。
  2. AE算法根据当前亮度,先调快门,再调增益。
  3. 如果快门已经降到最低(比如1/10000秒),画面仍然过曝,则缩小光圈。
  4. 如果增益已经拉到最高,画面仍然欠曝,则开大光圈。

在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引擎中的整体关系:

RK平台AE四种工作模式架构图 AE曝光引擎 自动模式 算法全权控制 手动模式 用户全权控制 快门优先 快门固定,增益/光圈自适应 光圈优先 光圈固定,快门/增益自适应 曝光参数输出 曝光时间 (sensor_exp) 模拟增益 (sensor_gain) 数字增益 (isp_dgain) 无论哪种模式,最终都映射到三个硬件参数 模式只是决定了哪些参数由用户锁定,哪些由算法动态计算

4.7 模式切换的避坑指南

最后,总结几个我在项目中踩过的坑:

  • 切换瞬间画面闪烁:模式切换时,新旧参数差异大导致。解决方案是加入3~5帧的渐变过渡。
  • 手动模式下参数越界:用户设了sensor不支持的值。一定要在UI上显示硬件极限,并在驱动层做clamp。
  • 快门优先下增益过高:环境太暗,算法拼命拉增益。建议设增益上限,并考虑动态调整目标亮度。
  • 光圈优先下快门溢出:光圈固定后,快门范围不够用。记得在光圈优先模式下扩展快门范围。

我曾经在RK3399项目上犯过一个低级错误:把快门优先和光圈优先的配置结构体搞反了,导致快门优先模式下算法去调光圈(而sensor根本没有光圈),画面一直过曝。查了两天才发现是mode枚举值定义错了。所以,写代码时一定要仔细核对rk_ae_mode_config结构体里的每个字段。