Pregunta

Pregunta Original

Estoy buscando una función que intenta cuantificar qué tan "distantes" (o distinto) de dos colores.Esta pregunta es realmente en dos partes:

  1. ¿Qué espacio de color que mejor representa la visión humana?
  2. ¿Qué distancia métrica en el espacio que mejor representa la visión humana (euclidiana?)
¿Fue útil?

Solución

Convertir a La*b* (también conocido como simplemente el "Laboratorio", y también podrás ver la referencia a la "CIELAB").Un buen rápida measaure de diferencia de color es

(L1-L2)^2 + (a1-a2)^2 + (b1-b2)^2

Color científicos tienen otros más refinados medidas, que no puede ser vale la pena molestarse, dependiendo de la precisión necesaria para lo que estás haciendo.

El a y b los valores representan oponerse a los colores de una manera similar a cómo los conos de trabajo, y puede ser negativo o positivo.Los colores neutros: blanco, los grises a=0,b=0.El L es el brillo definido de una manera particular, a partir de la cero (oscuridad total) a lo que sea.

Crudo explicación :>> Dado un color, nuestros ojos distinguir entre dos grandes rangos de longitud de onda azul vs longitudes de onda más largas.y entonces, gracias a la más reciente mutación genética, las longitudes de onda de los conos bifurca en dos, la distinción para nosotros roja vsverde.

Por el camino, va a ser muy bueno para su carrera para elevarse por encima de su color de hombre de las cavernas, los colegas que saben de sólo "RGB" o "CMYK", que son ideales para los dispositivos, pero chupar graves para la percepción de la obra.He trabajado para la imagen de los científicos que no sabía nada acerca de este material!

Para más diversión de la lectura en la diferencia de color de la teoría, la prueba:

Más detalle en el Laboratorio de http://en.kioskea.net/video/cie-lab.php3 Yo no puedo en este momento encontrar un no-feo página que en realidad tenía las fórmulas de conversión, pero estoy seguro de que alguien va a editar esta respuesta para incluir uno.

Otros consejos

como cmetric.htm enlace de arriba no para mí, así como muchas otras implementaciones para el color de la distancia he encontrado (después de una muy larga jurney..) cómo calcular los mejores colores de distancia, y ..más científicamente precisa uno: delta e y a partir de 2 RGB (!) los valores de uso de OpenCV:

