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 近似 |
4.2 光源的光谱分布:为什么色温一样,颜色却不同?
这里有个坑。你可能会觉得,色温一样的光源,拍出来应该一样吧?其实不是。
色温只描述了光源的「冷暖」程度,但没描述它的光谱组成。举个例子:一个 4000K 的白炽灯,和一个 4000K 的荧光灯,色温一样,但光谱分布完全不同。
白炽灯的光谱是连续的,像一条平滑的曲线。荧光灯的光谱是线状的,在某些波长上有尖峰。这就导致了一个问题:同一个物体,在这两种光源下,反射到 sensor 上的 RGB 值可能完全不同。
我曾经在调试一款手机时遇到过:在 TL84 下白平衡已经调得很准了,换到 CWF 下就偏绿。查了半天,发现是 sensor 对 545nm 附近的荧光灯尖峰特别敏感。后来在 AWB 算法里加了一个荧光灯检测分支,才把这个问题解决。
4.3 混合光源场景:算法工程师的噩梦
单一光源还好办,最头疼的是混合光源。比如:
- 室内靠窗的位置:窗外是 D65 日光,室内是 TL84 荧光灯
- 夜晚街景:路灯(高压钠灯,约 2200K)+ 店铺招牌(LED,约 5000K)
- 舞台灯光:追光灯(3200K)+ 背景 LED 屏(6500K)
这种场景下,整个画面没有一个统一的色温。你让 AWB 算法怎么选?
高通平台的策略是:分区域统计,全局决策。具体来说:
- 把画面分成 N×N 个块(通常是 16×16 或 32×32)
- 每个块独立统计 R/G、B/G 比值
- 用聚类算法找出「主光源」和「次光源」
- 根据主光源的色温做全局白平衡
但这个方法有个问题:如果主光源和次光源的面积差不多,算法就会「左右为难」。我见过一个 case:画面左边是暖色台灯,右边是冷色窗光,AWB 在两者之间来回跳,拍出来的视频一帧暖一帧冷,用户体验极差。
awb_convergence_speed,默认值是 0.3。我把它调到 0.6,收敛快了很多,但代价是稳定性下降。最后折中到 0.45,才勉强平衡。这个参数没有标准答案,得根据具体项目调。
4.4 光源与 AWB 算法的映射关系
下面这张图是我自己整理的,展示了从「物理光源」到「算法决策」的完整链路。
从这张图你能看到,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;
4.6 一个实战案例:混合光源下的 AWB 调试
最后分享一个我实际处理过的 case。某款手机在商场里拍照,画面总是偏黄。商场用的是 TL84 荧光灯,但天花板上有几个天窗,透进来 D65 日光。
我抓了 log 一看,AWB 估计的色温在 3800K 到 4200K 之间来回跳。3800K 时画面偏蓝,4200K 时偏黄。为什么?因为算法把混合光源当成了一个「中间色温」来处理,但实际场景里根本没有 4000K 的光源。
解决方案是:在 AWB 算法里加了一个「双光源检测」逻辑。如果统计到的 R/G、B/G 比值分布出现两个明显的聚类中心,就判定为混合光源,然后选择面积较大的那个光源做主光源。
改完之后,色温稳定在了 4100K 左右,画面虽然不能说完全准确,但至少不跳了。用户反馈也好了很多。