确定RGB颜色亮度的公式

我正在寻找某种公式或algorithm来确定给定RGB值的颜色的亮度。 我知道它不能像将RGB值加在一起那么简单,并且有更高的总和更亮,但是对于从哪里开始,我感到不知所措。

你的意思是亮度? 感知亮度? 亮度?

  • 亮度(某些色彩空间的标准):( (0.2126*R + 0.7152*G + 0.0722*B) [1]
  • 亮度(感知选项1):( (0.299*R + 0.587*G + 0.114*B) [2]
  • 亮度(感知选项2,计算较慢): sqrt( 0.241*R^2 + 0.691*G^2 + 0.068*B^2 )sqrt( 0.299*R^2 + 0.587*G^2 + 0.114*B^2 ) (感谢@MatthewHerbst ) [3]

我觉得你要找的是RGB – > Luma转换公式。

光度/数字ITU BT.709 :

 Y = 0.2126 R + 0.7152 G + 0.0722 B 

数字国际电联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 

我已经在接受的答案中比较了三种algorithm。 我生成的颜色只有大约每使用400个颜色。 每种颜色用2×2像素表示,颜色从最黑到最浅(从左到右,从上到下)sorting。

第一张照片 – 亮度(相对)

 0.2126 * R + 0.7152 * G + 0.0722 * B 

第二张照片 – http://www.w3.org/TR/AERT#color-contrast

 0.299 * R + 0.587 * G + 0.114 * B 

第三张照片 – HSP颜色模型

 sqrt(0.299 * R^2 + 0.587 * G^2 + 0.114 * B^2) 

第4张照片 – WCAG 2.0 SC 1.4.3 相对亮度和对比度公式(请参阅@ Synchro的回答)

根据一行中的颜色数量,图案有时会在第1张和第2张图片上出现。 我从来没有发现从第三或第四algorithm的图片上的任何模式。

如果我不得不select,我会使用3号algorithm,因为它更容易实现,比第四个速度快33%。

感知亮度算法比较

以下是用于浏览器等的sRGB图像唯一的CORRECTalgorithm。

在计算内积之前,有必要对颜色空间应用伽玛函数的倒数。 然后,将伽马函数应用于减小的值。 未能join伽玛function可能会导致错误达20%。

对于典型的电脑东西,色彩空间是sRGB。 sRGB的正确数字大约是。 0.21,0.72,0.07。 sRGB的Gamma是一个复合函数,近似取幂1 /(2.2)。 这是C ++中的全部内容。

 // sRGB luminance(Y) values const double rY = 0.212655; const double gY = 0.715158; const double bY = 0.072187; // Inverse of sRGB "gamma" function. (approx 2.2) double inv_gam_sRGB(int ic) { double c = ic/255.0; if ( c <= 0.04045 ) return c/12.92; else return pow(((c+0.055)/(1.055)),2.4); } // sRGB "gamma" function (approx 2.2) int gam_sRGB(double v) { if(v<=0.0031308) v *= 12.92; else v = 1.055*pow(v,1.0/2.4)-0.055; return int(v*255+0.5); // This is correct in C++. Other languages may not // require +0.5 } // GRAY VALUE ("brightness") int gray(int r, int g, int b) { return gam_sRGB( rY*inv_gam_sRGB(r) + gY*inv_gam_sRGB(g) + bY*inv_gam_sRGB(b) ); } 

有趣的是, RGB => HSV的这个公式只使用v = MAX3(r,g,b)。 换句话说,你可以使用(r,g,b)的最大值作为HSV中的V.

我检查了Hearn&Baker的第575页,这也是他们计算“价值”的方法。

来自Hearn&Baker第319页

在这里提到的随机select公式中,我build议你selectW3C标准推荐的公式。

这是一个简单但精确的PHP实现WCAG 2.0 SC 1.4.3 相对亮度和对比度公式。 它会生成适合评估WCAG合规性所需比率的值,如本页所示 ,因此适用于任何Web应用程序。 这对于移植到其他语言是微不足道的。

 /** * Calculate relative luminance in sRGB colour space for use in WCAG 2.0 compliance * @link http://www.w3.org/TR/WCAG20/#relativeluminancedef * @param string $col A 3 or 6-digit hex colour string * @return float * @author Marcus Bointon <marcus@synchromedia.co.uk> */ function relativeluminance($col) { //Remove any leading # $col = trim($col, '#'); //Convert 3-digit to 6-digit if (strlen($col) == 3) { $col = $col[0] . $col[0] . $col[1] . $col[1] . $col[2] . $col[2]; } //Convert hex to 0-1 scale $components = array( 'r' => hexdec(substr($col, 0, 2)) / 255, 'g' => hexdec(substr($col, 2, 2)) / 255, 'b' => hexdec(substr($col, 4, 2)) / 255 ); //Correct for sRGB foreach($components as $c => $v) { if ($v <= 0.03928) { $components[$c] = $v / 12.92; } else { $components[$c] = pow((($v + 0.055) / 1.055), 2.4); } } //Calculate relative luminance using ITU-R BT. 709 coefficients return ($components['r'] * 0.2126) + ($components['g'] * 0.7152) + ($components['b'] * 0.0722); } /** * Calculate contrast ratio acording to WCAG 2.0 formula * Will return a value between 1 (no contrast) and 21 (max contrast) * @link http://www.w3.org/TR/WCAG20/#contrast-ratiodef * @param string $c1 A 3 or 6-digit hex colour string * @param string $c2 A 3 or 6-digit hex colour string * @return float * @author Marcus Bointon <marcus@synchromedia.co.uk> */ function contrastratio($c1, $c2) { $y1 = relativeluminance($c1); $y2 = relativeluminance($c2); //Arrange so $y1 is lightest if ($y1 < $y2) { $y3 = $y1; $y1 = $y2; $y2 = $y3; } return ($y1 + 0.05) / ($y2 + 0.05); } 

我发现这个代码 (用C#编写的)能很好地计算颜色的“亮度”。 在这种情况下,代码正试图确定是否将白色或黑色文本放在颜色上。

要添加所有其他人说的话:

所有这些方程式在实践中都相当成功,但如果您需要非常精确,则必须首先将颜色转换为线性颜色空间(应用反转图像伽马),然后进行原色的重量平均值,如果您想要显示颜色 – 将亮度恢复到显示器伽玛值。

在黑暗的灰色,ingnoring伽玛和做适当的伽马之间的亮度差异高达20%。

HSV的色彩空间应该做的伎俩,看到维基百科的文章取决于你在你工作的语言可能会得到一个图书馆的转换。

H是颜色(即红色,绿色…)的数值的色调

S是颜色的饱和度,即它是多么“激烈”

V是颜色的“亮度”。

RGB亮度值= 0.3 R + 0.59 G + 0.11 B

http://www.scantips.com/lumin.html

如果你正在寻找如何接近白色的颜色,你可以使用从(255,255,255)的欧几里得距离,

我认为RGB色彩空间相对于L2欧几里德距离是非常不均匀的。 统一空间包括CIE LAB和LUV。

这个链接深入解释了一切,包括为什么这些乘数常数在R,G和B值之前存在。

编辑:这里也有一个解释(0.299 * R + 0.587 * G + 0.114 * B)

Jive Dadson的反伽马公式需要在Javascript中实现半调整,即函数gam_sRGB的返回需要返回int(v * 255)。 不返回int(v * 255 + .5); 半调整四舍五入,这可能导致R = G = B(即灰色三元组)上的值太高。 在R = G = B三元组上的灰度转换应该产生一个等于R的值; 这个公式是有效的证据。 请参阅九个灰度阴影的公式(没有半调整)。

这里有一些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=pr/255.0; float g=pg/255.0; float b=pb/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 } 

HSV的'V'可能是你正在寻找的。 MATLAB有一个rgb2hsv函数,前面引用的维基百科文章充满了伪代码。 如果RGB2HSV转换不可行,则较不准确的模型将是图像的灰度版本。

为了清楚起见,使用平方根的公式必须是

sqrt(coefficient * (colour_value^2)

sqrt((coefficient * colour_value)^2

其certificate在于将R = G = B三元组转换为灰度R.这只有在将颜色值平方而不是颜色值乘以系数时才是正确的。 见九个灰度阴影

我想知道这些rgb系数是如何确定的。 我自己做了一个实验,结果如下:

 Y = 0.267 R + 0.642 G + 0.091 B 

与长期build立的国际电联系数接近但明显不同。 我想知道这些系数对于每个观察者是否会有所不同,因为我们眼睛的视网膜都可能有不同数量的视锥和视杆,特别是不同types视锥的比例可能不同。

以供参考:

国际电联BT.709:

 Y = 0.2126 R + 0.7152 G + 0.0722 B 

国际电联BT.601:

 Y = 0.299 R + 0.587 G + 0.114 B 

我通过在明亮的红色,明亮的绿色和明亮的蓝色背景上快速移动一个小的灰色条,并调整灰色,直到尽可能地混合,做了testing。 我也用其他色调重复了这个testing。 我在不同的显示器上重复了这个testing,甚至是一个固定伽马系数为3.0的testing,但是对我来说看起来都是一样的。 更重要的是,国际电联的系数字面上是错误的我的眼睛。

是的,我估计有一个正常的色彩视觉。

为了用R确定颜色的亮度,我将HSV系统颜色中的RGB系统颜色进行转换。

在我的脚本中,由于其他原因我使用了HEX系统代码,但是也可以使用rgb2hsv {grDevices}来启动RGB系统代码。 文档在这里 。

这是我的代码的这一部分:

  sample <- c("#010101", "#303030", "#A6A4A4", "#020202", "#010100") hsvc <-rgb2hsv(col2rgb(sample)) # convert HEX to HSV value <- as.data.frame(hsvc) # create data.frame value <- value[3,] # extract the information of brightness order(value) # ordrer the color by brightness 

请定义亮度。 如果你正在寻找如何接近白色的颜色,你可以使用从(255,255,255)的欧几里得距离 ,