我正在寻找某种公式或算法来确定给定RGB值的颜色的亮度。我知道这不像把RGB值加在一起那么简单,更高的总和更亮,但我有点不知所措,不知道从哪里开始。
当前回答
HSV色彩空间应该做的把戏,看维基百科文章取决于你正在工作的语言,你可能会得到一个库转换。
H是色调,是颜色的数值(即红色,绿色…)
S是颜色的饱和度,即它有多“强烈”
V是颜色的亮度。
其他回答
基于所有这些答案,我的简单结论是,对于大多数实际用例,您只需要:
brightness = 0.2*r + 0.7*g + 0.1*b
当r,g,b值在0到255之间时,亮度范围也在0(=黑)到255(=白)之间。
可以对它进行微调,但通常没有必要。
我认为你正在寻找的是RGB ->流光转换公式。
光度/数字ITU BT.709:
Y = 0.2126 R + 0.7152 G + 0.0722 B
数字ITU BT.601(给予R和B部分更多权重):
Y = 0.299 R + 0.587 G + 0.114 B
如果你愿意用准确性来换取性能,有两个近似公式:
Y = 0.33 R + 0.5 G + 0.16 B
Y = 0.375 R + 0.5 G + 0.125 B
这些可以快速计算为
Y = (R+R+B+G+G+G)/6
Y = (R+R+R+B+G+G+G+G)>>3
这里有一小段C代码,可以正确地计算可感知的亮度。
// reverses the rgb gamma
#define inverseGamma(t) (((t) <= 0.0404482362771076) ? ((t)/12.92) : pow(((t) + 0.055)/1.055, 2.4))
//CIE L*a*b* f function (used to convert XYZ to L*a*b*) http://en.wikipedia.org/wiki/Lab_color_space
#define LABF(t) ((t >= 8.85645167903563082e-3) ? powf(t,0.333333333333333) : (841.0/108.0)*(t) + (4.0/29.0))
float
rgbToCIEL(PIXEL p)
{
float y;
float r=p.r/255.0;
float g=p.g/255.0;
float b=p.b/255.0;
r=inverseGamma(r);
g=inverseGamma(g);
b=inverseGamma(b);
//Observer = 2°, Illuminant = D65
y = 0.2125862307855955516*r + 0.7151703037034108499*g + 0.07220049864333622685*b;
// At this point we've done RGBtoXYZ now do XYZ to Lab
// y /= WHITEPOINT_Y; The white point for y in D65 is 1.0
y = LABF(y);
/* This is the "normal conversion which produces values scaled to 100
Lab.L = 116.0*y - 16.0;
*/
return(1.16*y - 0.16); // return values for 0.0 >=L <=1.0
}
我想知道这些rgb系数是如何确定的。我自己做了一个实验,得出了以下结论:
Y = 0.267 R + 0.642 G + 0.091 B
接近,但与长期建立的ITU系数明显不同。我想知道这些系数是否对每个观察者来说都是不同的,因为我们眼睛视网膜上的视锥细胞和视杆细胞的数量都是不同的,尤其是不同类型的视锥细胞之间的比例可能是不同的。
供参考:
这是BT . 709:
Y = 0.2126 R + 0.7152 G + 0.0722 B
这是BT . 601:
Y = 0.299 R + 0.587 G + 0.114 B
我在亮红色、亮绿色和亮蓝色的背景上快速移动一个小灰色条,并调整灰色,直到它尽可能地融合在一起。我还用其他色调重复了这个测试。我在不同的显示器上重复了测试,即使是gamma因子固定为3.0的显示器,但在我看来都是一样的。更重要的是,ITU系数对我的眼睛来说是错误的。
是的,我对颜色的视觉应该是正常的。
把这看作是对Myndex的精彩回答的补充。正如他(和其他人)解释的那样,计算RGB颜色的相对亮度(和感知亮度)的算法是设计用于线性RGB值的。你不能只是将它们应用到原始sRGB值上,并希望得到相同的结果。
理论上,这一切听起来都很棒,但我真的需要亲眼看看证据,所以,受到彼得·赫塔克(Petr Hurtak)的颜色渐变的启发,我自己做了一个。它们说明了两种最常见的算法(ITU-R建议BT.601和BT.709),并清楚地说明了为什么应该使用线性值(而不是伽玛校正值)进行计算。
首先,下面是旧的ITU BT.601算法的结果。左边的使用原始sRGB值。右边的使用线性值。
ITU-R BT.601颜色亮度梯度
0.299 r + 0.587 g + 0.114 b
在这个分辨率下,左边的照片实际上看起来非常好!但如果你仔细观察,你会发现一些问题。在更高的分辨率下,不需要的人工制品更加明显:
线性的不受这些影响,但是有很多干扰。让我们将其与ITU-R建议BT.709进行比较……
ITU-R BT.709颜色亮度梯度
0.2126 r + 0.7152 g + 0.0722 b
哦男孩。显然不打算与原始sRGB值一起使用!然而,这正是大多数人所做的!
在高分辨率下,你可以真正看到这个算法在使用线性值时是多么有效。它没有之前那个那么多噪音。虽然这些算法都不是完美的,但这个算法已经是最好的了。