7

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

我目前使用的灯是 RGBW LED 灯条 - 具体来说,我正在使用低成本的 RGBW 灯:灯由四个 LED 组成,每个 LED 都可以单独控制。

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

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

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

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

4

4 回答 4

6

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

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

将您的 LED 视为一个巨大的像素。Oliver 的答案使用 Wo = min(Ri,Gi,Bi),计算成本低且有效。本文介绍了其他可最大限度降低功耗的替代方案,这对家庭自动化项目有什么好处。我还在一个带有 OpenHAB、Arduino 和 RGBW LED 的家庭自动化项目中,一方面论文提出的替代方案会很好,另一方面,一个巨大的 LUT 将无法正常工作并转换 arduino 8 上的所有值。我建议您尝试使用论文中引用的不那么节能的技术来校正 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 值,你最终会得到一些褪色的颜色。

于 2015-01-07T21:52:57.110 回答
5

我一直在查看 Roberto 建议的答案,但在许多情况下,颜色似乎更暗且饱和度不足。以 RGB = (255,255,2) 为例,RGBW = (128,128,1,2)。

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

K = (Wo + M)/M

请注意,它是大写的 M,而不是小写的 m。鉴于此更改,您也不需要 Q,因为它天生就可以正确扩展。在相同的 RGB = (255,255,2) 示例上使用新的 K 会导致更合理的 RGBW = (255,255,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 ]
于 2019-12-31T00:01:49.053 回答
1

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

这个 repo 可以为你完成这项工作https ://github.com/iamh2o/rgbw_colorspace_converter/

我和一个朋友一起写了这个模块,这样“颜色”对象可以通过几个颜色系统来实例化,并且该对象可以输出到它支持的所有其他颜色系统的翻译——经过大量研究(一个关键部分是https://www.neltnerlabs.com/saikoled/how-to-convert-from-hsi-to-rgb-white),我们终于搞定了 [HSI/HSL/HSV/RGB/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

于 2021-08-18T07:57:06.227 回答
0

我知道这是一个相当老的问题,但我正在查看 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
  • 乙->乙
  • W -> min(R, G, B)

与此相反(对于您的场景)将只是扔掉 W.

  • R -> R
  • G -> G
  • 乙->乙
  • W -> 空
于 2014-11-17T14:04:13.130 回答