我正在寻找某种公式或算法来确定给定RGB值的颜色的亮度。我知道这不像把RGB值加在一起那么简单,更高的总和更亮,但我有点不知所措,不知道从哪里开始。
当前回答
基于所有这些答案,我的简单结论是,对于大多数实际用例,您只需要:
brightness = 0.2*r + 0.7*g + 0.1*b
当r,g,b值在0到255之间时,亮度范围也在0(=黑)到255(=白)之间。
可以对它进行微调,但通常没有必要。
其他回答
我想知道这些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系数对我的眼睛来说是错误的。
是的,我对颜色的视觉应该是正常的。
基于所有这些答案,我的简单结论是,对于大多数实际用例,您只需要:
brightness = 0.2*r + 0.7*g + 0.1*b
当r,g,b值在0到255之间时,亮度范围也在0(=黑)到255(=白)之间。
可以对它进行微调,但通常没有必要。
为了用R确定颜色的亮度,我将RGB系统颜色转换为HSV系统颜色。
在我的脚本中,我之前因为其他原因使用了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
我已经在接受的答案中对三种算法做了比较。我循环生成颜色,大约每400个颜色使用一次。每种颜色由2x2像素表示,颜色从最深到最浅(从左到右,从上到下)排序。
第一张图片-亮度(相对)
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的答案在这里)
根据一行中的颜色数量,有时可以在第一张和第二张图片上发现图案。我从第3或第4算法的图片上没有发现任何模式。
如果我必须选择,我会选择算法3,因为它更容易实现,比4快33%。
正如@Nils Pipenbrinck所提到的:
所有这些方程在实践中都很有效,但如果你需要非常精确,你就必须[做一些额外的gamma东西]。在深灰色中,忽略伽玛和正确伽玛之间的亮度差异高达20%。
这里有一个完全自包含的JavaScript函数,它做了“额外的”工作来获得额外的准确性。它基于Jive Dadson对这个问题的c++回答。
// Returns greyscale "brightness" (0-1) of the given 0-255 RGB values
// Based on this C++ implementation: https://stackoverflow.com/a/13558570/11950764
function rgbBrightness(r, g, b) {
let v = 0;
v += 0.212655 * ((r/255) <= 0.04045 ? (r/255)/12.92 : Math.pow(((r/255)+0.055)/1.055, 2.4));
v += 0.715158 * ((g/255) <= 0.04045 ? (g/255)/12.92 : Math.pow(((g/255)+0.055)/1.055, 2.4));
v += 0.072187 * ((b/255) <= 0.04045 ? (b/255)/12.92 : Math.pow(((b/255)+0.055)/1.055, 2.4));
return v <= 0.0031308 ? v*12.92 : 1.055 * Math.pow(v,1.0/2.4) - 0.055;
}
请参阅Myndex的答案以获得更准确的计算。