Aquí podría ser tu PUBLICIDAD


Seguimiento: Encontrar una "distancia" precisa entre los colores

votos
44

Pregunta original

Estoy buscando una función que intente cuantificar cuán distantes (o distintos) dos colores son. Esta pregunta es realmente en dos partes:

  1. ¿Qué espacio de color representa mejor la visión humana?
  2. ¿Qué distancia métrica en ese espacio representa mejor la visión humana (euclidiana?)
Publicado el 04/08/2008 a las 16:08
fuente por usuario Louis Brandy
En otros idiomas...        العربية       

8 respuestas

votos
43

Convierta a La * b * (también conocido simplemente como "Lab", y también verá la referencia a "CIELAB"). Una buena medida rápida de la diferencia de color es

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

Los científicos de color tienen otras medidas más refinadas, que pueden no valer la pena, dependiendo de la precisión necesaria para lo que estás haciendo.

Los valores ay brepresentan colores opuestos de forma similar a cómo funcionan los conos, y pueden ser negativos o positivos. Los colores neutros - blanco, grises son a=0, b=0. El Lbrillo es definido de una manera particular, desde cero (oscuridad absoluta) hasta lo que sea.

Explicación cruda: >> Dado un color, nuestros ojos distinguen entre dos amplios rangos de longitud de onda: azul versus longitudes de onda más largas. y luego, gracias a una mutación genética más reciente, los conos de longitud de onda más largos se bifurcaron en dos, distinguiéndonos rojo contra verde.

Por cierto, será grandioso que su carrera supere a sus colegas de color de las cavernas que solo conocen "RGB" o "CMYK", que son geniales para los dispositivos pero que aspiran a un trabajo de percepción serio. ¡He trabajado para científicos de imágenes que no sabían nada de esto!

Para leer más divertido sobre la teoría de diferencia de color, intente:

Más detalles en Lab en http://en.kioskea.net/video/cie-lab.php3. No puedo encontrar una página no fea que tenga las fórmulas de conversión, pero estoy seguro de que alguien editará esta página. respuesta para incluir uno.

Respondida el 16/09/2008 a las 05:08
fuente por usuario DarenW


Aquí podría ser tu PUBLICIDAD


votos
8

como enlace cmetric.htm anterior no para mí, al igual que muchas otras implementaciones para la distancia de color que encontré (después de un largo jurney ..) la forma de calcular la mejor distancia de color y .. más científicamente exacta uno: delta E y de 2 (!) valores RGB usando OpenCV:

Esto requirió 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 funciona nada más sacarlo de la caja, espero que nadie encuentra un error grave allí ... 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 ayuda a alguien :)

Respondida el 17/10/2013 a las 02:39
fuente por usuario user1241378

votos
4

HSL y HSV son mejores para la percepción del color humano. De acuerdo con Wikipedia :

A veces es preferible trabajar con materiales artísticos, imágenes digitalizadas u otros medios para usar el modelo de color HSV o HSL sobre modelos alternativos como RGB o CMYK, debido a las diferencias en la forma en que los modelos emulan cómo los humanos perciben el color. RGB y CMYK son modelos aditivos y sustractivos, respectivamente, que modelan la forma en que las luces de colores primarios o los pigmentos (respectivamente) se combinan para formar nuevos colores cuando se mezclan.

Representación gráfica de HSV

Respondida el 04/08/2008 a las 04:16
fuente por usuario huseyint

votos
3

El artículo de Wikipedia sobre las diferencias de color enumera una serie de espacios de color y métricas de distancia diseñados para concordar con la percepción humana de las distancias de color.

Respondida el 24/08/2008 a las 04:38
fuente por usuario palm3D

votos
2

Como alguien que es daltónico, creo que es bueno tratar de agregar más separación que la visión normal. La forma más común de daltonismo es la deficiencia de rojo / verde. No significa que no se puede ver rojo o verde, significa que es más difícil de ver y más difícil de ver las diferencias. Por lo tanto, se necesita una separación mayor antes de que una persona daltónica sepa la diferencia.

Respondida el 16/09/2008 a las 05:45
fuente por usuario bruceatk

votos
2

Bueno, como primer punto de referencia, diría que las métricas comunes HSV (Hue, Saturation y Value) o HSL son mejor representativas de cómo los humanos perciben el color que RGB o CYMK. Ver HSL, HSV en Wikipedia .

Supongo que ingenuamente trazaré los puntos en el espacio HSL para los dos colores y calcularé la magnitud del vector de diferencia. Sin embargo, esto significaría que el amarillo brillante y el verde brillante se considerarían tan diferentes como el verde o el verde oscuro. Pero luego muchos consideran rojo y rosa dos colores diferentes.

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

Desde el punto de vista de los programadores, necesitarías trazar los vectores de diferencia, pero modificados por una matriz de proporcionalidad que ajustaría las longitudes según corresponda en varias regiones del espacio de HSL; esto sería bastante arbitrario y estaría basado en varias ideas de teoría de color, pero debe ajustarse de manera bastante arbitraria según lo que desee aplicar a esto.

Aún mejor, podrías ver si alguien ya hizo algo así en línea ...

Respondida el 04/08/2008 a las 04:37
fuente por usuario Brendan

votos
2

La distancia más fácil sería, por supuesto, considerar los colores como vectores en 3D que se originan en el mismo origen y tomar la distancia entre sus puntos finales.

Si necesita considerar factores tales que el verde es más prominente al juzgar la intensidad, puede ponderar los valores.

ImageMagic proporciona las siguientes escalas:

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

Por supuesto, valores como este solo serían significativos en relación con otros valores para otros colores, no como algo que sería significativo para los humanos, así que todo lo que podrías usar para los valores sería el orden de similiaridad.

Respondida el 04/08/2008 a las 04:14
fuente por usuario Lasse Vågsæther Karlsen

votos
2

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

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

Respondida el 04/08/2008 a las 04:14
fuente por usuario Vincent Robert