Я только что завершил интересное исследование цветовых пространств . Как уже упоминалось здесь, преобразование RGB в CIE-Lab и выполнение вычислений Delta E даст вам воспринимаемое цветовое расстояние. Это дает хорошие результаты.
Моя цель состояла в том, чтобы найти ближайший индекс в ограниченной цветовой палитре. Тем не менее, я обнаружил, что при использовании вычислений CIE-Lab Delta E получаются «неправильные» цвета. В частности, оттенки серого могут привести к получению слишком большой насыщенности и выберут красный вместо серого из палитры, но у других цветов тоже были проблемы (я не помню, какие из них). Что бы там ни было, я увеличил весовые оттенки с множителем в 1,2 раза, насыщенность в 1,5 раза и значения B в 1,0 или 2,0 раза в зависимости от направления. Результаты более или менее работают лучше, чем просто Delta E.
Вычислить расстояние Хюэ немного сложно, так как это круг. Например, оттенки 0 и 359 - это расстояние 1. Решение состоит в том, чтобы выбрать минимум двух разных расстояний.
Вот мой код, основанный на вышеупомянутом:
// Finds the nearest color index in a RGB palette that matches the requested color.
// This function uses HSB instead of CIE-Lab since this function is intended to be called after GetReadableTextForegroundColors() and results in more consistent color accuracy.
public static function FindNearestPaletteColorIndex($palette, $r, $g, $b)
{
$hsb1 = self::ConvertRGBToHSB($r, $g, $b);
$result = false;
$founddist = false;
foreach ($palette as $key => $rgb)
{
$rgb = array_values($rgb);
$r = $rgb[0];
$g = $rgb[1];
$b = $rgb[2];
$hsb2 = self::ConvertRGBToHSB($r, $g, $b);
$hdiff = min(abs($hsb1["h"] - $hsb2["h"]), abs($hsb1["h"] - $hsb2["h"] + ($hsb1["h"] < $hsb2["h"] ? -360.0 : 360.0))) * 1.2;
$sdiff = ($hsb1["s"] - $hsb2["s"]) * 1.5;
$bdiff = $hsb1["b"] - $hsb2["b"];
if ($hsb1["b"] < $hsb2["b"]) $bdiff *= 2.0;
$hdiff *= $hdiff;
$sdiff *= $sdiff;
$bdiff *= $bdiff;
$dist = $hdiff + $sdiff + $bdiff;
if ($result === false || $founddist >= $dist)
{
$result = $key;
$founddist = $dist;
}
}
return $result;
}
Источник: https://github.com/cubiclesoft/php-misc/blob/master/support/color_tools.php
Преобразование вышеупомянутого для использования HSL вместо HSB / HSV не должно быть слишком сложным. Я предпочитаю цветовое пространство HSB, поскольку оно отражает Photoshop, что позволяет мне подтверждать числа, которые я ищу в программном обеспечении.