Esto requiere 3 conversiones de espacio de color + algunos de conversión de código de javascript (http://svn.int64.org/viewvc/int64/colors/colors.js) para C++

Y finalmente el código (parece que a la derecha de la caja, la esperanza no se encuentra un grave error que hay ...pero parece bien después de una serie de pruebas)

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/photo/photo.hpp>
#include <math.h>

using namespace cv;
using namespace std;

#define REF_X 95.047; // Observer= 2°, Illuminant= D65
#define REF_Y 100.000;
#define REF_Z 108.883;

void bgr2xyz( const Vec3b& BGR, Vec3d& XYZ );
void xyz2lab( const Vec3d& XYZ, Vec3d& Lab );
void lab2lch( const Vec3d& Lab, Vec3d& LCH );
double deltaE2000( const Vec3b& bgr1, const Vec3b& bgr2 );
double deltaE2000( const Vec3d& lch1, const Vec3d& lch2 );


void bgr2xyz( const Vec3b& BGR, Vec3d& XYZ )
{
    double r = (double)BGR[2] / 255.0;
    double g = (double)BGR[1] / 255.0;
    double b = (double)BGR[0] / 255.0;
    if( r > 0.04045 )
        r = pow( ( r + 0.055 ) / 1.055, 2.4 );
    else
        r = r / 12.92;
    if( g > 0.04045 )
        g = pow( ( g + 0.055 ) / 1.055, 2.4 );
    else
        g = g / 12.92;
    if( b > 0.04045 )
        b = pow( ( b + 0.055 ) / 1.055, 2.4 );
    else
        b = b / 12.92;
    r *= 100.0;
    g *= 100.0;
    b *= 100.0;
    XYZ[0] = r * 0.4124 + g * 0.3576 + b * 0.1805;
    XYZ[1] = r * 0.2126 + g * 0.7152 + b * 0.0722;
    XYZ[2] = r * 0.0193 + g * 0.1192 + b * 0.9505;
}

void xyz2lab( const Vec3d& XYZ, Vec3d& Lab )
{
    double x = XYZ[0] / REF_X;
    double y = XYZ[1] / REF_X;
    double z = XYZ[2] / REF_X;
    if( x > 0.008856 )
        x = pow( x , .3333333333 );
    else
        x = ( 7.787 * x ) + ( 16.0 / 116.0 );
    if( y > 0.008856 )
        y = pow( y , .3333333333 );
    else
        y = ( 7.787 * y ) + ( 16.0 / 116.0 );
    if( z > 0.008856 )
        z = pow( z , .3333333333 );
    else
        z = ( 7.787 * z ) + ( 16.0 / 116.0 );
    Lab[0] = ( 116.0 * y ) - 16.0;
    Lab[1] = 500.0 * ( x - y );
    Lab[2] = 200.0 * ( y - z );
}

void lab2lch( const Vec3d& Lab, Vec3d& LCH )
{
    LCH[0] = Lab[0];
    LCH[1] = sqrt( ( Lab[1] * Lab[1] ) + ( Lab[2] * Lab[2] ) );
    LCH[2] = atan2( Lab[2], Lab[1] );
}

double deltaE2000( const Vec3b& bgr1, const Vec3b& bgr2 )
{
    Vec3d xyz1, xyz2, lab1, lab2, lch1, lch2;
    bgr2xyz( bgr1, xyz1 );
    bgr2xyz( bgr2, xyz2 );
    xyz2lab( xyz1, lab1 );
    xyz2lab( xyz2, lab2 );
    lab2lch( lab1, lch1 );
    lab2lch( lab2, lch2 );
    return deltaE2000( lch1, lch2 );
}

double deltaE2000( const Vec3d& lch1, const Vec3d& lch2 )
{
    double avg_L = ( lch1[0] + lch2[0] ) * 0.5;
    double delta_L = lch2[0] - lch1[0];
    double avg_C = ( lch1[1] + lch2[1] ) * 0.5;
    double delta_C = lch1[1] - lch2[1];
    double avg_H = ( lch1[2] + lch2[2] ) * 0.5;
    if( fabs( lch1[2] - lch2[2] ) > CV_PI )
        avg_H += CV_PI;
    double delta_H = lch2[2] - lch1[2];
    if( fabs( delta_H ) > CV_PI )
    {
        if( lch2[2] <= lch1[2] )
            delta_H += CV_PI * 2.0;
        else
            delta_H -= CV_PI * 2.0;
    }

    delta_H = sqrt( lch1[1] * lch2[1] ) * sin( delta_H ) * 2.0;
    double T = 1.0 -
            0.17 * cos( avg_H - CV_PI / 6.0 ) +
            0.24 * cos( avg_H * 2.0 ) +
            0.32 * cos( avg_H * 3.0 + CV_PI / 30.0 ) -
            0.20 * cos( avg_H * 4.0 - CV_PI * 7.0 / 20.0 );
    double SL = avg_L - 50.0;
    SL *= SL;
    SL = SL * 0.015 / sqrt( SL + 20.0 ) + 1.0;
    double SC = avg_C * 0.045 + 1.0;
    double SH = avg_C * T * 0.015 + 1.0;
    double delta_Theta = avg_H / 25.0 - CV_PI * 11.0 / 180.0;
    delta_Theta = exp( delta_Theta * -delta_Theta ) * ( CV_PI / 6.0 );
    double RT = pow( avg_C, 7.0 );
    RT = sqrt( RT / ( RT + 6103515625.0 ) ) * sin( delta_Theta ) * -2.0; // 6103515625 = 25^7
    delta_L /= SL;
    delta_C /= SC;
    delta_H /= SH;
    return sqrt( delta_L * delta_L + delta_C * delta_C + delta_H * delta_H + RT * delta_C * delta_H );
}

Espero que ayude a alguien :)

