Преобразование цвета RGBW в стандартное представление RGB/HSB
Я строю интерфейс для управления освещением в системе домашней автоматизации. Мне удалось управлять стандартным включением / выключением и регулировкой яркости света для разных поставщиков без особых проблем, но теперь я застрял с проблемой, связанной с RGB подсветкой.
Источник света, которым я сейчас пользуюсь, - это светодиодная полоса RGBW - в частности, я работаю с недорогой лампой RGBW: источник света состоит из четырех светодиодов, и каждый светодиод можно контролировать индивидуально.
Чтобы быть более понятным - я работаю над кодом C#, который должен восстановить текущий выбранный цвет и отобразить его в пользовательском интерфейсе, а также дать пользователю возможность указать новый цвет для источника света. Для установки цвета и его получения я должен использовать поставщика команд, который позволяет мне отправлять и получать команды через веб-сервис.
Поставщик работает с цветами RGBW - используются четыре компонента: красный, зеленый, синий и белый. Чтобы представить текущий цвет света на моем интерфейсе, я хотел бы перевести цвет RGBW, возвращаемый службой, в более стандартную схему RGB/HSB.
Поиск в Интернете, единственная ссылка на преобразование цветов, которую я нашел (исключая пример с ++ для преобразования rgb в rgbw, который, по моему мнению, должен иметь серьезную ошибку), - это статья, в которой показано преобразование из HSI в RGBW, которое обратное тому, что мне было нужно: ссылка здесь
Я ищу некоторое представление о том, как я могу достичь этого преобразования (или простое объяснение, почему это невозможно). Насколько я понимаю, преобразование из RGB в RGBW является произвольным - одно значение RGB может быть представлено в виде нескольких значений RGBW, но обратное преобразование должно быть однозначным. Также обратите внимание, что хотя я использую C#, не стесняйтесь ссылаться на алгоритмы и на другом языке - язык не проблема, проблема в том, что я не знаю математики для преобразования цвета.
4 ответа
Как конвертировать RGB в RGBW описано в пункте 2.1 следующей статьи
http://www.mirlab.org/conference_papers/International_Conference/ICASSP%202014/papers/p1214-lee.pdf
Думайте о своих светодиодах как об огромном пикселе. Ответ Оливера использует Wo = min(Ri,Gi,Bi), что вычислительно дешево и просто работает. В этом документе объясняются другие альтернативы для минимизации энергопотребления, что хорошо для проекта домашней автоматизации. Я также работаю над проектом домашней автоматизации с использованием светодиодов OpenHAB, Arduino и RGBW, и, с одной стороны, предложенная альтернатива будет хорошей, с другой стороны, огромная 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, исправьте значение Wo с помощью правильного Qw, и вы будете удивлены тем, что простое решение без исправления - это не то, что можно было бы ожидать, что другие ответы не так сильно меняются. Проверьте бумагу на результаты искажения цвета, я полагаю, что если вы не исправите значения RGB, у вас будут размытые цвета.
Я просматривал ответ, предложенный Роберто, но во многих случаях цвета казались более тусклыми и ненасыщенными. Если взять пример RGB = (255,255,2), получим RGBW = (128,128,1,2).
Если копать дальше, кажется, что в статье Чула Ли есть ошибка в уравнении для К. Уравнение, которое взято из статьи Лили Ван ("Компромисс между яркостью и цветом в дисплеях RGBW для использования в мобильных телефонах") на самом деле:
K = (Wo + M)/M
Обратите внимание, что это заглавная M, а не строчная m. Учитывая это изменение, вам также не понадобится Q, поскольку он правильно масштабируется по своей природе. Использование нового K в том же примере RGB = (255,255,2) приводит к гораздо более разумному 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 ]
Я знаю, что это довольно старый вопрос, но я смотрю на алгоритм RGB-> RGBW и нашел эту статью, которая - хотя и не ответ - может помочь?
http://web.archive.org/web/20101008153429/http://www.nouvoyance.com:80/files/pdf/Adding-a-White.pdf
В этом они предлагают одно преобразование для RGB-> RGBW просто создать W из min (R, G, B).
- R -> R
- G -> G
- B -> B
- W -> мин (R, G, B)
Обратной стороной этого (для вашего сценария) будет просто выбросить W.
- R -> R
- G -> G
- B -> B
- W -> ноль
Немного поздно, но все же кажется, что найти инструменты для этого на удивление непросто.
Это репо может сделать эту работу за вас : 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 довольно специфичен для физического освещения / светодиодов и не применим к цифровым дисплеям, 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