Я создаю демо из 20 шариков, подпрыгивающих друг от друга, с фоном, заполненным сплошным цветом. Цвет для каждого шара выбирается случайным образом randint(0, 255)
для каждого компонента кортежа R, G, B.
Проблема в том, что некоторые шары имеют цвет, очень похожий на фон, что затрудняет их просмотр. Я хотел бы избежать этого, либо путем прокрутки другого цвета, если выбранный цвет слишком похож (в пределах заданного порога), либо путем удаления его от цвета фона.
Как рассчитать индекс сходства для использования в качестве порога? Или как преобразовать цвет, скажем, в менее синий ?
Очевидный отказ от ответственности: я ничего не знаю о теории цвета, поэтому я не знаю, существуют ли вышеупомянутые понятия!
Я пишу на python, но я ищу концепции и стратегии, так что псевдокод - это хорошо (или просто теория).
РЕДАКТИРОВАТЬ:
Чтобы уточнить несколько моментов:
Каждый шар имеет свой случайный цвет. Я бы хотел, чтобы они оставались как можно более случайными и максимально изучали цветовое пространство (будь то RGB или HSV,
pygame
для определения цвета принимаются оба формата)Я просто хотел бы избежать того, чтобы каждый цвет был "слишком близко" к фону. Проблема не только в оттенке: у меня все в порядке с голубым шаром на темно-синем фоне (или «голубым» на синем и т. Д.)
На данный момент мне все равно, будет ли шар цвета, аналогичного (или даже идентичного) другому шару. Избежать этого - бонус, но это незначительная проблема.
Цвет фона - это постоянный один цвет RGB. Пока я использую «базовый» синий
(0, 0, 255)
, но я не согласен с этим. Поэтому считайте фон произвольного цвета (с произвольным оттенком, яркостью, насыщенностью и т. Д.).
EDIT2:
Версия TL, DR: просто дайте возможность создавать X случайных цветов, чтобы ни один не "слишком сильно" исчезал на фоне произвольного (но единственного и постоянного) цвета
Ответы:
Вы можете использовать тот факт, что цвета составляют (трехмерное) цветовое пространство и рассчитать расстояние в этом цветовом пространстве. Затем вам нужно определить метрику в этом цветовом пространстве, чтобы найти расстояние между двумя цветами.
Например, расстояние в евклидовом пространстве между двумя точками x = (x1, x2, x3) и y = (y1, y2, y3) определяется как d (x, y) = sqrt ((y1-x1) * (y1- x1) + (y2-x2) * (y2-x2) + (y3-x3) * (y3-x3)).
Теперь вы можете рассчитать расстояние между цветом шариков и цветом фона, а если оно слишком мало, создайте новый случайный цвет и протестируйте снова.
Вы обнаружите, что ни RGB, ни даже HSV не являются хорошими цветовыми пространствами для этой задачи. Википедия статья о разнице цвета использует L б цветового пространства и дает несколько возможных метрик.
Существует также обсуждение стека и потока по этой теме.
источник
Страница стандартов доступности веб-сайтов Организации Объединенных Наций ( http://www.un.org/webaccessibility/1_visual/13_colourcontrast.shtml ) действительно указывает стандарт для обеспечения надлежащего контраста текста на веб-сайтах, учитывая, что некоторые пользователи имеют дальтонизм. Это может быть особенно важно для вас, так как некоторые из ваших пользователей также могут быть дальтониками (было бы трудно отличить красный шар от зеленого фона, если они имеют одинаковую яркость).
Страница ООН указывает на анализатор коэффициента цветовой контрастности Juicy Studios по адресу ( http://juicystudio.com/services/luminositycontrastratio.php#specify ), в котором говорится, что текст на фоне должен иметь контрастность 4,5: 1, за исключением того, что я считаю, что похоже на ваш случай:
Теперь, какова контрастность? Далее по гиперссылкам (это весело!) Мы попадаем на страницу W3, которая определяет контрастность как:
Где L1 и L2 - относительные яркости цветов. L1 - более яркий цвет, L2 - менее яркий цвет. Опять же, мы переходим по ссылке на ту же страницу W3, которая указывает:
ПРИМЕЧАНИЕ : символ каретки ^ выше относится к возведению в степень (x²)
И у нас есть довольно хорошая основа для алгоритма контраста (это дружелюбно к дальтоникам!)
источник
^
, я бы никогда не подумал о побитовом XOR в этом контексте. (или в любом^
другом . C'mon C phreaks, это де-факто символ для возведения в степень в псевдокодах (хотя на самом деле очень немногие языки используют его ... в**
Использование значений RGB путем генерации случайного
0-255
значения для каждого компонента может не только создавать цвета, похожие на фон, но также может привести к очень похожим цветам для шаров.Я бы, вероятно, выбрал менее случайный подход и создал бы цвета, которые гарантированно будут отличаться. Вы можете создать цвет для каждого ~ 32 градусов в диапазоне оттенков и чередовать яркость или насыщенность (используйте цветовую модель HSV вместо RGB).
Так что-то вроде этого:
который создаст 20 цветов, красиво распределенных. Это предполагает, что вы используете целочисленную математику, поэтому
i = 0
иi = 1
создаст то же значение оттенка.Конечно, это не слишком хорошо масштабируется ... если у вас есть 100 значений цвета для создания, расстояние между оттенками может быть недостаточным, и вы снова получите похожие цвета. В этом случае вы также можете изменить значение
V
(яркость).Я не знаю, на что похож ваш цвет фона, но HSV также облегчает сравнение цветов (просто сравните 3 компонента и не забывайте, что HUE является круглым (0 == 360)).
ОБНОВИТЬ:
Поскольку я на самом деле не ответил на ваш вопрос, а предложил другой подход, вот как может выглядеть алгоритм для произвольного фона и совершенно случайных цветных шаров (это метод грубой силы, но он должен хорошо работать для вашего варианта использования):
источник
V
(так как текущий алгоритм не меняет этого).Так как вы упомянули, что у вас есть постоянный фон, цвет шаров может быть случайным, но они должны падать на определенных диапазонах, которые по-прежнему дополняют фон.
Основы. Прежде чем мы это сделаем, вам нужно знать основы. Рассмотрим следующие цвета:
Смесь цветов RGB [(0..255), (0..255), (0..255)] создает новые цвета, как указано выше.
Вычисление отрицательных цветов Вычисление отрицательных цветов аналогично преобразованию красного в голубой, зеленого в фиолетовый и синего в желтый.
Дополнительный цвет
В соответствии со ссылкой на вычисление дополнительных цветов: http://serennu.com/colour/rgbtohsl.php
О HSL
HSL выражает цвета с точки зрения их оттенка, насыщенности и яркости, давая число для каждого из этих трех атрибутов цвета.
Оттенок - это позиция цвета на цветовом круге, выраженная в градусах от 0 ° до 359 °, представляющая 360 ° колеса; 0 ° - красный, 180 ° - красный, противоположный голубой, и так далее.
Насыщенность - это интенсивность цвета, насколько он тусклый или яркий. Чем ниже насыщенность, тем более тусклый (серый) цвет выглядит. Это выражается в процентах, 100% - полное насыщение, самый яркий и 0% - отсутствие насыщенности, серый.
Легкость - это то, насколько светлый цвет. Немного отличается от насыщенности. Чем больше белого цвета, тем выше его значение Легкости, чем больше черного, тем ниже его Легкость. Таким образом, 100% Lightness превращает цвет в белый, 0% Lightness превращает цвет в черный, и «чистый» цвет будет 50% Lightness.
Легче увидеть разницу между Насыщенностью и Легкостью, чем объяснить это. Если вы хотите прояснить ситуацию, попробуйте просмотреть варианты «Яркость» и «Насыщенность» на странице калькулятора цвета, выбрав в качестве начального цвета довольно яркий цвет.
Таким образом, запись HSL выглядит следующим образом, давая значения Hue, Saturation и Lightness в следующем порядке: t
Красный: 0 ° 100% 50% Бледно-розовый: 0 ° 100% 90% Голубой: 180 ° 100% 50% Вот шаги:
Преобразуйте ваш цвет в HSL.
Измените значение оттенка на противоположное значение оттенка (например, если ваш оттенок равен 50 °, противоположный будет под углом 230 ° на колесе - на 180 ° дальше вокруг).
Оставьте значения насыщенности и легкости такими, какими они были.
Преобразуйте это новое значение HSL обратно в исходное обозначение цвета (RGB или что-то еще).
Такие сайты, как EasyRGB.com, могут сделать для вас общее преобразование из RGB в HSL или наоборот.
Пример программирования сделан на PHP по ссылке
Преобразование из RGB в HSL
Значение выше синего цвета # 0000FF rgb (0,0,255) может быть представлено как красный шестнадцатеричный 00 + зеленый шестнадцатеричный 00 + синий шестнадцатеричный FF
Он также может быть представлен как красное десятичное число 0 + зеленое десятичное число 0 + голубое десятичное число 255
Теперь вставьте эти значения в процедуру rgb2hsl. Ниже приведена моя PHP-версия универсального кода EasyRGB.com для этого преобразования:
Входные данные - $ var_r, $ var_g и $ var_b сверху. Выходные данные - эквивалент HSL как $ h, $ s и $ l - они снова выражаются в виде долей 1, как и входные значения
Итак, теперь у нас есть цвет как значение HSL в переменных $ h, $ s и $ l. Эти три выходные переменные на данном этапе снова представлены как доли от 1, а не как градусы и проценты. Так, например, голубой (180 ° 100% 50%) будет выглядеть как $ h = 0,5, $ s = 1 и $ l = 0,5.
Затем найдите значение противоположного оттенка, то есть того, который находится на расстоянии 180 ° или 0,5 (я уверен, у математиков есть более элегантный способ обозначить это, но):
Рассчитайте противоположный оттенок, $ h2
Значение HSL дополнительного цвета теперь составляет $ h2, $ s, $ l. Итак, мы готовы преобразовать это обратно в RGB (снова моя PHP-версия формулы EasyRGB.com). Обратите внимание, что форматы ввода и вывода на этот раз отличаются, см. Мои комментарии в верхней части кода:
Входные данные - это значение HSL дополнительного цвета, хранящееся в $ h2, $ s, $ l в виде дробей 1 Выходные данные - это RGB в обычном формате 255 255 255, хранящиеся в $ r, $ g, $ b. Оттенок преобразуется с использованием функции hue_2_rgb, показанной в конце этого кода
И после этой процедуры у нас наконец-то есть $ r, $ g и $ b в формате 255 255 255 (RGB), которые мы можем преобразовать в шесть цифр шестнадцатеричного числа:
$ rgbhex - это наш ответ - дополнительный цвет в гексе.
Так как ваш цвет фона синий или 0,0255, HSL
Оттенок (H): 240 градусов / Насыщенность (S): 100% / Легкость (L): 4,9%
противоположность 240 - 60 по кругу, затем преобразование обратно в RGB дает значение # 181800
источник
Я хотел бы расширить идею @ ashes999 по созданию набросков.
Мой код будет как Python, как я могу изо всех сил (я никогда не писал строки Python в моей жизни, но я просмотрел книгу один или два раза).
Это может выглядеть не очень красиво и не совсем идеально для производственного кода, но этого должно быть достаточно для быстрого исправления. Я не тестировал код, так как у меня точно нет программы «шарики подпрыгивая вокруг экрана», которую я мог бы изуродовать для проверки.
Редактировать:
Увидев действующий код, ситуация перевернулась с ног на голову, поэтому вместо этого я предлагаю это решение.
Заменить строки 276-284 следующим текстом:
В этой новой упрощенной версии фабричный метод выплевывает шары, а специализированный метод генерирует цвета. Генератор цвета проверяет случайно сгенерированный цвет, чтобы определить, находится ли он в пределах определенного диапазона близости к цвету фона. Цвет считается слишком близким к цвету BG, если все три его цветовых канала находятся в пределах
leeway
любой стороны BG. Таким образом, если длина пути равна 0, только цвета, которые точно соответствуют BG, отклоняются. Я выбрал 5 по умолчанию, который отказывается от цвета BG и 5 цветов по обе стороны. Так как цвет BG белый, я не уверен, что он откажется от черного, потому что цифры закручиваются. Этого можно избежать, используя функции min и max, но я оставил их для краткости.источник
pygame
в качестве библиотеки. Без лишних слов, только базовые преобразования RGB-HSV-CYMK: pygame.org/docs/ref/color.htmllerp
функция в моем ответе - это все, что нужно сделать. (Лерп означает «Линейная интерполяция»).print
отличаетесь, потому что вы используете Python 3, а я все еще в Python 2. И я не уверен,pygame
был ли еще портирован на Py3. Итог: не беспокойтесь :) Вопрос о цветах, вам не нужны настоящие шары, подпрыгивающие :)Для формата RGB это, кажется, работает достаточно хорошо и тривиально:
iversity_score = (abs (r1 - r2) + abs (g1 - g2) + abs (b1 - b2)) / 765,0
Это даст вам оценку от 0,0 до 1,0. Чем ниже, тем сложнее различить два цвета.
Это должно быть очевидно, но ради полноты: значения r, g, b должны быть сначала приведены к числу с плавающей запятой, и предполагается, что их максимальное значение равно 255.
источник