将RGBW颜色转换为标准RGB/HSB表示



我正在为家庭自动化系统中的灯光管理构建一个接口。我设法控制了各种供应商的标准开/关和可调光,没有什么问题,但现在我遇到了一个与RGB光有关的问题。

我目前使用的灯是RGBW led灯带,具体来说,我使用的是低成本的RGBW灯:该灯由四个led组成,每个led都可以单独控制。

更清楚地说,我正在编写一些c#代码,这些代码应该检索当前选择的颜色并将其显示在UI中,并使用户能够为灯光指定新的颜色。为了设置颜色并检索它,我必须使用一个命令提供程序,使我能够通过web服务发送和接收命令。

该提供商使用RGBW颜色-使用红、绿、蓝和白四种颜色。为了在我的界面上表示当前的灯光颜色,我想将服务返回的RGBW颜色转换为更标准的RGB/HSB方案。

在网上搜索,我发现的颜色转换的唯一参考(不包括rgb到rgbw转换的c++示例,根据我的理解,它一定有一些严重的错误)是这篇文章,它显示了从HSI到rgbw的转换,这与我需要的相反:链接此处

我正在寻找一些关于我如何实现这种转换的见解(或者为什么不可能的简单解释)。就我所知,从RGB到RGBW的转换是任意的——单个RGB值可以表示为多个RGBW值,但相反的转换应该是唯一的。还要注意,当我使用c#时,也可以随意参考其他语言中的算法——语言不是问题,问题是我不知道进行颜色转换的数学方法。

如何将RGB转换为RGBW在以下论文的第2.1项中进行了描述

http://www.mirlab.org/conference_papers/International_Conference/ICASSP%202014/papers/p1214-lee.pdf

把你的led想象成一个巨大的像素。奥利弗的答案使用了Wo=min(Ri,Gi,Bi),这在计算上很便宜,而且很有效。本文解释了最大限度地减少功耗的其他选择,这对家庭自动化项目有好处。我也在一个家庭自动化项目中使用OpenHAB、Arduino和RGBW LED,一方面,论文提出的替代方案会很好,另一方面,一个巨大的LUT无法工作,无法转换Arduino eighter上的所有值。我建议你尝试使用论文中引用的不那么节能的技术来校正RGB值:

假设Ri,Gi,Bi是颜色输入,从0到255的整数,所以Q=255,并且您的输出是Wo,Ro,Go和Bo,值从0到255:

M = max(Ri,Gi,Bi)
m = min(Ri,Gi,Bi)
Wo = if (m/M < 0.5) use ( (m*M) / (M-m) ) else M 
Q = 255
K = (Wo + M) / m
Ro = floor( [ ( K * Ri ) - Wo ] / Q )
Go = floor( [ ( K * Gi ) - Wo ] / Q )
Bo = floor( [ ( K * Bi ) - Wo ] / Q )

在实施之前,在电子表格中进行练习,在Wo=m、m^2和-m^3+m^2+m上进行实验,用正确的Qw更正Wo值,你会惊讶于没有更正的简单解决方案不是人们所期望的,其他答案也没有那么大的变化。检查纸张的颜色失真结果,我想如果你不纠正RGB值,你最终会得到一些褪色的颜色。

我一直在复习Roberto提出的答案,但在许多情况下,颜色似乎更暗且不饱和。以RGB=(255255,2)为例,得出RGBW=(128128,1,2)。

进一步挖掘,Chul Lee的论文似乎在K的方程中有一个错误。这个方程来自Lili Wang的一篇论文("手机使用RGBW显示器的亮度和颜色之间的权衡")实际上是:

K = (Wo + M)/M

请注意,它是大写的M,而不是小写的M。考虑到这一变化,您也不需要Q,因为它在性质上可以正常缩放。在相同的RGB=(255255,2)示例上使用新的K导致更合理的RGBW=(255255,0,2)。

综合起来:

M = max(Ri,Gi,Bi)
m = min(Ri,Gi,Bi)
Wo = if (m/M < 0.5) use ( (m*M) / (M-m) ) else M 
K = (Wo + M) / M
Ro = floor[ ( K * Ri ) - Wo ]
Go = floor[ ( K * Gi ) - Wo ]
Bo = floor[ ( K * Bi ) - Wo ]

