2009-10-27 5 views
12

Je cherche une fonction qui peut représenter avec précision la distance entre deux couleurs comme un nombre ou quelque chose."Distance" entre les couleurs dans PHP

Par exemple, je cherche à avoir un tableau de valeurs HEX ou des tableaux RVB et je veux trouver la couleur la plus proche du tableau pour une couleur donnée

par exemple. Je passe une fonction à une valeur RVB et la couleur «la plus proche» dans le tableau est retournée

+0

Question similaire: http://stackoverflow.com/questions/1313/followup-finding-an-accurate-distance-between-colors – Kai

Répondre

19

Chaque couleur est représentée sous la forme d'un tuple dans le code HEX. Pour déterminer les correspondances proches, vous devez soustraire chaque composant RVB séparément.

Exemple:

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. 

modifier

Donc, vous voulez la couleur la plus proche du nom? Créer un tableau avec les valeurs hexadécimales de chaque couleur, l'itérer et retourner le nom. Quelque chose comme ça;

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) ; 

} 
+0

Je comprends que je dois obtenir les valeurs RVB, mais je cherche une fonction qui, pour peut renvoyer la couleur "la plus similaire" dans un tableau pour une couleur donnée. Un exemple simple: [BLEU, ROUGE, rouge foncé, VERT] Si la fonction a été donné la couleur bleu clair, à partir du tableau ci-dessus, Id attendent la fonction de retour « BLUE » Vive Philip – Phil

+0

Si vous ne poursuivez pas du tout les valeurs hexadécimales, créez simplement une fonction avec une grosse instruction switch qui prend le nom de la couleur et renvoie juste ce que vous pensez être le nom de couleur le plus proche. –

+3

La fonction colofDiff est bonne, mais doit corriger un bug en retour, "renvoyer abs ($ red1 - $ red2) + abs ($ green1 - $ green2) + abs ($ blue1 - $ blue2);" – Cesar

4

Une approche très simple consiste à calculer la distance résumée entre les trois dimensions. Par exemple, simple_distance ("12,10,255", "10,10,250") = 7

Une approche plus sophistiquée consisterait à prendre le carré des distances pour chaque composante et à les additionner - de cette façon, les composants étant trop loin seraient "puni" plus: square_distance ("12,10,255", "10,10,250") = 2 * 2 + 0 * 0 + 5 * 5 = 29.

Bien sûr, vous devrez parcourir la liste des couleurs et trouver le plus proche.

1

Vous pouvez convertir votre valeur RVB en HSL ou HSV. alors les couleurs sont faciles à comparer: ordre des couleurs par teinte d'abord, puis par saturation, puis par luminance. dans l'ordre résultant, 2 couleurs l'une à côté de l'autre apparaîtront comme très proches perceptuellement.

Prenez garde à ce que la teinte ne se déforme pas: pour une teinte allant de 0 à 255, une teinte de 0 et une teinte de 255 sont très proches.

voir l'article wikipedia sur HSL http://en.wikipedia.org/wiki/HSL_and_HSV pour la formule qui vous permettra de convertir RVB à HSL

(noter que d'autres est plus compliqué espaces de couleurs, comme Lab, peuvent donner de meilleurs résultats, mais la conversion)

nous allons définir mathématiquement:

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

où F est un facteur choisi avec soin (quelque chose comme 256 ...)

la formule ci-dessus ne prend pas en compte le contour de la teinte ...

+0

cela n'a aucun sens. Si les couleurs A et B présentaient une légère différence de luminance et de même teinte, les couleurs A et C avaient la même luminance et une grande différence de teinte (disons que l'une est rouge et l'autre verte ...), la distance entre A et B serait plus grand que la distance entre A et C ... –

+0

il semble que vous avez mal compris la commande que je vous propose: vous commandez d'abord par teinte, puis vous commandez des couleurs avec une teinte égale par saturation, enfin vous commandez des couleurs avec une teinte et une saturation égales par luminance. étant donné cet ordre, les couleurs A et B ont la même teinte et la distance (A, B) est plus petite que (A, C). –

+0

J'ai édité ma réponse pour inclure une petite formule mathématique, qui, j'espère, aide à mieux comprendre la commande ... –

12

Here is a paper on the subject qui devrait donner une bonne réponse. Je pensais que la conversion en HSL/HSV d'abord serait une bonne idée aussi, mais ensuite je me suis rendu compte qu'aux valeurs extrêmes de S & L/V, H n'a pas d'importance, et au milieu, il importe le plus .Je pense que si vous voulez une solution simple, rester dans l'espace RVB serait plus sage. J'utiliserais la distance cartésienne. Si vous envisagez de couleur R G B contre Ri Gi Bi pour plusieurs i, vous voulez que le i qui minimise

(R - Ri)^2 + (G - Gi)^2 + (B - Bi)^2 
8

D'abord, vous devez choisir e espace colorimétrique approprié vous voulez que les comparaisons de couleurs se produire dans (RVB, HSV, HSL, CMJN, etc.).

En supposant que vous voulez savoir à quel point deux points dans l'espace RGB 3-dimenionsal sont à l'autre, vous pouvez calculer la distance pythagoricienne entre eux, à savoir,

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

Cela vous donne en fait la place de la distance. (Prendre la racine carrée n'est pas nécessaire si vous comparez uniquement les valeurs au carré.)

Ceci suppose que vous voulez traiter les valeurs R, G et B de façon égale. Si vous souhaitez poids plutôt les composants de couleur individuels, comme ce qui se passe lors de la conversion RVB en niveaux de gris, vous devez ajouter un coefficient à chaque terme de la distance, à savoir,

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

Cela suppose la conversion populaire de RGB à niveaux de gris de 30% rouge + 59% vert + 11% bleu.

Mise à jour

Cette dernière équation devrait probablement être

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