La HSL y HSV son mejores para los humanos la percepción del color.De acuerdo a Wikipedia:

A veces es preferible en el trabajo con materiales de arte, imágenes digitalizadas, o de otros medios de comunicación, para utilizar el VHS o el modelo de color HSL sobre modelos alternativos tales como RGB o CMYK, debido a las diferencias en las formas en que los modelos de emular cómo los seres humanos perciben el color.RGB y CMYK son aditivos y sustractivos de modelos, respectivamente, el modelado de la forma en que primaria luces de colores o pigmentos (respectivamente) se combinan para formar nuevos colores cuando se mezclan.

Graphical depiction of HSV

El Artículo de Wikipedia sobre las diferencias de color enumera una serie de espacios de color y la distancia métricas diseñado para estar de acuerdo con la percepción humana del color y de las distancias.

Puede parecer spam, pero no, este enlace es muy interesante para los espacios de color :)

http://www.compuphase.com/cmetric.htm

La forma más fácil distancia sería, por supuesto, sólo considere los colores como vectores 3d procedentes del mismo origen, y tomando la distancia entre sus puntos finales.

Si usted necesita considerar factores tales que el verde es más prominente en el juicio de la intensidad, puede sopesar los valores.

ImageMagic proporciona las siguientes escalas:

  • rojo:0.3
  • verde:0.6
  • azul:0.1

Por supuesto, los valores como esto sólo sería significativo en relación con otros valores para los otros colores, no como algo que tenga sentido para los seres humanos, por lo que todo lo que usted podría utilizar los valores de sería similiarity pedido.

Bien, como primer punto de llamar, yo diría que de los sistemas de medición comunes HSV (Matiz, Saturación y Valor) o HSL son más representativo de cómo los seres humanos perciben el color que decir RGB o CYMK.Ver HSL, HSV en la Wikipedia.

Supongo que, ingenuamente, me gustaría representar los puntos en el HSL espacio para los dos colores y calcular la magnitud de la diferencia de vectores.Sin embargo, esto significaría que de color amarillo brillante y de color verde brillante podría ser considerado sólo como diferentes, como la de verde a verde oscuro.Pero, a continuación, muchos consideran que el rojo y el rosa de dos colores diferentes.

Por otra parte, a diferencia de los vectores en la misma dirección en este espacio de parámetros no son iguales.Por ejemplo, el ojo humano capta verde mucho mejor que otros colores.Un cambio en el tono de verde por la misma cantidad que un cambio de rojo puede parecer mayor.También un cambio en la saturación de una pequeña cantidad de cero es la diferencia entre el gris y el rosa, en otros lugares el cambio sería la diferencia entre los dos tonos de rojo.

A partir de una programadores punto de vista, sería necesario para la trama de la diferencia de los vectores, pero modificado por la proporcionalidad de la matriz que ajustar las longitudes en consecuencia, en las distintas regiones de la HSL espacio - esto sería bastante arbitraria y estaría basada en varios colores de la teoría de las ideas, pero ser ajustado bastante arbitrariamente en función de lo que quería aplicar esto.

Mejor aún, usted podría ver si alguien ya ha hecho tal cosa en línea...

Como alguien que es ciego a los colores, creo que es bueno tratar de agregar más separación, entonces la visión normal.La forma más común de la ceguera es de color rojo/verde de la deficiencia.Esto no significa que usted no puede ver el rojo o el verde, significa que es más difícil de ver y de más difícil ver las diferencias.Por lo que se necesita una mayor separación antes de un color a una persona ciega puede decir la diferencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top