2009-10-27 37 views
12

sto cercando una funzione che può rappresentare con precisione la distanza tra due colori come un numero o qualcosa del genere."distanza" tra i colori in PHP

Per esempio sto cercando di avere una matrice di valori HEX o array RGB e voglio trovare il colore più simile nella matrice per un determinato colore

ad es. Passo una funzione di un valore RGB e il colore 'vicina' nella matrice sia nuovamente

+0

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

risposta

19

Ogni colore è rappresentato come una tupla nel codice esadecimale. Per determinare le corrispondenze ravvicinate è necessario sottrarre separatamente ciascun componente RGB.

Esempio:

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. 

modificare

Così si desidera che il più vicino colore di nome? Crea una matrice con i valori esadecimali di ciascun colore, esegui iterazione e restituisci il nome. Qualcosa come questo;

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

Capisco che ho bisogno di ottenere i valori RGB, ma sto cercando una funzione che per può restituire il colore "più simile" in un array per un determinato colore. Un semplice esempio: [blu, rosso, rosso scuro, VERDE] Se la funzione è stato dato il colore LIGHTBLUE, dalla matrice di cui sopra, Id si aspettano la funzione per restituire "BLU" Cin cin Philip – Phil

+0

Se non stanno citando i valori esadecimali, basta creare una funzione con una grande istruzione switch che prende il nome del colore e restituisce semplicemente quello che pensi sia il nome del colore più vicino. –

+3

La funzione colofDiff è buona, ma deve correggere un bug in cambio, "return abs ($ red1 - $ red2) + abs ($ green1 - $ green2) + abs ($ blue1 - $ blue2);" – Cesar

4

Un approccio molto semplice è quello di calcolare la distanza sintetizzati tra le tre dimensioni. Ad esempio simple_distance ("12,10,255", "10,10,250") = 7

Un approccio più sofisticato sarebbe prendere quadrato delle distanze per ogni componente e sommare quelli - così componenti essendo troppo sarebbe "punito" di più: square_distance ("12,10,255", "10,10,250") = 2 * 2 + 0 * 0 + 5 * 5 = 29.

Naturalmente sarebbe necessario iterare l'elenco dei colori e trovare quello più vicino.

1

è possibile convertire il valore RGB a HSL o HSV. quindi i colori sono facili da confrontare: ordina prima i colori per tonalità, poi per saturazione, poi per luminanza. nell'ordine risultante, 2 colori l'uno accanto all'altro appariranno molto vicini percettivamente.

attenzione che avvolge intorno tonalità: per una tonalità che varia da 0 a 255, una tonalità di 0 e una tonalità di 255 sono molto vicini.

si veda l'articolo di Wikipedia su HSL http://en.wikipedia.org/wiki/HSL_and_HSV per la formula che vi permetterà di convertire RGB a HSL

(notare che altri spazi di colore, come il laboratorio, può dare risultati migliori, ma la conversione è più complicato)

definiamo questo matematicamente:

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

dove F è un fattore scelto con cura (si parla di 256 ...)

la formula di cui sopra non tiene in considerazione l'avvolgente tonalità ...

+0

questo non ha senso. Se i colori A e B avevano una leggera differenza di luminanza e stessa tonalità, e i colori A e C avevano la stessa luminanza e una grande differenza di tonalità (diciamo che uno è rosso e l'altro è verde ...), la distanza tra A e B B sarebbe maggiore della distanza tra A e C ... –

+0

sembra che abbiate frainteso l'ordine che propongo: il primo ordine per tonalità, quindi ordinate colori con tonalità uguale per saturazione, infine ordinate colori con tonalità e saturazione uguali per luminanza. dato questo ordine, i colori A e B hanno la stessa tonalità e la distanza (A, B) è minore di (A, C). –

+0

ho modificato la mia risposta includendo una piccola formula matematica, che, spero, aiuta a capire meglio l'ordinamento ... –

12

Here is a paper on the subject che dovrebbe dare una buona risposta.

Pensavo che convertire prima in HSL/HSV sarebbe stata una buona idea, ma poi mi sono reso conto che a valori estremi di S & L/V, H non importa, e nel mezzo, importa di più .

Penso che se si desidera una soluzione semplice, stare nello spazio RGB sarebbe più saggio. Userei la distanza cartesiana. Se state pensando di colore R G B contro Ri Gi Bi per diversi i, si desidera che il i che minimizza

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

In primo luogo si deve scegliere esimo spazio colore appropriato si desidera che i confronti dei colori che si verifichi a (RGB, HSV, HSL, CMYK, ecc.).

Supponendo che si desidera sapere come vicino due punti nello spazio 3-dimenionsal RGB sono gli uni agli altri, è possibile calcolare la distanza di Pitagora tra di loro, vale a dire,

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

Questo in realtà ti dà il quadrato della la distanza. (Prendere la radice quadrata non è necessario se si confrontano solo i valori al quadrato.)

Ciò presuppone che si desideri trattare i valori R, G e B allo stesso modo. Se si preferisce il peso singoli componenti di colore, come ad esempio quello che succede quando si converte RGB in scala di grigi, è necessario aggiungere un coefficiente a ciascun termine della distanza, vale a dire,

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

Questo presuppone la conversione popolare da Da RGB a scala di grigi: 30% rosso + 59% verde + 11% blu.

Aggiornamento

L'ultima equazione dovrebbe probabilmente essere

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