2009-10-27 27 views
12

Estoy buscando una función que pueda representar con precisión la distancia entre dos colores como un número o algo así."Distancia" entre colores en PHP

Por ejemplo, yo estoy buscando tener una matriz de valores HEX o matrices RGB y quiero encontrar el color más similar en la matriz para un color dado

por ejemplo. Paso una función con un valor RGB y se devuelve el color 'más cercano' en la matriz

+0

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

Respuesta

19

Cada color se representa como una tupla en el código HEX. Para determinar coincidencias cercanas, debe restar cada componente RGB por separado.

Ejemplo:

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. 

edición

Así que desea que el color más cercano llamado? Crea una matriz con los valores hexadecimales de cada color, repítelo y devuelve el nombre. Algo como esto;

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

Entiendo que necesito obtener los valores RGB, pero estoy buscando una función que para puede devolver el color "más similar" en una matriz para un color dado. Un ejemplo sencillo: [azul, rojo, rojo oscuro, VERDE] Si se le dio la función el color azul claro, a partir de la matriz anterior, Id esperar que la función devuelva "AZUL" Saludos Philip – Phil

+0

Si no están demandando valores hexadecimales en absoluto, solo crea una función con una gran declaración de cambio que toma el nombre del color y simplemente devuelve lo que crees que es el nombre de color más cercano. –

+3

La función colofDiff es buena, pero tiene que corregir un error a cambio, "return abs ($ red1 - $ red2) + abs ($ green1 - $ green2) + abs ($ blue1 - $ blue2);" – Cesar

4

Un enfoque muy simple es calcular la distancia resumida entre las tres dimensiones. Por ejemplo, simple_distance ("12,10,255", "10,10,250") = 7

Un enfoque más sofisticado sería tomar el cuadrado de las distancias para cada componente y sumarlos, de esta manera los componentes estarían demasiado lejos. "castigado" más: square_distance ("12,10,255", "10,10,250") = 2 * 2 + 0 * 0 + 5 * 5 = 29.

Por supuesto, tendrías que repetir la lista de colores y encontrar la más cercana.

1

puede convertir su valor RGB a HSL o HSV. entonces los colores son fáciles de comparar: ordene los colores primero por matiz, luego por saturación, luego por luminancia. en el orden resultante, 2 colores próximos uno al otro aparecerán como muy cerca perceptualmente.

tenga en cuenta que el tono se envuelve: para un tono que va de 0 a 255, un tono de 0 y un tono de 255 son muy similares.

ver el artículo de Wikipedia sobre HSL http://en.wikipedia.org/wiki/HSL_and_HSV para la fórmula que le permitirá convertir RGB a HSL

(obsérvese que los otros espacios de color, como laboratorio, puede dar mejores resultados, pero la conversión es más complicado)

vamos a definir matemáticamente:

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

donde F es un factor elegido cuidadosamente (algo así como 256 ...)

la fórmula anterior no tiene en cuenta el tono envolvente ...

+0

esto no tiene sentido. Si los colores A y B tienen una ligera diferencia en la luminancia y el mismo matiz, y los colores A y C tienen la misma luminancia y una gran diferencia de matiz (digamos que uno es rojo y el otro es verde ...), la distancia entre A y B sería mayor que la distancia entre A y C ... –

+0

parece que entendiste mal el orden que propongo: primero ordena por matiz, luego ordena colores con igual matiz por saturación, finalmente ordena colores con tono igual y saturación por luminancia. dado este orden, los colores A y B tienen el mismo matiz y la distancia (A, B) es menor que (A, C). –

+0

edité mi respuesta para incluir una pequeña fórmula matemática que, espero, ayude a entender mejor el orden ... –

12

Here is a paper on the subject que debería dar una buena respuesta.

Estaba pensando que la conversión a HSL/HSV primero también sería una buena idea, pero luego me di cuenta de que a valores extremos de S & L/V, H no importa, y en el medio, es lo más importante .

Creo que si quieres una solución simple, permanecer en el espacio RGB sería más inteligente. Usaría la distancia cartesiana. Si usted está considerando el color R G B contra Ri Gi Bi para varios i, desea que el i que minimiza

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

En primer lugar tiene que elegir º espacio de color apropiado desea que las comparaciones de color que se produzca en (RGB, HSV, HSL, CMYK, etc.).

Suponiendo que usted quiere saber qué tan cerca dos puntos en el espacio RGB 3-dimenionsal son el uno al otro, se puede calcular la distancia de Pitágoras entre ellos, es decir,

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

En realidad, esto le da a la plaza de la distancia. (No es necesario tomar la raíz cuadrada si compara solo los valores al cuadrado.)

Esto supone que desea tratar los valores R, G y B por igual. Si prefiere el peso de los componentes de color individuales, como lo que sucede cuando se convierte de RGB a escala de grises, hay que añadir un coeficiente a cada término de la distancia, es decir,

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

Esto supone la conversión populares desde RGB a escala de grises de 30% rojo + 59% verde + 11% azul.

actualización

Esa última ecuación debe ser probablemente

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