3. 色彩科学基础:人眼视觉特性、RGB与XYZ色彩空间、色度图(CIE 1931)简介

做白平衡校正,说白了就是在跟人眼的视觉系统较劲。你想想看,为什么同一张白纸,在暖光灯下我们看着还是白的,但相机拍出来却黄得不行?这就是人眼和传感器之间的差距。这一章,我们就来聊聊这个差距到底在哪,以及怎么用数学工具去弥合它。

3.1 人眼视觉特性:我们到底看到了什么?

人眼不是一台完美的相机。它有很多「作弊」的地方。我刚开始做图像处理时,总以为RGB三通道就是人眼看到的全部,后来才发现,这想法太天真了。

人眼视觉有几个关键特性,跟白平衡直接相关:

  • 色彩恒常性:这是最核心的。大脑会自动补偿光源颜色,让我们觉得物体颜色是「固有」的。白平衡算法,本质上就是在模仿这个机制。
  • 亮度适应:人眼对亮度的感知不是线性的。暗部稍微亮一点,我们感觉变化很大;亮部再亮一点,我们几乎察觉不到。这就是为什么Gamma校正如此重要。
  • 视锥细胞响应:人眼有三种视锥细胞,分别对长波(L,偏红)、中波(M,偏绿)、短波(S,偏蓝)敏感。但它们的响应曲线是重叠的,而且峰值分布并不均匀。

关键点:人眼的色彩恒常性并不完美。在极端光源下(比如深红色暗房),大脑也会「翻车」。这就是为什么自动白平衡算法在某些场景下会失效——它试图模拟一个不完美的系统。

3.2 RGB色彩空间:传感器的原始语言

相机传感器直接输出的就是RGB数据。但这里的RGB,跟你在显示器上看到的RGB,其实不是一回事。

传感器RGB有几个「坑」:

  • 设备相关:不同型号的传感器,甚至同一型号不同批次,对红绿蓝的敏感度都不一样。你在这个相机上拍出的红色,换到另一个相机上可能偏橙。
  • 线性问题:传感器输出的是线性光强信号,但人眼感知是非线性的。直接拿线性RGB去做白平衡,结果往往很「假」。
  • 色域有限:sRGB、Adobe RGB这些标准,只能覆盖人眼可见色的一部分。有些颜色,你根本没法用RGB精确表示。

我在项目中遇到过一个问题:用某款工业相机采集的RGB数据,直接做白平衡后,绿色植物总是偏黄。折腾了两天,最后发现是传感器的绿色通道响应曲线跟标准sRGB不匹配。后来我改用XYZ空间做中间转换,问题就解决了。

3.3 CIE 1931 XYZ色彩空间:一个「标准」的坐标系

既然RGB不靠谱,那总得有个「标准」吧?CIE 1931 XYZ色彩空间就是干这个的。它基于人眼视觉实验数据,定义了一个与设备无关的色彩空间。

XYZ空间有几个特点:

  • 所有可见色都能表示:它的色域覆盖了人眼能看到的全部颜色。
  • Y代表亮度:这一点很巧妙。X和Z只负责色度信息,Y单独管亮度。做白平衡时,我们通常只调整色度,不动亮度。
  • 线性变换:从线性RGB到XYZ,就是一个3x3矩阵乘法。计算简单,适合硬件实现。

我的习惯:在做自动白平衡时,我通常先把线性RGB转到XYZ空间,在XYZ里做色温校正,再转回RGB。虽然多了一步矩阵运算,但结果稳定得多。尤其是处理混合光源场景时,这个流程几乎成了我的「标准动作」。

3.4 CIE 1931 色度图:一张「地图」

色度图就是把XYZ空间里的颜色,投影到一个二维平面上。横轴是x,纵轴是y,z = 1 - x - y。这张图,就是色彩科学的「世界地图」。

这张图能告诉我们什么?

  • 色域边界:马蹄形曲线就是人眼能看到的全部颜色。曲线上的点是单色光(光谱色),内部是混合色。
  • 白点位置:不同色温的白光,在色度图上有对应的坐标。D65(6500K)大概在(0.3127, 0.3290)附近。白平衡校正,就是把图像的白点「拉」到这个目标位置。
  • 色温轨迹:黑体辐射在不同温度下的颜色变化,在色度图上形成一条曲线,叫普朗克轨迹。大多数自然光源都落在这条线附近。

我曾经调试一个户外监控摄像头的白平衡,发现阴天时画面总是偏蓝。查了半天,发现算法里用的白点坐标是D65,但阴天的实际色温接近7000K,白点位置差了一大截。后来我根据色度图上的色温轨迹,动态调整目标白点,问题就解决了。

避坑指南:色度图上的距离,并不代表人眼感知的颜色差异。两个点挨得很近,人眼可能觉得颜色完全不同;离得很远,人眼反而觉得差不多。这就是「麦克亚当椭圆」现象。做白平衡时,别在色度图上用欧氏距离做聚类,否则结果会很「辣眼睛」。

3.5 从RGB到XYZ的转换

说了这么多,到底怎么转?其实就是一个矩阵乘法。以sRGB到XYZ(D65)为例:

// 线性sRGB to XYZ (D65)
// 假设RGB已经去Gamma校正,是线性值
double[][] matrix = {
    { 0.4124564,  0.3575761,  0.1804375 },
    { 0.2126729,  0.7151522,  0.0721750 },
    { 0.0193339,  0.1191920,  0.9503041 }
};

double X = matrix[0][0] * R + matrix[0][1] * G + matrix[0][2] * B;
double Y = matrix[1][0] * R + matrix[1][1] * G + matrix[1][2] * B;
double Z = matrix[2][0] * R + matrix[2][1] * G + matrix[2][2] * B;

反过来,从XYZ到sRGB,就是求逆矩阵。不同标准(Adobe RGB、DCI-P3)的矩阵系数不一样,用之前一定要确认好。

3.6 知识结构图

下面这张图,把这一章的核心概念串起来了。你可以看到,从人眼到传感器,再到数学空间,最后落到白平衡应用,是一条清晰的链路。

色彩科学基础结构图 色彩科学基础:从人眼到白平衡 人眼视觉系统 色彩恒常性 · 亮度适应 视锥细胞(LMS)响应 传感器RGB 设备相关 · 线性光强 色域有限 CIE 1931 XYZ 设备无关 · 全色域 Y代表亮度 CIE 1931 色度图 白点定位 · 色温轨迹 色域边界 自动白平衡校正 色温估计 · 色彩补偿 核心思路 用设备无关的XYZ空间 做色温校正,再转回RGB

3.7 本章小结

这一章的内容,说白了就是三件事:

  1. 人眼会「骗人」,但白平衡算法得学会怎么「骗」回去。
  2. RGB不靠谱,因为它跟设备绑死了。XYZ才是通用的「世界语」。
  3. 色度图是地图,白点位置、色温轨迹,都在上面标得清清楚楚。