4. 色温与光源:从物理到算法的第一道门槛

做 AWB 算法,说白了就是在跟「光」打交道。你想想看,相机看到的颜色,本质上就是物体反射的光。光源一变,整个场景的颜色就全变了。所以,理解光源,是搞懂白平衡的第一步。

我个人习惯把光源分成两类:一类是实验室里能精确复现的标准光源,另一类是真实世界里乱七八糟的混合光。今天咱们就从标准光源开始聊。

4.1 常见标准光源与色温

先看一张表。这张表我建议你存下来,调试时经常要用到。

光源名称 相关色温 (K) 典型应用场景 CIE 标准
D65 6504 日光、户外正午 CIE 标准照明体 D65
D50 5003 印刷、摄影灯箱 CIE 标准照明体 D50
A 光源 2856 白炽灯、钨丝灯 CIE 标准照明体 A
TL84 4000 商场、办公室荧光灯 CIE F11
CWF 4150 北美商用荧光灯 CIE F2
U30 3000 暖白荧光灯 CIE F12
H 光源 5500 摄影闪光灯 CIE 标准照明体 D55 近似
一个小技巧: 我在项目里调试时,经常把 D65 当作「锚点」。因为大部分传感器的 R/G、B/G 比值,在 D65 下最接近 1。如果某个光源下比值偏离太大,就要小心了——可能是 sensor 的光谱响应有问题。

4.2 光源的光谱分布:为什么色温一样,颜色却不同?

这里有个坑。你可能会觉得,色温一样的光源,拍出来应该一样吧?其实不是。

色温只描述了光源的「冷暖」程度,但没描述它的光谱组成。举个例子:一个 4000K 的白炽灯,和一个 4000K 的荧光灯,色温一样,但光谱分布完全不同。

白炽灯的光谱是连续的,像一条平滑的曲线。荧光灯的光谱是线状的,在某些波长上有尖峰。这就导致了一个问题:同一个物体,在这两种光源下,反射到 sensor 上的 RGB 值可能完全不同。

我曾经在调试一款手机时遇到过:在 TL84 下白平衡已经调得很准了,换到 CWF 下就偏绿。查了半天,发现是 sensor 对 545nm 附近的荧光灯尖峰特别敏感。后来在 AWB 算法里加了一个荧光灯检测分支,才把这个问题解决。

核心结论: AWB 算法不能只看色温,必须考虑光源的光谱特征。这也是为什么高通平台里会有「光源类型」这个参数——它不只是个标签,而是用来选择不同的颜色校正矩阵。

4.3 混合光源场景:算法工程师的噩梦

单一光源还好办,最头疼的是混合光源。比如:

  • 室内靠窗的位置:窗外是 D65 日光,室内是 TL84 荧光灯
  • 夜晚街景:路灯(高压钠灯,约 2200K)+ 店铺招牌(LED,约 5000K)
  • 舞台灯光:追光灯(3200K)+ 背景 LED 屏(6500K)

这种场景下,整个画面没有一个统一的色温。你让 AWB 算法怎么选?

高通平台的策略是:分区域统计,全局决策。具体来说:

  1. 把画面分成 N×N 个块(通常是 16×16 或 32×32)
  2. 每个块独立统计 R/G、B/G 比值
  3. 用聚类算法找出「主光源」和「次光源」
  4. 根据主光源的色温做全局白平衡

但这个方法有个问题:如果主光源和次光源的面积差不多,算法就会「左右为难」。我见过一个 case:画面左边是暖色台灯,右边是冷色窗光,AWB 在两者之间来回跳,拍出来的视频一帧暖一帧冷,用户体验极差。

避坑指南: 我曾经在调试混合光源场景时,发现 AWB 收敛速度太慢。后来查了高通文档,发现有个参数叫 awb_convergence_speed,默认值是 0.3。我把它调到 0.6,收敛快了很多,但代价是稳定性下降。最后折中到 0.45,才勉强平衡。这个参数没有标准答案,得根据具体项目调。

4.4 光源与 AWB 算法的映射关系

下面这张图是我自己整理的,展示了从「物理光源」到「算法决策」的完整链路。

光源与 AWB 算法映射关系图 光源 → AWB 算法映射链路 物理光源 D65 / A / TL84 / CWF 混合光源 日光+荧光 / 多色温 特殊光源 LED / 钠灯 / 汞灯 Sensor 光谱响应 R/G/B 通道对光源光谱的积分结果 AWB 统计模块 分块统计 R/G、B/G、Y 均值 → 剔除过曝/欠曝区域 光源识别与色温估计 匹配标准光源库 → 输出色温 + 光源类型 R/G/B 增益计算与校正 说明:混合光源场景下,第四层需要额外做聚类分析,识别主光源和次光源

从这张图你能看到,AWB 算法不是直接处理「色温」的,而是处理「统计值」。光源的光谱分布,经过 sensor 的 R/G/B 滤色片积分后,变成了 R/G 和 B/G 比值。算法再拿这些比值去匹配已知的光源库。

4.5 高通平台上的光源配置

在高通 Spectra 平台上,光源信息是通过 awb_calibration_data 结构体配置的。里面有一个 light_source 数组,每个元素对应一种光源。

// 高通 AWB 校准数据结构体(简化版)
typedef struct {
    uint32_t color_temperature;  // 色温,单位 K
    float r_g_ratio;             // 该光源下的 R/G 比值
    float b_g_ratio;             // 该光源下的 B/G 比值
    float r_g_std;               // R/G 标准差(用于判断光源稳定性)
    float b_g_std;               // B/G 标准差
    uint8_t light_type;          // 光源类型:0=D65, 1=A, 2=TL84, 3=CWF...
} awb_light_source_t;
调试经验: 我建议你在实验室里至少标定 6-8 种光源。除了 D65、A、TL84 这三个必选项,最好加上 CWF、U30、H 光源,以及一个 LED 光源。因为现在越来越多的场景用的是 LED 照明,它的光谱和传统光源差别很大。

4.6 一个实战案例:混合光源下的 AWB 调试

最后分享一个我实际处理过的 case。某款手机在商场里拍照,画面总是偏黄。商场用的是 TL84 荧光灯,但天花板上有几个天窗,透进来 D65 日光。

我抓了 log 一看,AWB 估计的色温在 3800K 到 4200K 之间来回跳。3800K 时画面偏蓝,4200K 时偏黄。为什么?因为算法把混合光源当成了一个「中间色温」来处理,但实际场景里根本没有 4000K 的光源。

解决方案是:在 AWB 算法里加了一个「双光源检测」逻辑。如果统计到的 R/G、B/G 比值分布出现两个明显的聚类中心,就判定为混合光源,然后选择面积较大的那个光源做主光源。

改完之后,色温稳定在了 4100K 左右,画面虽然不能说完全准确,但至少不跳了。用户反馈也好了很多。

记住: 在混合光源下,追求「准确」是不现实的。我们的目标是「视觉可接受」和「时间稳定性」。有时候,一个稳定的偏色,比来回跳动的「准色」更让用户满意。