1、3A算法概述

各位好,我是老周。今天开始咱们聊ISP里最核心的3A算法。说实话,我入行那会儿,3A还是各家秘而不宣的黑盒子。现在虽然开源方案多了,但真正吃透它们协同逻辑的人,依然不多。

3A是啥?说白了就是三个自动调节的闭环:AE(自动曝光)、AF(自动对焦)、AWB(自动白平衡)。它们各自管一摊,但又互相牵扯。你想想看,曝光变了,颜色跟着变;对焦动了,亮度也可能跳。这就是为什么我们要把它们放在一起讲。

核心观点:3A不是三个独立模块,而是一个三角协同系统。任何一个算法单独调优,都可能打破另两个的平衡。

1.1 什么是AE、AF、AWB

先分别认识一下这三位老朋友。

算法 全称 管什么 输出什么
AE 自动曝光 画面亮度、动态范围 曝光时间、增益、光圈
AF 自动对焦 画面清晰度、景深 镜头位置、对焦搜索方向
AWB 自动白平衡 色温、色彩还原 R/G、B/G增益

AE 的目标很简单:让画面不暗不亮。但它要权衡的东西很多——暗光下是提增益还是拉长曝光?高动态场景保高光还是保暗部?我在项目中遇到过,有些手机在夜景模式下一味拉长曝光,结果手抖全糊了。嗯,这就是AE策略没跟防抖联动的问题。

AF 呢,就是让主体清晰。它通过评价图像的对比度(或者用相位检测点)来判断是否合焦。我刚开始做AF时,总觉得爬山算法很笨,后来发现它其实最鲁棒。你想想看,在低光照下,相位检测可能不准,但对比度检测反而更可靠。

AWB 负责把白色还原成白色。不管是在暖黄的钨丝灯下,还是冷白的日光灯下,白墙看起来都应该是白的。AWB通过统计色温信息,调整R和B通道的增益。我记得有一次,客户反馈说拍出来的肤色偏绿,查了半天,原来是AWB在混合光源下被搞晕了。

1.2 3A在ISP Pipeline中的位置

ISP的pipeline很长,3A算法并不在像素处理的主路径上,而是作为旁路控制环存在。我画了张图,你看一眼就明白了。

3A在ISP Pipeline中的位置与协同关系 3A在ISP Pipeline中的位置与协同关系 Sensor RAW BLC / LSC Demosaic AWB Gain Gamma / CCM AE 自动曝光 AF 自动对焦 AWB 自动白平衡 曝光/增益 镜头位置 R/G增益 亮度影响 色温影响 对焦影响亮度统计 💡 关键理解 3A算法不直接处理像素数据,而是从pipeline中提取统计信息(亮度直方图、对比度、色温), 计算出控制参数后,反馈给sensor或ISP模块。它们是“旁路控制环”,不是“主处理路径”。

从图上你能看到:Sensor输出RAW后,经过BLC、LSC、Demosaic等预处理,然后进入AWB Gain模块。而AE、AF、AWB这三个算法,分别从pipeline的不同位置取数据,算出结果后再反馈回去。

举个例子:AE会从统计模块拿到亮度直方图,然后决定下一帧的曝光时间和增益。AF会从图像中提取高频能量(对比度),然后驱动镜头马达。AWB会统计R/G/B通道的比值,然后调整白平衡增益。

我的经验:很多新手以为3A是pipeline的一部分,其实它们是跑在独立的控制线程上的。在嵌入式平台上,3A通常跑在单独的CPU核或DSP上,跟主pipeline异步交互。这样做的好处是——即使3A算得慢一点,也不会阻塞帧率。

1.3 3A算法的协同工作逻辑

好了,单独讲完三个算法,咱们聊聊它们怎么配合。这才是今天的重点。

3A的协同,说白了就是一个三角制约关系:

  • AE 影响 AF:曝光时间变了,图像亮度变了,对比度曲线也跟着变。AF的爬山算法依赖对比度,亮度太低时对比度也低,AF容易误判。
  • AE 影响 AWB:曝光增益大了,噪声放大,色温统计的稳定性下降。我在项目中遇到过,暗光下AWB疯狂抖动,就是因为AE增益太高,把色温统计信噪比拉垮了。
  • AF 影响 AE:对焦位置变了,画面模糊程度变了,整体亮度统计也会变。尤其是拍高反差物体时,合焦和离焦的亮度能差好几个档。
  • AWB 影响 AE:这个比较隐蔽。AWB调整R/G增益后,亮度统计的权重会变化。有些ISP的AE统计会考虑颜色权重,AWB一变,AE也跟着跳。

⚠️ 避坑指南:我曾经在一个项目中,AE和AWB各自独立收敛,结果出现了“呼吸效应”——画面一亮一暗循环跳动。查了三天才发现,是AE的收敛速度跟AWB的更新周期产生了共振。解决方案很简单:给两个算法加上不同的时间常数,或者让一个算法收敛后再启动另一个。

那实际工程中怎么处理这种协同?我总结了几种常见策略:

策略 做法 适用场景 缺点
串行收敛 先AE,再AWB,最后AF 场景切换、上电初始化 收敛慢,约3~5帧
并行+优先级 AE优先,AWB次之,AF最后 预览模式、视频录制 需要精细的锁机制
联合代价函数 把亮度、色温、清晰度统一建模 高端旗舰、计算摄影 计算量大,调参复杂

我个人比较推荐第二种——并行+优先级。原因很简单:串行太慢,用户能感知到延迟;联合代价函数又太复杂,调试周期长。并行+优先级是个折中方案,工程上最实用。

具体怎么做呢?我举个例子:

// 伪代码:3A协同调度框架
void ThreeA_RunLoop(Stats *stats, SensorParams *sensor) {
    // 1. AE 优先计算,因为它影响最大
    AE_Result ae = AE_Compute(stats->histogram, sensor->lux);
    Sensor_SetExposure(ae.exposure_time, ae.analog_gain);
    
    // 2. 如果AE变化较大,暂时冻结AWB和AF
    if (ae.delta > AE_THRESHOLD) {
        AWB_Freeze();
        AF_Freeze();
        return;
    }
    
    // 3. AE稳定后,更新AWB
    AWB_Result awb = AWB_Compute(stats->rgb_ratio, ae.exposure_time);
    ISP_SetWhiteBalanceGain(awb.r_gain, awb.b_gain);
    
    // 4. 最后更新AF(依赖稳定的亮度和颜色)
    AF_Result af = AF_Compute(stats->focus_metric, sensor->lens_pos);
    Lens_Move(af.lens_target);
}

这段代码的核心思想是:AE优先,AWB和AF跟随。AE变化大时,先稳住它,再让AWB和AF基于稳定的亮度去计算。这样能避免三个算法互相拉扯。

总结一下:3A协同没有银弹。不同场景、不同硬件平台,策略都不一样。但有一条原则是通用的——谁对画面影响大,谁先收敛。AE影响亮度和动态范围,永远是老大;AWB影响颜色,排第二;AF影响清晰度,排第三。这个优先级顺序,我做了十年ISP,还没见过反过来的。

好了,这一章就聊到这儿。3A的概念、位置、协同逻辑,你应该有个整体认识了。后面我们会深入每个算法的细节,包括统计方法、控制策略、以及它们在实际芯片上的实现技巧。