Интерполяция цвета
- Войдите на сайт для отправки комментариев
Сб, 19/12/2020 - 18:52
Здравствуйте, делаю подсветку на адресной ленте - плавное переливание светодиодов. Использую библиотеку FastLed
#define NUM_LEDS 1 #include "FastLED.h" #include "lib8tion.h" #define PIN 3 CRGB leds[NUM_LEDS]; CHSV targetColor[NUM_LEDS]; void setup() { for (uint16_t i = 0; i < NUM_LEDS; i++) { targetColor[i] = CHSV(random(0, 255), random(0, 255), random(0, 255)); } Serial.begin(9600); randomSeed(2648469515618); // read noise from component for set rnd seed FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip ); FastLED.setBrightness(255); pinMode(PIN, OUTPUT); } CHSV RgbToHsv(CRGB rgb) { CHSV hsv; unsigned char rgbMin, rgbMax; rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b); rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b); hsv.v = rgbMax; if (hsv.v == 0) { hsv.h = 0; hsv.s = 0; return hsv; } hsv.s = 255 * long(rgbMax - rgbMin) / hsv.v; if (hsv.s == 0) { hsv.h = 0; return hsv; } if (rgbMax == rgb.r) hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin); else if (rgbMax == rgb.g) hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin); else hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin); return hsv; } CHSV InterpolateColor(CHSV a, CHSV b) { float ah = a.h; float as = a.s; float av = a.v; float bh = b.h; float bs = b.s; float bv = b.v; ah = ah + (bh - ah) * 0.3; as = as + (bs - as) * 0.3; av = av + (bv - av) * 0.3; return CHSV(ah, as, av); } void loop() { for (uint16_t i = 0; i < NUM_LEDS; i++) { CHSV col = RgbToHsv(leds[i]); col = InterpolateColor(col, targetColor[i]); Serial.print(col.h); Serial.print(" "); Serial.print(col.s); Serial.print(" "); Serial.println(col.v); Serial.print(targetColor[i].h); Serial.print(" "); Serial.print(targetColor[i].s); Serial.print(" "); Serial.println(targetColor[i].v); if ( abs(col.h - targetColor[i].h) < 4 && abs(col.s - targetColor[i].s) < 4 && abs(col.v - targetColor[i].v) < 4) { targetColor[i] = CHSV(random(0, 255), random(0, 255), random(0, 255)); } leds[i] = col; } delay(10); FastLED.show(); }
В один момент цвета перестают меняться.
Проверил ту же формулу на числе uint8_t все работает. В чем проблема?
Какую формулу?
Функция считает по формуле a+(b-a) * t где 0<= t <=1
Так а что не работает?
В один момент цвета перестают меняться.
Проверил ту же формулу на числе uint8_t все работает. В чем проблема?
Есть цвет пикселя - случайный. Есть цвет пикселя который нам нужен - тоже случайный. Оно должно плавно переливаться из цвета который уже имеется в тот, который нам нужен. Цвет несколько раз меняется, а потом перестает, не дойдя до нужного значения. Не понимаю почему
В fastled уже есть всё необходимое. Не надо ничего самому изобретать.
В fastled уже есть всё необходимое. Не надо ничего самому изобретать.
Я нашел функцию lerp8by8, но не понял как ей дать значение frac меньше 1. Покажите пример если не сложно
Цвет несколько раз меняется, а потом перестает, не дойдя до нужного значения. Не понимаю почему
Программа работает в точности так, как она написана.
Расставьте комментарии в тексте. Может, сами найдете проблему, а может, мы найдем, где код не совпадает с комментариями. Гадать, как должно быть, и прочему в коде написано именно так, а не иначе (не зная, как должно быть), - дело неблагодарное.
Переведите цвет в CHS и вообще ничего делать не надо
Программа работает в точности так, как она написана.
Да, с простым числом все работает так, как оно и должно. Но с цветом что то не так, хотя действия те же самые.
Программа всегда работает так, как написана.
1. Как должна работать программа?
2. Как она на самом деле работает?
3. Чем 1 отличается от 2?
Я не в теме FastLed. Может поэтому для меня не очевидно, почему в строке 077 вы присваиваете через преобразование, а в строке 101 без преобразования.
Фастлед в одну сторону сам умеет конвертить цветовые пространства.
Программа всегда работает так, как написана.
1. Как должна работать программа?
2. Как она на самом деле работает?
3. Чем 1 отличается от 2?
1. должна плавно менять цвет н-ого числа светодиодов по hue до требуемого
2. плавно меняет цвет светодиода, но не доходит до требуемого
3. цвет не доходит до требуемого значения
Я не в теме FastLed. Может поэтому для меня не очевидно, почему в строке 077 вы присваиваете через преобразование, а в строке 101 без преобразования.
077: я не нашел как из rgb сделать hsv цвет в библиотеке fastled.
101: если переменной с типом CRGB присваивать переменную с типом CHSV то все работает, но не наоборот
Константин, несколько вопросов по коду
1. Если у вас вся работа с цветом в CHSV, зачем начальный цвет в RGB ?
задайте сразу весь цвет в CHSV и сложная конверсия будет не нужна. Я не вникал в детали вашей процедуры RgbToHsv() - но в ней легко может быть ошибка. А задав цвет в CHSV вы заведомо исключите этот источник проблем.
2. Теперь интерполяция цвета
зачем компоненты цвета имеют тип float? - они же целые
И почему в вашем понимании интерполяция - это именно 0.3 от разницы компонентов цвета? - логичнее было бы 0.5
Если же вы хотите интерполяцию за несколько шагов, то нужно разделить разность величин ah и bh на число отрезков, равное числу шагов... А число 0.3 - это ни к селу ни к городу...
Константин, несколько вопросов по коду
1. Если у вас вся работа с цветом в CHSV, зачем начальный цвет в RGB ?
1. При инициализации ленты
FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
в качестве массива светодиодов принимает только массив с типом CRGB
RgbToHsv() - но в ней легко может быть ошибка
Сомневаюсь. Использую этот фрагмент где только можно - все работает.
зачем компоненты цвета имеют тип float? - они же целые
если при расчетах, как я понимаю, использовать целые числа, то оно будет округляться в ближайшую сторону. А если использовать float, то округление произойдет в конце и потерь точности будет меньше. Думал из-за этого не работает, но нет.
И почему в вашем понимании интерполяция - это именно 0.3 от разницы компонентов цвета? - логичнее было бы 0.5
так переливание выглядит плавнее.
Если же вы хотите интерполяцию за несколько шагов, то нужно разделить разность величин ah и bh на число отрезков, равное числу шагов... А число 0.3 - это ни к селу ни к городу...
Попробую если заработает
Константин, везде по исходнику, где успользуется цвет в том или ином виде, вставьте комментарии, какая цветовая модель используется.
Потому как есть подозрение, что Вы где-то в процессе вычислений путаете RGB и HSV.
И еще, Вы уверены, что (106, 16, 90) и (158, 19, 232) - это разные цвета, а не один и тот же в разных цветовых пространствах?
Надо ещё учитывать, что в HSV Fastled-а спектр на байте повторяется.
Константин, везде по исходнику, где успользуется цвет в том или ином виде, вставьте комментарии, какая цветовая модель используется.
Потому как есть подозрение, что Вы где-то в процессе вычислений путаете RGB и HSV.
И еще, Вы уверены, что (106, 16, 90) и (158, 19, 232) - это разные цвета, а не один и тот же в разных цветовых пространствах?
Проверил, все модели правильные, а при интерполяции rgb конвертируется в hsv
Да, это разные цвета.
Я бы еще распечатал значения :
- col и leds после строки 77,
- значения (разности) передаваемые в функцию abs() в строках 94-96,
- значения targetColor после строки 98,
- col и leds после строки 101.
Автор пытается Значение хранящиеся в RGB преобразовывать в HSV, интерполировть к значению хранящемуся в HSV и снова преобразовывать из HSV в RGB для сохранения. При этом преобразование RGB -> HSV -> RGB приводит к существенно другому RGB.