我正在寻找某种公式或算法来确定给定RGB值的颜色的亮度。我知道这不像把RGB值加在一起那么简单,更高的总和更亮,但我有点不知所措,不知道从哪里开始。
当前回答
把这看作是对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值一起使用!然而,这正是大多数人所做的!
在高分辨率下,你可以真正看到这个算法在使用线性值时是多么有效。它没有之前那个那么多噪音。虽然这些算法都不是完美的,但这个算法已经是最好的了。
其他回答
为了用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
我认为你正在寻找的是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
我想知道这些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系数对我的眼睛来说是错误的。
是的,我对颜色的视觉应该是正常的。
正如@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的答案以获得更准确的计算。
方法可以根据您的需要而有所不同。以下是计算亮度的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颜色的例子,按每种方法排序。]