我正在寻找某种公式或算法来确定给定RGB值的颜色的亮度。我知道这不像把RGB值加在一起那么简单,更高的总和更亮,但我有点不知所措,不知道从哪里开始。
当前回答
再加上其他人说的话:
所有这些方程在实践中都工作得很好,但如果你需要非常精确,你必须首先将颜色转换为线性颜色空间(应用逆图像-gamma),对原色进行权重平均,如果你想显示颜色- 把亮度调回监控器伽马。
在深灰色中,忽略伽玛和正确伽玛之间的亮度差异高达20%。
其他回答
HSV色彩空间应该做的把戏,看维基百科文章取决于你正在工作的语言,你可能会得到一个库转换。
H是色调,是颜色的数值(即红色,绿色…)
S是颜色的饱和度,即它有多“强烈”
V是颜色的亮度。
方法可以根据您的需要而有所不同。以下是计算亮度的3种方法:
亮度(某些颜色空间的标准):(0.2126*R + 0.7152*G + 0.0722*B)光源 亮度(感知选项1):(0.299*R + 0.587*G + 0.114*B)光源 亮度(感知选项2,计算较慢):根号(0.241*R^2 + 0.691*G^2 + 0.068*B^2)→根号(0.299*R^2 + 0.587*G^2 + 0.114*B^2)(感谢@MatthewHerbst)来源
[编辑:添加了使用命名css颜色的例子,按每种方法排序。]
HSV的“V”可能就是你要找的。MATLAB有一个rgb2hsv函数,之前引用的维基百科文章充满了伪代码。如果RGB2HSV转换不可行,则较不准确的模型将是图像的灰度版本。
这里有一小段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
}
把这看作是对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值一起使用!然而,这正是大多数人所做的!
在高分辨率下,你可以真正看到这个算法在使用线性值时是多么有效。它没有之前那个那么多噪音。虽然这些算法都不是完美的,但这个算法已经是最好的了。