色彩空间基础:从RGB到人眼感知的桥梁
做AWB调优这些年,我最大的体会就是——不懂色彩空间,你连白平衡的“白”是什么都说不清楚。说白了,色彩空间就是给颜色一个“身份证”,让不同设备之间能准确传递颜色信息。
今天咱们就聊聊几个最核心的色彩空间。嗯,这些概念我几乎每天都在用。
RGB与sRGB:最熟悉的陌生人
RGB大家都懂,红绿蓝三通道嘛。但你知道吗?RGB其实不是一个标准化的色彩空间。它只是一个“加法混色”的模型。真正要定义颜色,还得指定三原色的具体波长、白点位置、Gamma曲线等等。
举个例子。你显示器上的RGB和相机传感器上的RGB,根本就不是一回事。我在项目中遇到过这种情况:同一张RAW图,在不同软件里打开颜色完全不一样。原因就是它们用了不同的RGB定义。
sRGB就是来解决这个问题的。它由微软和惠普在1996年联合推出,定义了标准的RGB色彩空间。现在几乎所有互联网图片、显示器、打印机都默认用sRGB。
sRGB的几个关键参数:
- 白点:D65(色温6500K)
- Gamma:近似2.2
- 三原色色度坐标:R(0.6400, 0.3300)、G(0.3000, 0.6000)、B(0.1500, 0.0600)
我个人习惯,在做AWB算法时,先把所有颜色统一转到sRGB空间再处理。这样至少保证“起点”是一致的。
CIE 1931 XYZ:色彩世界的“绝对坐标系”
RGB有个硬伤——它依赖于设备。那有没有一种“绝对”的色彩空间?有,就是CIE 1931 XYZ。
1931年,国际照明委员会(CIE)搞了一次大规模的人眼颜色匹配实验。他们让受试者调整红绿蓝三原色的强度,去匹配单色光。结果发现,有些颜色用正值的RGB是配不出来的,必须引入“负值”的红色。
这太反人类了。于是他们做了个数学变换,把RGB转换成了XYZ三个虚拟的“基色”。XYZ的好处是:所有可见光的颜色都能用正值的XYZ表示。
我的经验:在ISP pipeline里,我经常把sRGB转成XYZ再做白平衡增益计算。因为XYZ的Y分量直接对应亮度,处理起来更干净。我曾经踩过一个坑——直接在RGB空间做白平衡,结果高饱和区域出现了色偏。后来转到XYZ空间处理,问题就解决了。
RGB到XYZ的转换矩阵(D65白点,sRGB):
| X | | 0.4124564 0.3575761 0.1804375 | | R |
| Y | = | 0.2126729 0.7151522 0.0721750 | | G |
| Z | | 0.0193339 0.1191920 0.9503041 | | B |
CIE Lab与Luv:让“距离”代表“差异”
XYZ虽然绝对,但它有个问题——人眼对颜色的感知不是线性的。你想想看,在XYZ空间里,两个点之间的欧氏距离,并不代表人眼感觉到的颜色差异大小。
这就尴尬了。做AWB调优时,我们需要量化“这个颜色偏了多少”。如果度量标准不准,调优就是瞎调。
于是CIE Lab和Luv诞生了。它们都是“感知均匀”的色彩空间。
- CIE Lab:L代表亮度,a代表红绿轴,b代表黄蓝轴。Lab空间里,两个颜色之间的欧氏距离,大致等于人眼感知的色差。
- CIE Luv:同样感知均匀,但更适用于加色混合(比如显示器)。Luv的u、v轴与色度图更接近。
注意:Lab和Luv都是从XYZ转换来的,不是直接从RGB转的。所以流程是:RGB → XYZ → Lab/Luv。我曾经见过有人直接把RGB转Lab,结果颜色完全乱套了。
Lab转XYZ的公式(部分):
// 假设 L* 在 [0, 100], a*, b* 在 [-128, 127]
// 先计算 f(Y/Yn)
fy = (L* + 16) / 116
fx = a* / 500 + fy
fz = fy - b* / 200
// 然后反推 X, Y, Z
Y = Yn * (fy^3) // 如果 fy > 0.008856
X = Xn * (fx^3)
Z = Zn * (fz^3)
色度图与普朗克轨迹:AWB的“地图”
好了,现在有了各种色彩空间,我们怎么用它们做AWB?
色度图(Chromaticity Diagram)就是把XYZ的亮度信息去掉,只看色度。常用的有CIE xy色度图。x和y由XYZ计算得来:
x = X / (X + Y + Z)
y = Y / (X + Y + Z)
z = 1 - x - y
在xy色度图上,所有可见光颜色都落在“马蹄形”区域内。这个马蹄形的边界就是单色光(光谱色)。
普朗克轨迹(Planckian Locus)是色度图上的一条曲线。它代表了不同色温下黑体辐射的颜色。从低色温的橙红色(2000K),到中性白(5500K),再到高色温的蓝色(10000K)。
AWB的核心思想:找到图像中“应该是白色”的区域,计算它的色度坐标,然后沿着普朗克轨迹找到对应的色温,最后做增益补偿。
我在项目中常用的做法是:
- 把图像转到XYZ空间
- 计算每个像素的xy色度
- 在色度图上找到离普朗克轨迹最近的点
- 根据偏移量计算R、B增益
嗯,这里要注意:实际场景中的光源不一定正好落在普朗克轨迹上。比如荧光灯、LED灯,它们的色度点往往偏离轨迹。这时候就需要更复杂的算法了。
知识体系总览
下面这张图是我自己整理的色彩空间关系图,帮你理清思路:
从这张图你可以看到,整个色彩链路是从传感器RAW数据开始的。先转到RGB/sRGB做标准化,再转到XYZ做绝对度量,最后根据需求转到Lab或Luv做感知分析。而色度图和普朗克轨迹,则是我们做AWB时的“导航工具”。
避坑指南:我曾经在调一款手机摄像头时,发现AWB在室内荧光灯下总是偏绿。查了两天才发现,问题出在色度图上的荧光灯位置偏离普朗克轨迹太远,而我的算法只考虑了轨迹上的点。后来我加了一个“偏离补偿”模块,问题就解决了。
好了,色彩空间的基础就聊到这儿。记住一句话:没有正确的色彩空间,就没有正确的白平衡。下一节我们会深入AWB的具体算法实现,到时候这些色彩空间知识都会用上。
公众号:蓝海资料掘金营,微信deep3321