Сопоставление значений hex / hsl с цветовым диапазоном

Учитывая значение hex / rgb / hsl, как я могу поместить это значение в настраиваемый диапазон, скажем, из 11 основных цветов, таких как красный, синий и т. Д.

Лучшее, что я мог сделать, это сопоставить на глаз диапазон оттенков в hsl, но насыщенность и яркость могут изменить воспринимаемый цвет.

Я ищу алгоритм, который бы соответствовал указанным значениям в цветовом диапазоне.


person user681148    schedule 17.07.2019    source источник
comment
Ну, просто очень общая мысль об этом: если значение канала 50 (в RGB или другом) находится в диапазоне 0 - 255, это значение находится на 0.1961 от полного диапазона. Вы также можете объединить все каналы, чтобы получить такое значение. Теперь представьте, что вы сопоставляете свои основные цвета с диапазонами от 0 до 1, вы можете просто сопоставить свой 0.1961 с одним из этих цветов.   -  person bkis    schedule 17.07.2019


Ответы (1)


Если вы говорите только об 11 основных цветах (например, красный, оранжевый, желтый, зеленый, голубой, синий, фиолетовый, пурпурный, черный, белый, серый), я бы сказал, что вы уже там. Сопоставление оттенков - это все, что вам нужно для сопоставления самих цветов, если они находятся в разумном диапазоне от S и L.

На мой взгляд, любой L больше 95ish достаточно близок к белому, а любой L меньше 5ish достаточно близко к черному.

Затем, если ваш S меньше, скажем, 10, ваши варианты - черный, серый и белый, в зависимости от L, и вы даже можете использовать те же правила. Черный ‹= 5, Белый> = 95, иначе серый.

Чтобы сопоставить оттенок, используя мой пример списка цветов, вы не можете использовать однородный диапазон, поскольку различия между цветами на красном конце спектра намного меньше, чем на голубом конце. Вы можете определить их вручную или получить неплохие результаты, используя логистическую функцию.


TL: DR; Математика, наверное, излишняя.

Я бы просто посмотрел на оттенок, потому что создавать формулу для этого не нужно и сложно.

С учетом сказанного, вот моя попытка логистической функции, которая соответствует восприятию общих цветов.

 formula

Вы можете настроить значение k по своему усмотрению. Я думаю, что 1.1 дает разумный разброс (хотя я пробовал только пару значений). Число 8 дает вам количество значений, которые вы хотели бы получить из этой функции. Итак, поскольку у нас есть 8 разных цветов, которые мы пытаемся сопоставить (помимо черного, белого и серого), я использовал 8.

3 сдвигает домен вправо на 3 единицы. Я использовал 3, потому что это половина области, которую мы собираемся использовать для этой функции (3 единицы по обе стороны от средней точки).

Чтобы уточнить, это последняя функция:

 final

Для x эта формула настроена так, чтобы иметь минимум 0 и максимум 6, и он будет начинаться с голубого. Итак, если 0 <= f(x) < 1, он зеленый; если 1 <= f(x) < 2 он голубой и т. д.

Поскольку он начинается с голубого, вам нужно настроить входное значение оттенка так, чтобы 0 был эквивалентен самому краю того, что вы считаете голубым, а не зеленым. Давайте возьмем 150 для этого примера. Это означает, что голубой цвет имеет ширину 60 градусов, откуда я взял значение 1,1 K, так как оно хорошо совпадает.

Тогда наше значение x будет x = ((hue + (360 - 150)) % 360) / 60.0 или x = (hue + 210) % 360) / 60.0

Затем мы можем подключить это к нашему f (x) и получить число от 0 до 8, которое мы можем использовать, чтобы получить наш предполагаемый цвет. Если мы сделаем массив цветов, мы можем просто минимизировать значение и использовать его в качестве индекса, так как наш домен 0-6 даст нам диапазон примерно 0,36-7,7, поэтому он никогда не превысит 8 или ниже 0.

[cyan, blue, purple, magenta, red, orange, yellow, green]

Это перебор? Наверное.

Это интереснее? Определенно.


Наконец, код

function hsl($h, $s, $l){
    $options = array("cyan", "blue", "purple", "magenta", "red", "orange", "yellow", "green");
    if($l >= 95)
        return "white";
    else if($l <= 5)
        return "black";
    else if($s <= 10)
        return "gray";

    //Convert hue to x value
    $x = (($h + 210) % 360) / 60.0;
    $match = matchHue($x);
    return $options[$match];
}

function matchHue($x){
    return intval(floor(8 / (1 + pow(M_E, (-1.1 * ($x - 3))))));
}

Все это зависит от вашего варианта использования и от того, какие цвета вы пытаетесь использовать, так что ymmv, но если вам нужна формула, а не жестко закодированный список, такая логистическая функция, вероятно, будет вашим лучшим выбором для отражения воспринимаемого цвета из оттенков.


Еще больше перебор. Почему бы и нет?

Если вам нужно больше вариантов с S и L, например, чтобы иметь дополнительные оттенки цвета, вы можете использовать тот же стиль логистической функции или даже просто линейную функцию.

Легкость подчиняется той же функции. Средне-серый будет самым большим сегментом круговой диаграммы, поэтому вы должны установить x = 0 как нижнюю границу среднего серого.

Насыщенность - это скорее логарифмическая функция. Первые 25% или около того имеют несколько узнаваемых оттенков, а верхние 75% - гораздо меньше. Что-то вроде

 log

Где N - количество распознаваемых оттенков. Область этой функции - 0-100, а диапазон - 0-N. Вы можете настроить k по своему вкусу, чтобы изменить ширину ступенек, но даже если оставить k равным 1, вы получите адекватные результаты.

person David    schedule 17.07.2019
comment
Да, это в значительной степени то, что я сделал, жестко запрограммированный список значений оттенка и некоторые крайние случаи, когда L играет важную роль, например, коричневый и зеленый от желтого с низким L. Большое спасибо Дэвид, вы немного поработали над своим ответом - person user681148; 18.07.2019