4. 自动白平衡(AWB)算法原理:色温与色彩恒常性

自动白平衡,说白了就是让相机在不同光线下都能把白色拍成白色。你想想看,白炽灯下拍的白纸偏黄,日光灯下偏绿,阴天偏蓝——人眼会自动纠正,但传感器不会。AWB 要做的,就是模拟人眼的这种色彩恒常性。

我刚开始做 ISP 调优时,觉得 AWB 不就是算个增益嘛,后来在项目里被各种极端场景折磨过,才明白这里面门道有多深。今天咱们就把 AWB 的底牌翻出来看看。

4.1 色温与色彩恒常性

色温不是温度,是光源颜色的度量。单位是开尔文(K)。数值越低越暖(烛光 ~2000K),越高越冷(阴天 ~7000K)。

光源类型 典型色温(K) 视觉感受
烛光 1500-2000 暖黄
白炽灯 2700-3200 暖白
日光灯 4000-5000 中性偏绿
正午日光 5000-5500 标准白
阴天/阴影 6500-7500 冷蓝

色彩恒常性是人眼的本事——不管光源怎么变,我们对物体颜色的感知基本不变。但 CMOS 传感器没这功能,它老老实实地记录入射光。所以同一张白纸,在不同色温下拍出来就是不同颜色。

核心矛盾:传感器忠实记录物理光 → 人眼期望看到恒常颜色 → AWB 必须做中间人,把物理色偏纠正回感知色。

4.2 灰度世界假设

这是 AWB 最经典的假设,也是大多数商用算法的起点。它说:一幅色彩丰富的自然图像,所有像素的 R、G、B 均值应该趋于相等。

换句话说,整张图的平均色应该是灰色。如果平均色偏红,说明光源偏红,需要降 R 增益;偏蓝就降 B 增益。

数学表达很简单:

R_avg = G_avg = B_avg

增益计算:
gain_R = G_avg / R_avg
gain_B = G_avg / B_avg
gain_G = 1.0(通常固定 G 通道)

我在项目中遇到过一个问题:当场景里大面积是纯色物体时(比如一片蓝天、一面红墙),灰度世界假设就崩了。整张图平均色就是蓝的或红的,算法会误判为光源偏色,然后过度补偿,结果蓝天被拉成灰色。

灰度世界假设的致命弱点:场景必须色彩丰富。纯色场景、单色物体占主导时,算法完全失效。我见过有人拿红色消防栓测试 AWB,结果输出一片灰白——这就是假设被打破的典型。

4.3 色温估计方法

光靠灰度世界假设不够,实际工程中需要更鲁棒的色温估计。我常用的方法有三种:

4.3.1 基于色温曲线的统计法

在 R/G 和 B/G 色度空间里,不同色温的光源会形成一条曲线。算法把图像像素投影到这个空间,统计分布,找到最可能的色温点。

// 伪代码:色温曲线匹配
for each pixel (r, g, b):
    rg = r / g
    bg = b / g
    在色温曲线上找最近的点
    统计每个色温区间的像素数量
选择像素最多的色温区间作为估计值

4.3.2 基于学习的方法

提前标定好各种光源下的色温-增益映射表。实际运行时,根据图像统计特征查表或插值。这个方法在手机 ISP 里很常见,因为计算量小、稳定。

4.3.3 多区域融合法

把图像分成 N×N 块,每块独立做色温估计,然后加权融合。权重取决于块内色彩丰富度——纯色块权重低,多彩块权重高。

我的经验:多区域融合法在实际工程中最实用。它天然抗大块纯色干扰,而且实现简单。我曾在某个安防项目里用 4×4 分块 + 灰度世界假设,把 AWB 准确率从 72% 提到了 91%。

4.4 增益计算与实现

色温估计出来后,下一步就是算增益。增益计算分两步:

  1. 查表/插值得到目标白点——在标准光源下标定好的 R/G、B/G 目标值。
  2. 计算实际增益——当前统计值与目标值的比值。
// 实际增益计算示例
float target_RG = 0.45;  // D65 光源下标定值
float target_BG = 0.55;

float current_RG = R_avg / G_avg;
float current_BG = B_avg / G_avg;

float gain_R = target_RG / current_RG;
float gain_B = target_BG / current_BG;
float gain_G = 1.0f;

// 应用增益到每个像素
for each pixel:
    R_out = R_in * gain_R;
    G_out = G_in * gain_G;
    B_out = B_in * gain_B;

增益钳位很重要:我曾经遇到过增益算出来 3.5 倍的情况,结果图像噪点爆炸。一定要设上下限,比如 [0.5, 2.0],超出部分截断或平滑过渡。

4.5 AWB 算法知识结构

下面这张图把 AWB 的核心逻辑串起来了:从传感器原始数据到最终白平衡校正,每一步都有坑,每一步都有技巧。

AWB 算法核心流程 RAW 图像输入 分块统计 R/G, B/G 均值 灰度世界假设估计 色温曲线匹配 多区域加权融合 增益计算 + 钳位 白平衡校正输出 增益钳位范围 [0.5, 2.0] 超出部分平滑截断

4.6 工程中的避坑指南

做 AWB 调优这些年,我踩过的坑能写本书。挑几个最要命的说说:

  • 纯色场景误判:我曾经在调试一个户外监控项目时,画面里全是蓝天和白云,灰度世界假设直接把蓝天拉成灰色。后来加了色温曲线约束才解决。
  • 混合光源:室内窗边——一边是日光灯,一边是太阳光。单一色温估计根本搞不定。我建议用多区域独立校正,或者干脆放弃全局 AWB,改用局部自适应。
  • 低照度噪声放大:暗光下增益本来就大,AWB 再一放大,噪点直接起飞。我的做法是:低照度时降低 AWB 强度,优先保信噪比。
  • 快速切换场景:从室内走到室外,色温从 3000K 跳到 5500K。如果增益突变,画面会闪一下。必须做时间域平滑,比如用 IIR 滤波器。

一个实用技巧:在增益计算前,先对统计值做中值滤波。我试过,能有效去除极端像素的干扰,尤其适合有少量高饱和色块的场景。代价是增加 2-3ms 的计算时间,但在嵌入式平台上完全可接受。