Равномерная случайная выборка CIELUV для цветов RGB

Выбрать случайный цвет на компьютере сложнее, чем я думал.

Наивный способ равномерной случайной выборки 0..255 для R,G,B будет иметь тенденцию рисовать много одинаковых зеленых цветов. Было бы разумно брать сэмплы из перцептуально однородного пространства, такого как CIELUV.

Простой способ сделать это - взять образец L,u,v на обычной сетке и убедиться, что цветное твердое тело содержится в границах (я видел разные границы для этого). Если образец выходит за пределы встроенного твердого тела RGB (проверенного путем сопоставления его XYZ, затем RGB), отклоните его и выполните выборку снова. Вы можете согласиться на неуклюжий, но гарантированно завершенный "спасательный" выбор (как и наивная процедура), если откажетесь от более чем некоторого произвольного порогового числа раз.

Я считаю, что проверка того, находится ли образец в пределах RGB, должна быть обязательно проверена на особый случай черного цвета (некоторые реализации в конечном итоге молчат о делении на ноль). Если L=0 и либо u!=0, либо v!=0, тогда образец необходимо отклонить, иначе вы закончите передискретизацию плоскости L=0 в пространстве Luv.

Есть ли у этой процедуры явный недостаток? Похоже, это сработало, но я заметил, что становлюсь черным чаще, чем я думал, что имело смысл, пока я не подумал о том, что происходило в этом случае. Может ли кто-нибудь указать мне правильные границы сетки CIELUV, чтобы убедиться, что я заключаю твердое тело RGB?

Полезная ссылка для тех, кто этого не знает:https://www.easyrgb.com/en/math.php

2 ответа

Ключевая проблема заключается в том, что вам нужны границы для отклонения выборок, выходящих за пределы RGB. Мне удалось найти здесь это сработало (хорошая демонстрация на странице, API предоставляет удобные функции):https://www.hsluv.org/

Несколько вещей, которые я заметил с равномерной выборкой CIELUV в RGB:

  • большинство цветов - зеленый и фиолетовый (это верно независимо от границ RGB)
  • вам сложно выбрать то, что мы считаем желтым (очень маленький объем высокой яркости, пространство с высокой цветностью)

Я реализовал различные стратегии, которые фокусируются на выборке оттенков (что действительно то, что мы хотим, когда мы думаем о «выборке цветов») путем взвешивания в соответствии с максимальным количеством цветностей при этой яркости. Это позволяет легче уловить такие цвета, как хроматические светло-желтые, и позволяет избежать передискретизации зеленого и пурпурного. Вы можете увидеть эти методы в действиях здесь (выберите «рандомизировать цвета»):

https://www.mysticsymbolic.art/

Источник для рандомизаторов цвета здесь:https://github.com/mittimithai/mystic-symbolic/blob/chromacorners/lib/random-colors.ts

Хорошо, хотя вы не показываете код, который используете для генерации случайных чисел, а затем применяете их к цветовому пространству CIELUV, я собираюсь предположить, что вы создаете случайное число 0,0–100,0 из генератора случайных чисел, а затем просто присвоить его L* .

Это, скорее всего, даст вам много черных или очень темных результатов.

Позволь мне объяснить

L* из L* U * v * не является линейным , как к свету. Y CIEXYZ линейен относительно света. L* - это легкость восприятия, поэтому к Y применяется экспоненциальная кривая, чтобы сделать его линейным по отношению к восприятию, но затем нелинейным по отношению к свету.

ПОПРОБУЙ ЭТО

Чтобы получить L* со случайным значением 0—100:

  • Сгенерировать случайное число от 0,0 до 1,0
  • Затем примените показатель степени 0,42.
  • Затем умножьте на 100, чтобы получить L*
          Lstar = Math.pow(Math.random(), 0.42) * 100;

Это берет ваше случайное число, которое представляет свет, и применяет кривую мощности, которая имитирует человеческое восприятие легкости.

УФ-цвет

Что касается значений u и v , вы, вероятно, можете просто оставить их как линейные случайные числа. Ограничьте u примерно -84 и +176, а v примерно -132,5 и +107,5

          Urnd = (Math.random() - 0.5521) * 240;
    Vrnd = (Math.random() - 0.3231) * 260;

Полярный цвет

Может быть интересно преобразовать uv в LCh LUV или LshLUV

Для оттенка это, вероятно, так же просто, как H = Math.random() * 360
Для цветов с ограничением 0–178: C = Math.random() * 178

Следующий вопрос: стоит ли искать цветность? Или насыщенность? CIELUV может предоставлять либо Hue, либо Sat, но для прямой генерации случайных цветов кажется, что цветность немного лучше.

И, конечно же, эти простые примеры не предотвращают перерасхода, поэтому они окрашивают значения, которые необходимо проверить, чтобы убедиться, являются ли они допустимым sRGB или нет. Есть несколько вещей, которые можно сделать, чтобы ограничить сгенерированные значения допустимыми цветами, но цель здесь заключалась в том, чтобы получить лучшее распределение без лишних результатов черного / темного.

Пожалуйста, дайте мне знать о любых вопросах.

Другие вопросы по тегам