色彩科学基础:人眼视觉特性、色彩空间与白平衡

做AI ISP这几年,我越来越觉得色彩科学是根。你想想看,传感器采集的是RAW数据,但最终用户看到的是照片。中间这层转换,全靠色彩科学撑着。如果基础不牢,后面做HDR融合、色彩重建,很容易跑偏。

这一章,我们聊聊人眼怎么看颜色、几个核心色彩空间怎么用,以及白平衡到底在平衡什么。嗯,都是基本功,但也是我踩坑最多的地方。

人眼视觉特性:我们为什么需要色彩空间?

人眼不是完美的传感器。它有三个关键特性,直接决定了我们怎么设计色彩处理流程。

  • 三色视锥细胞:人眼视网膜上有三种视锥细胞,分别对长波(L,红)、中波(M,绿)、短波(S,蓝)敏感。这就是三色刺激理论的生理基础。
  • 亮度与色度分离感知:人眼对亮度变化比对色度变化更敏感。所以视频压缩里YUV比RGB更高效,ISP里做降噪也要先保亮度。
  • 色适应:人眼会自动调整对不同光源的感知。同一张白纸,在日光灯下和烛光下,你看着都是白的。但传感器不会,它需要白平衡算法来模拟这个能力。

核心结论:色彩空间本质上是把物理光谱映射到人眼感知空间的数学工具。没有这个映射,传感器和显示器之间就是鸡同鸭讲。

RGB色彩空间:最直接,也最不通用

RGB是最直观的色彩空间。每个像素用R、G、B三个分量表示,范围0-255(8bit)或0-1023(10bit)。

但有个坑:RGB是设备相关的。同一组RGB值,在不同显示器上颜色完全不同。我在项目中遇到过,算法在实验室显示器上调好了,拿到客户那边偏色严重。后来才意识到,是sRGB和DCI-P3的色域差异导致的。

RGB变体 色域 典型应用
sRGB 较小,覆盖约35% CIE色域 网页、普通显示器
Adobe RGB 较大,覆盖约50% CIE色域 专业摄影、印刷
DCI-P3 介于sRGB和Adobe RGB之间 数字影院、高端手机
BT.2020 超大,覆盖约75% CIE色域 HDR、8K视频

我的建议:做ISP算法时,内部统一用线性RGB或XYZ做计算,只在最终输出时转换到目标色域。这样可以避免多次转换带来的精度损失。

XYZ色彩空间:色彩科学的“通用语”

XYZ是CIE在1931年定义的色彩空间。它基于人眼三色刺激实验,是设备无关的。说白了,RGB是方言,XYZ是普通话。

XYZ的Y分量直接对应亮度,X和Z对应色度。这个特性让它在色彩匹配和色域转换中特别好用。

// sRGB到XYZ的转换矩阵(D65白点)
// 注意:输入RGB需要先做gamma校正
float[3][3] sRGB_to_XYZ = {
  {0.4124564, 0.3575761, 0.1804375},
  {0.2126729, 0.7151522, 0.0721750},
  {0.0193339, 0.1191920, 0.9503041}
};

避坑指南:我曾经在HDR融合中直接用sRGB做加权平均,结果颜色边缘出现奇怪的伪影。后来改成在XYZ空间做融合,问题就解决了。因为XYZ的亮度分量是线性的,而sRGB的gamma校正会破坏线性关系。

Lab色彩空间:感知均匀的“人眼友好”空间

Lab的设计目标是让数值差异和人眼感知差异成正比。L是亮度,a和b是色度坐标。a从绿到红,b从蓝到黄。

为什么需要Lab?因为RGB和XYZ都不是感知均匀的。举个例子,在RGB空间里,[100, 0, 0]和[110, 0, 0]的差异,人眼几乎看不出来;但[0, 100, 0]和[0, 110, 0]的差异,人眼能明显感觉到。Lab解决了这个问题。

  • L分量:0-100,对应从黑到白
  • a分量:负值偏绿,正值偏红
  • b分量:负值偏蓝,正值偏黄

我在做色彩增强算法时,习惯在Lab空间里操作。只调整a和b分量,不动L,可以避免引入亮度噪声。这个技巧在低光场景下特别管用。

HSV色彩空间:调色师的“直觉空间”

HSV把颜色分解成色相(Hue)、饱和度(Saturation)、明度(Value)。H用角度表示,0°是红,120°是绿,240°是蓝。

这个空间的好处是直观。你想让画面更鲜艳?调S。你想让整体偏暖?调H。不需要像RGB那样三个分量一起猜。

// RGB到HSV的转换(简化版)
// 输入RGB归一化到[0,1]
float max_val = max(R, max(G, B));
float min_val = min(R, min(G, B));
float delta = max_val - min_val;

// 计算H
if (delta == 0) H = 0;
else if (max_val == R) H = 60 * fmod((G - B) / delta, 6);
else if (max_val == G) H = 60 * ((B - R) / delta + 2);
else H = 60 * ((R - G) / delta + 4);

// 计算S
S = (max_val == 0) ? 0 : delta / max_val;

// V就是max_val
V = max_val;

实用技巧:做肤色检测时,HSV比RGB好用得多。肤色在HSV空间里集中在H=0°-30°、S=0.1-0.6、V=0.3-0.9的区域。用这个范围做mask,比RGB阈值稳定很多。

色彩温度与白平衡:让传感器学会“色适应”

色温用开尔文(K)表示。低色温偏暖(烛光约1800K),高色温偏冷(阴天约6500K)。标准日光大约是5500K。

白平衡的目标是:不管光源是什么,让白色物体在图像里看起来是白的。这需要估计当前光源的色温,然后做反向补偿。

常用的白平衡方法有三种:

  1. 灰度世界法:假设场景中所有颜色的平均值是灰色。计算R、G、B通道的平均值,然后调整增益使三者相等。
  2. 完美反射法:假设场景中最亮的像素是白色。找到这些像素,用它们的RGB值来估计光源。
  3. 色温曲线法:预先标定不同色温下的R/G和B/G比值,形成一条曲线。实时计算当前图像的R/G和B/G,查曲线得到色温。

踩坑记录:我曾经在夜景场景下用灰度世界法做白平衡,结果画面偏蓝得一塌糊涂。为什么?因为夜景里蓝色霓虹灯太多,平均值根本不是灰色。后来我改用色温曲线法,结合场景检测,才把这个问题解决。

本章知识体系

下面这张图总结了色彩科学的核心脉络,从人眼感知到算法实现,每一步都有对应的色彩空间和工具。

色彩科学知识体系 色彩科学知识体系 人眼视觉特性 三色视锥细胞(L/M/S) 亮度与色度分离感知 色适应机制 核心色彩空间 RGB(设备相关) XYZ(设备无关) Lab(感知均匀) HSV(调色直觉) 白平衡算法 灰度世界法 完美反射法 色温曲线法 核心逻辑 人眼感知特性决定了色彩空间的设计目标: • 三色视锥细胞 → RGB/XYZ(三通道表示) • 亮度色度分离 → Lab/YUV(分离亮度和色度) • 色适应 → 白平衡算法(模拟人眼自动调整)

这张图把三个核心模块串起来了。左边是人眼特性,中间是色彩空间,右边是白平衡算法。每个模块之间都有明确的映射关系。做ISP算法时,我经常回头看看这张图,提醒自己不要偏离物理基础。

一句话总结:色彩科学不是数学游戏,它是人眼感知的数学建模。理解了这个,你才能做出让用户觉得“舒服”的图像。