2. 色彩科学基础:人眼视觉特性、三基色原理、CIE 1931色度图、RGB与XYZ色彩空间转换

做自动白平衡,说白了就是在跟人眼的视觉系统较劲。你想想看,为什么同一张白纸,在暖光灯下看着是白的,在阴天室外看着也是白的?相机可没这么聪明,它拍出来要么偏黄要么偏蓝。要解决这个问题,得先搞懂人眼是怎么感知颜色的。

2.1 人眼视觉特性:我们是怎么看到颜色的

人眼视网膜上有两类感光细胞:视杆细胞和视锥细胞。视杆细胞负责暗视觉,对亮度敏感,但分不清颜色。视锥细胞负责明视觉,有三种类型,分别对长波(红)、中波(绿)、短波(蓝)敏感。这就是我们感知颜色的生理基础。

关键点:人眼对亮度的响应是非线性的,对颜色的感知具有适应性。白平衡算法本质上就是在模拟这种适应性。

我在项目中遇到过一个问题:同一个场景,用不同品牌的相机拍出来,白平衡效果差异很大。后来发现,除了传感器差异,各家对“人眼适应性”的建模方式不同。有的直接用灰度世界假设,有的用完美反射假设,效果自然不一样。

2.2 三基色原理:颜色混合的底层逻辑

三基色原理告诉我们:人眼视锥细胞的响应是线性的,通过红、绿、蓝三种原色的不同比例混合,可以匹配出自然界中绝大部分颜色。注意,我说的是“匹配”,不是“生成”。

三基色混合遵循 Grassmann 定律:

  • 加色混合:红+绿=黄,红+蓝=品红,绿+蓝=青,红+绿+蓝=白
  • 线性可加性:混合色的三刺激值等于各成分三刺激值之和
  • 连续性:光强度连续变化时,颜色感知也连续变化

嗯,这里要注意:加色混合是显示器、相机传感器的工作方式,跟颜料混合(减色混合)完全是两码事。做图像处理时千万别搞混。

2.3 CIE 1931 色度图:颜色的“地图”

CIE 1931 色度图是颜色科学里最重要的工具之一。它把颜色映射到一个二维平面上,横坐标是 x,纵坐标是 y,代表色度。这个图有几个关键特征:

  • 马蹄形边界:代表单色光(纯光谱色)
  • 内部区域:代表混合色
  • 等温线:代表不同色温的白光
  • 普朗克轨迹:黑体在不同温度下的颜色变化曲线

做白平衡校正时,我们经常要判断图像中的“白色”是否落在普朗克轨迹附近。如果偏了,说明色温估计有问题。

个人经验:我曾经调试一个室内场景的白平衡,怎么调都偏绿。后来在色度图上一看,原来场景里有大量绿色植物,导致灰度世界假设失效。改用完美反射假设后,效果就好了。

CIE 1931 色度图与白平衡校正流程 输入图像 色温估计 色度图映射 增益计算 普朗克轨迹 黑体在不同温度下的 颜色变化曲线 等温线 相同色温点的连线 用于判断色温偏差

2.4 RGB 与 XYZ 色彩空间转换

RGB 色彩空间依赖设备,不同显示器的 RGB 标准不一样。XYZ 色彩空间是设备无关的,由 CIE 在 1931 年定义。做白平衡算法时,我们经常需要在 RGB 和 XYZ 之间来回转换。

转换公式如下:

// RGB 到 XYZ 转换矩阵(sRGB 标准)
// 假设 RGB 已经过 gamma 校正
double M[3][3] = {
    {0.4124564, 0.3575761, 0.1804375},
    {0.2126729, 0.7151522, 0.0721750},
    {0.0193339, 0.1191920, 0.9503041}
};

// 转换
X = M[0][0]*R + M[0][1]*G + M[0][2]*B;
Y = M[1][0]*R + M[1][1]*G + M[1][2]*B;
Z = M[2][0]*R + M[2][1]*G + M[2][2]*B;

反过来,从 XYZ 到 RGB 的转换矩阵就是上面矩阵的逆矩阵:

// XYZ 到 RGB 转换矩阵(sRGB 标准)
double M_inv[3][3] = {
    { 3.2404542, -1.5371385, -0.4985314},
    {-0.9692660,  1.8760108,  0.0415560},
    { 0.0556434, -0.2040259,  1.0572252}
};

// 转换
R = M_inv[0][0]*X + M_inv[0][1]*Y + M_inv[0][2]*Z;
G = M_inv[1][0]*X + M_inv[1][1]*Y + M_inv[1][2]*Z;
B = M_inv[2][0]*X + M_inv[2][1]*Y + M_inv[2][2]*Z;

避坑指南:我曾经在转换时忘记做 gamma 校正,结果颜色全乱了。记住:sRGB 到 XYZ 转换前,必须先做 gamma 解码(linearize),转换完再做 gamma 编码。否则你得到的颜色会严重偏暗或偏亮。

2.5 色度坐标与色温的关系

从 XYZ 可以计算出色度坐标 (x, y):

x = X / (X + Y + Z);
y = Y / (X + Y + Z);

色温 (CCT, Correlated Color Temperature) 可以通过查表或公式从 (x, y) 估算。常用的方法是找到普朗克轨迹上距离当前 (x, y) 最近的点,该点对应的温度就是相关色温。

色温 (K) 光源类型 色度坐标 (x, y)
2000 烛光/日出日落 (0.5267, 0.4133)
3200 钨丝灯 (0.4235, 0.3990)
5000 日光灯/正午阳光 (0.3457, 0.3585)
6500 阴天/标准 D65 (0.3127, 0.3290)
10000 蓝天阴影 (0.2800, 0.2880)

做白平衡时,我们通常先估计场景的色温,然后根据色温计算 R、G、B 三个通道的增益系数,最后用这些系数校正图像。整个过程的核心,就是上面这些色彩科学基础。

个人建议:刚开始做白平衡算法时,别急着调参。先把色度图画出来,看看你的“白色”点落在哪里。如果偏离普朗克轨迹太远,说明算法有问题,不是调几个增益能解决的。