«Расстояние» между цветами в PHP - PullRequest
13 голосов
/ 28 октября 2009

Я ищу функцию, которая может точно представлять расстояние между двумя цветами в виде числа или чего-то еще.

Например, я ищу массив значений HEX или RGB-массивов и хочу найти наиболее похожий цвет в массиве для данного цвета

например. Я передаю функции значение RGB и возвращается «ближайший» цвет в массиве

Ответы [ 6 ]

19 голосов
/ 28 октября 2009

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

Пример:

Color 1: #112233 
Color 2: #122334
Color 3: #000000

Difference between color1 and color2: R=1,  G=1   B=1  = 0x3 
Difference between color3 and color1: R=11, G=22, B=33 = 0x66

So color 1 and color 2 are closer than
1 and 3.

редактировать

Итак, вы хотите самый близкий названный цвет? Создайте массив с шестнадцатеричными значениями каждого цвета, повторите его и верните имя. Как то так;

function getColor($rgb)
{
    // these are not the actual rgb values
    $colors = array(BLUE =>0xFFEEBB, RED => 0x103ABD, GREEN => 0x123456);

    $largestDiff = 0;
    $closestColor = "";
    foreach ($colors as $name => $rgbColor)
    {
        if (colorDiff($rgbColor,$rgb) > $largestDiff)
        {
            $largestDiff = colorDiff($rgbColor,$rgb);
            $closestColor = $name;
        }

    }
    return $closestColor;

}

function colorDiff($rgb1,$rgb2)
{
    // do the math on each tuple
    // could use bitwise operates more efficiently but just do strings for now.
    $red1   = hexdec(substr($rgb1,0,2));
    $green1 = hexdec(substr($rgb1,2,2));
    $blue1  = hexdec(substr($rgb1,4,2));

    $red2   = hexdec(substr($rgb2,0,2));
    $green2 = hexdec(substr($rgb2,2,2));
    $blue2  = hexdec(substr($rgb2,4,2));

    return abs($red1 - $red2) + abs($green1 - $green2) + abs($blue1 - $blue2) ;

}
13 голосов
/ 28 октября 2009

Вот статья по теме , которая должна дать хороший ответ.

Я думал, что сначала было бы неплохо перейти на HSL / HSV, но потом я понял, что при экстремальных значениях S & L / V H не имеет значения, а в середине это имеет значение больше всего.

Я думаю, если вы хотите простое решение, пребывание в пространстве RGB было бы разумнее. Я бы использовал декартово расстояние. Если вы рассматриваете цвет R G B против Ri Gi Bi для нескольких i, вам нужен i, который минимизирует

(R - Ri)^2 + (G - Gi)^2 + (B - Bi)^2
8 голосов
/ 28 октября 2009

Сначала вы должны выбрать подходящее цветовое пространство, в котором должны выполняться сравнения цветов (RGB, HSV, HSL, CMYK и т. Д.).

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

d2 = (r1 - r2)**2 + (g1 - g2)**2 + (b1 - b2)**2;

Это фактически дает вам квадрат расстояния. (Получение квадратного корня не обязательно, если вы сравниваете только квадратные значения.)

Это предполагает, что вы хотите одинаково относиться к значениям R, G и B. Если вы предпочитаете взвешивать отдельные цветовые компоненты, например, что происходит при преобразовании RGB в оттенки серого, вам необходимо добавить коэффициент к каждому члену расстояния, т. Е.

d2 = 30*(r1-r2)**2 + 59*(g1-g2)**2 + 11*(b1-b2)**2;

Предполагается, что популярное преобразование из RGB в оттенки серого состоит из 30% красного + 59% зеленого + 11% синего.

Обновление

Последнее уравнение, вероятно, должно быть

d2 = (30*(r1-r2))**2 + (59*(g1-g2))**2 + (11*(b1-b2))**2;
4 голосов
/ 28 октября 2009

Очень простой подход - рассчитать суммарное расстояние между тремя измерениями. Например, simple_distance («12,10,255», «10,10,250») = 7

Более сложным подходом было бы взять квадрат расстояний для каждого компонента и суммировать их - таким образом слишком большие компоненты будут "наказаны" больше: square_distance ("12,10,255", "10,10,250") = 2 * 2 + 0 * 0 + 5 * 5 = 29.

Конечно, вам придется перебрать список цветов и найти ближайший.

1 голос
/ 21 октября 2013

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

Вам нужно использовать специальную формулу.

Смотрите здесь .

1 голос
/ 28 октября 2009

вы можете конвертировать ваше значение RGB в HSL или HSV. тогда цвета легко сравнивать: сначала упорядочите цвета по оттенку, затем по насыщенности, затем по яркости. в результирующем порядке 2 цвета рядом друг с другом будут восприниматься как очень близко воспринимаемые.

остерегайтесь того, что оттенок окутывает: для оттенка в диапазоне от 0 до 255 оттенок 0 и оттенок 255 очень близки.

см. Статью в Википедии по HSL http://en.wikipedia.org/wiki/HSL_and_HSV для формулы, которая позволит вам конвертировать RGB в HSL

(обратите внимание, что другие цветовые пространства, такие как L.a.b., могут давать лучшие результаты, но преобразование более сложное)

давайте определим это математически:

distance(A(h,s,l), B(h,s,l)) = (A(h)-B(h)) * F^2 + (A(s)-B(s)) * F + (A(l)-B(l))

где F - тщательно выбранный фактор (что-то вроде 256 ...)

в приведенной выше формуле не учитывается обтекание оттенка ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...