有点晚了,但令人惊讶的是,这似乎仍然是一件很难找到工具的事情。

此回购可以为您完成这项工作:https://github.com/iamh2o/rgbw_colorspace_converter/

我和一个朋友一起写了这个模块,这样"颜色"对象就可以通过几个颜色系统实例化,并且对象可以向它支持的所有其他颜色系统进行翻译——这是经过大量研究(一个关键部分是https://www.neltnerlabs.com/saikoled/how-to-convert-from-hsi-to-rgb-white),我们最终确定了[HSI/HSL/HVS/RRGB/HEX]->RGBW转换。

有很多包解决了一般的色彩空间问题,但RGBW的情况似乎非常特定于物理照明/LED,不适用于数字显示器,RGBW没有包含在我看过的任何模块中。

这个模块的杀手级功能是,可以根据您的需求(在不同的颜色系统中创建它),在多个颜色系统中操作您实例化的颜色对象,并且它将保持到其他空间的所有转换都是最新的-而且它非常快,我们还没有将其作为帧速率限制组件。

因此,像这样的东西将是一个穿过完全明亮、完全饱和的彩虹的循环(注意RGB和HSV代码是如何远不适合程序操作的):

from rgbw_colorspace_converter.colors.converters import RGB
color = RGB(255,0,0)
ctr = 0
while ctr < 10:
color.hsv_h += .1
print(f"HSV:{color.hsv}  RGB:{color.rgb}  HSI:{color.hsi} HEX:{color.hex}")
ctr += 1
# "H" in hsv is actually expressed in 360 degrees, and it is cylindrical. We've normalized it to being between 0-1 (so H=0=H=1 - both are red)
HSV:(0.0, 1.0, 1.0)  RGB:(255, 0, 0)  HSI:(0.0, 1.0, 0.33333) HEX:#ff0000
HSV:(0.1, 1.0, 1.0)  RGB:(255, 153, 0)  HSI:(36.0, 1.0, 0.533328) HEX:#ff9900
HSV:(0.2, 1.0, 1.0)  RGB:(203, 255, 0)  HSI:(72.23529411764707, 1.0, 0.5986868235294117) HEX:#cbff00
HSV:(0.3, 1.0, 1.0)  RGB:(51, 255, 0)  HSI:(108.0, 1.0, 0.399996) HEX:#33ff00
HSV:(0.4, 1.0, 1.0)  RGB:(0, 255, 102)  HSI:(144.0, 1.0, 0.46666199999999997) HEX:#00ff66
HSV:(0.5, 1.0, 1.0)  RGB:(0, 255, 255)  HSI:(180.0, 1.0, 0.66666) HEX:#00ffff
HSV:(0.6, 1.0, 1.0)  RGB:(0, 102, 255)  HSI:(216.0, 1.0, 0.46666199999999997) HEX:#0066ff
HSV:(0.7, 1.0, 1.0)  RGB:(50, 0, 255)  HSI:(251.76470588235296, 1.0, 0.39868882352941176) HEX:#3200ff
HSV:(0.8, 1.0, 1.0)  RGB:(204, 0, 255)  HSI:(288.0, 1.0, 0.599994) HEX:#cc00ff
HSV:(0.9, 1.0, 1.0)  RGB:(255, 0, 152)  HSI:(324.2352941176471, 1.0, 0.5320208235294118) HEX:#ff0098
HSV:(1.0, 1.0, 1.0)  RGB:(255, 0, 0)  HSI:(0.0, 1.0, 0.33333) HEX:#ff0000

我知道这是一个相当古老的问题,但我正在研究RGB->RGBW算法,发现这篇文章虽然不是答案,但可能会有所帮助?

http://web.archive.org/web/20101008153429/http://www.nouvoyance.com:80/files/pdf/Adding-a-White.pdf

在这方面,他们建议RGB->RGBW的一种转换是简单地从min(R,G,B)创建W。

  • R->R
  • G->G
  • B->B
  • W->最小值(R、G、B)

相反(对于您的场景),只需扔掉W.

  • R->R
  • G->G
  • B->B
  • W->空

最新更新