生成相同亮度的纯色(用于在LED上显示)

时间:2017-10-11 19:03:11

标签: algorithm colors led

我有一些RGB LED,我想让它们显示随机颜色。

我的第一种方法是从0-360选择随机色调 h ,创建表格的HSV颜色( h ,1,1),然后转换使用the algorithm given on Wikipedia从HSV到RGB。这几乎可以达到我的要求,但并不完全。

问题在于LED可能看起来更亮或更暗,具体取决于色调。无论色调如何,我希望它总是看起来是相同的亮度。

因此,例如,蓝色在RGB空间中将是(0,0,1),但青色将是(0,1,1)。如果我们做出简化假设,即所有三个原色同样明亮,那么青色的亮度是蓝色的两倍。

我想要的是RGB空间中蓝色为(0,0,1),青色为(0,0.5,0.5),因此原色的总和始终为1.0。

我可以使用这样的算法轻松地将一些东西放在一起:

  • 在0和1之间选择值 x
  • 选择三个原色中的一个,并将其设置为 x
  • 选择其余两个原色中的一个,并将其设置为1 - x
  • 将第三个主要设置为0。

我的问题是:有更原则的方法吗?是否有一些行为符合我想要的颜色空间?

结论: @Vincent van der Weele拥有我需要规范化的重要见解。 @Stefan Haustein的luma是另一种说同样话题的方式,同时也为不同的原色添加不同的权重。但是,这些特殊的重量在我的情况下不起作用。在实验上,我为R,G和B选择了0.3,0.25和0.2的权重。而且在实验上,我选择了2.0的伽玛(与我最初使用的2.8相反)。这仍然不完美,但它比以前好多了。我想这只是天生凌乱。

2 个答案:

答案 0 :(得分:2)

我会将亮度用于你的光谱中最暗的颜色(=蓝色,0.0722)。然后缩放计算的RGB值,以便得到的亮度与此值匹配。见https://en.wikipedia.org/wiki/Luma_(video)

luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
// factor * luma = 0.0722
factor = 0.0722 / luma;
r *= factor;
g *= factor;
b *= factor;

P.S。通过简化假设,这将是

luma = (r + g + b) / 3.0;
factor = 1.0 / (3.0 * luma);
r *= factor;
g *= factor;
b *= factor;

将总亮度归一化为单个分​​量的亮度(1/3)

答案 1 :(得分:2)

你是对的,黄色,青色和洋红色的组合颜色比红色,绿色和蓝色的原色更亮。您可以在HSV生成的色调的简单图中看到这一点(我相信HSL会看起来一样):

HSV in sRGB

它们更亮,但两次更亮。那是因为眼睛用power-law function响应光线。将强度调整到the power of 0.43最接近你眼睛看到的强度;这意味着黄色,青色和品红色只会亮1.35倍。

还有另外一个因素需要考虑。 HSV公式产生sRGB值,其gamma correction factor约为2.2 - 这些值与产生的光量不是线性的。您的LED可能线性的,因此它们看起来会有所不同:

HSV linearized

呸!显然,驱动LED的值需要处于线性色彩空间,而不是sRGB。

为了保持恒定的亮度,幂律空间中所有颜色的总和将需要保持不变。您可以通过将幂定律应用于线性r,g,b强度,然后在总和上缩放r,g,b来实现此目的。采用幂律的倒数将值恢复为线性RGB。

这是一些实际的Python代码和生成的图像。 r,g,b值从线性转换为sRGB以生成图像文件,但为了清楚起见,我将其留下。我根据standard sRGB linearity conversions编写的srgb2.from_sRGB函数。

r,g,b = colorsys.hsv_to_rgb(angle/360, 1.0, 1.0)
r,g,b = srgb2.from_sRGB([r*255,g*255,b*255])
gamma = .43
r,g,b = r**(1/gamma), g**(1/gamma), b**(1/gamma)
t = r + g + b
r = r / t
g = g / t
b = b / t
r,g,b = r**gamma, g**gamma, b**gamma

HSV normalized

没有更多的亮点!