第四章 白平衡(AWB):色温与色彩恒常性、灰度世界与完美反射法、高通AWB算法特点

各位同学,今天我们来聊聊白平衡。嗯,这个话题很有意思。你想想看,为什么我们人眼看一张白纸,无论在阳光下还是灯光下,都觉得它是白的?但相机拍出来,有时候偏蓝,有时候偏黄。这就是白平衡要解决的问题。

4.1 色温与色彩恒常性

先说色温。这个概念其实挺直观的——你把一块铁加热,温度低的时候发红,温度高了发蓝。色温的单位是开尔文(K)。

我给大家一个常用的参考表:

光源类型 色温范围(K) 视觉感受
烛光 1500-2000 暖黄
白炽灯 2500-3000 暖白
日光灯 4000-5000 中性
正午阳光 5000-6500 冷白
阴天 6500-8000 偏蓝

这里有个坑,我刚开始做ISP的时候踩过。色温低不代表温度低,它只是描述光谱分布的参数。你想想看,蜡烛火焰温度其实很高,但色温反而低。别搞混了。

再说色彩恒常性。这是人眼的一个神奇能力——不管光源怎么变,我们都能认出物体的本来颜色。但相机没这个本事。它老老实实地记录进入传感器的光线,光源变了,颜色就变了。

白平衡算法,说白了就是模拟人眼的色彩恒常性。它要回答一个问题:在当前光源下,什么东西应该是白色的?

4.2 灰度世界法

灰度世界法是最经典的算法之一。它的假设很简单:一张色彩丰富的照片,所有颜色的平均值应该是灰色的。

为什么?因为自然界中,红绿蓝三通道的反射率平均下来差不多。如果照片整体偏蓝,说明蓝色通道的增益太高了,需要降下来。

算法实现也很直接:

// 灰度世界法伪代码
// 1. 计算R、G、B三个通道的平均值
avgR = mean(R_channel)
avgG = mean(G_channel)
avgB = mean(B_channel)

// 2. 计算灰色参考值
grayValue = (avgR + avgG + avgB) / 3

// 3. 计算各通道增益
gainR = grayValue / avgR
gainG = grayValue / avgG
gainB = grayValue / avgB

// 4. 应用增益
R_out = R_in * gainR
G_out = G_in * gainG
B_out = B_in * gainB

我在项目中遇到过一个问题:如果场景里大片都是蓝色天空,灰度世界法就会把整个画面调黄。因为算法以为蓝色太多了,拼命压低蓝色通道。结果天空变黄了,草地也变黄了,整个画面像得了黄疸。

注意:灰度世界法对场景内容非常敏感。大面积单色场景、夜景、室内暖色调场景,效果都不好。别指望一个算法打天下。

4.3 完美反射法

完美反射法,也叫白点法。它的思路不一样——它找场景中最亮的点,假设这些点应该是白色的。

为什么?因为白色物体反射所有波长的光。如果场景里有一块白色区域,它反射的光就代表了光源的颜色。找到这个白点,就能算出光源色温。

实现步骤:

// 完美反射法伪代码
// 1. 将RGB图像转为亮度图
Y = 0.299*R + 0.587*G + 0.114*B

// 2. 找到亮度最高的前1%像素
threshold = percentile(Y, 99)
mask = Y >= threshold

// 3. 在这些像素中计算R/G/B的平均值
avgR_white = mean(R[mask])
avgG_white = mean(G[mask])
avgB_white = mean(B[mask])

// 4. 计算增益
gainR = avgG_white / avgR_white
gainB = avgG_white / avgB_white
gainG = 1.0

这个算法有个致命弱点——如果场景里根本没有白色物体呢?比如拍一片森林,最亮的可能是树叶上的高光,但树叶不是白色的。算法就会乱算。

我曾经在一个项目里调试夜景模式,发现完美反射法在路灯下总是偏紫。后来发现,路灯下的白色汽车被算法当成了参考点,但车漆其实带一点蓝色调。嗯,这就是典型的参考点选错了。

4.4 高通AWB算法特点

高通的AWB算法,说实话,在业界算是第一梯队的。我拆解过几个平台的代码,说说它的特点。

第一,多区域统计。高通把画面分成几十个区域,每个区域独立统计色温信息。这样能处理混合光源场景——比如室内一半是窗外的日光,一半是室内的暖光。

第二,置信度加权。不是所有区域都平等对待。算法会判断每个区域的可信度:

  • 饱和度太高的区域,权重降低(可能是彩色物体)
  • 亮度太低的区域,权重降低(噪声太大)
  • 纹理太复杂的区域,权重降低(可能是边缘)

第三,时序平滑。这个我特别喜欢。如果AWB增益跳变太快,视频里就会出现颜色闪烁。高通的做法是:当前帧的增益 = 上一帧增益 × 0.7 + 当前帧计算增益 × 0.3。这样颜色变化就很平滑。

第四,场景分类器。高通内置了一个轻量级的场景分类模型。它能识别:

场景类型 算法策略
户外日光 偏向灰度世界法
室内暖光 偏向完美反射法
夜景 降低增益上限,防止噪声放大
混合光源 多区域独立处理
经验之谈:调试AWB时,别只看实验室的色卡。拿到真实场景去测,特别是商场、地铁、咖啡馆这些混合光源的地方。我见过太多算法在实验室跑得好好的,一到真实场景就翻车。

最后说一个高通特有的机制——色温查找表。高通把常见光源的色温响应曲线预先标定好,存成LUT。算法算出色温后,直接查表得到增益值。这样做的好处是:

  • 速度快,不用实时计算复杂的数学模型
  • 稳定性好,不会出现极端增益值
  • 可定制,厂商可以修改LUT来调出自己的色彩风格

我个人习惯,在调试AWB时,会先关掉所有后处理,只看原始增益值。这样能判断是AWB本身的问题,还是后面色彩矩阵的问题。很多工程师一上来就调色彩矩阵,结果AWB的偏差被放大了,越调越乱。

好了,这一章的内容就到这里。白平衡这个东西,说简单也简单,说复杂也复杂。核心就是一句话:找到场景中的白色参考,算出光源色温,然后补偿回去。但具体怎么找、怎么算,里面的门道就多了。

下一章我们讲自动曝光(AE),这也是ISP三大核心之一。到时候见。