Acompanhamento: Encontrar uma "distância" exacta entre as cores

votos
44

Pergunta original

Eu estou procurando uma função que tenta quantificar como distante (ou distinto) duas cores são. Esta questão é realmente em duas partes:

  1. O espaço de cor melhor representa a visão humana?
  2. Que distância métrica nesse espaço melhor representa a visão humana (euclidiana?)
Publicado 04/08/2008 em 16:08
fonte usuário
Em outras línguas...                            


8 respostas

votos
43

Converter para La * b * (aka simplesmente "Lab", e você também verá a referência a "CIELAB"). Um bom measaure rápida da diferença de cor é

(L1-L2) ^ 2 + (A1-A2) ^ 2 + (B1-B2) 2 ^

cientistas cores têm outras medidas mais refinadas, o que pode não valer a pena o incomodam, dependendo precisão necessária para o que você está fazendo.

O ae bvalores representam cores opostas de uma forma semelhante à forma como cones funcionam, e pode ser negativo ou positivo. As cores neutras - branco, cinzas são a=0, b=0. A Lé definido brilho de uma forma particular, a partir de zero (escuridão pura) até que seja.

explicação Crude: >> Dada uma cor, nossos olhos distinguir entre duas grandes intervalos de comprimento de onda - azul vs comprimentos de onda mais longos. e depois, graças a um mais recente mutação genética, os cones de comprimento de onda mais longos bifurcado em dois, distinguindo para nós vermelha vs. verde.

By the way, vai ser ótimo para sua carreira a subir acima de sua cor colegas homem das cavernas que sabem de apenas "RGB" ou "CMYK", que são grandes para dispositivos, mas chupar para o trabalho percepção sério. Eu trabalhei para cientistas de imagem que não sabiam nada sobre essas coisas!

Para mais divertido de ler sobre a teoria da diferença de cor, tente:

Mais detalhes sobre Lab em http://en.kioskea.net/video/cie-lab.php3 eu não posso neste momento encontrar uma página não-feia que realmente tinha as fórmulas de conversão mas eu tenho certeza que alguém vai editar esta resposta para incluir um.

Respondeu 16/09/2008 em 17:08
fonte usuário

votos
8

como ligação cmetric.htm acima falhou para mim, assim como muitas outras implementações para distância cor que eu encontrei (após um longo jurney ..) como calcular a distância melhor cor e .. mais cientificamente precisas um: deltaE e de 2 (!) RGB valores usando OpenCV:

Isto exigiu 3 conversões de espaço de cores + alguma conversão de código a partir do JavaScript ( http://svn.int64.org/viewvc/int64/colors/colors.js ) para C ++

E, finalmente, o código (parece funcionar direito fora da caixa, espero que ninguém encontra um bug sério lá ... mas parece bem depois de uma série de testes)

#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 ajude alguém :)

Respondeu 17/10/2013 em 02:39
fonte usuário

votos
4

HSV são melhores para a percepção de cor humana. De acordo com a Wikipedia :

Às vezes, é preferível trabalhar com materiais de arte, imagens digitalizadas, ou outros meios de comunicação, para usar o modelo de cores HSV ou HSL sobre modelos alternativos, como RGB ou CMYK, por causa das diferenças nas formas dos modelos emular como os seres humanos percebem as cores. RGB e CMYK são modelos aditivas e subtrativas, respectivamente, modelando a maneira que as luzes de cores primárias ou pigmentos (respectivamente) se combinam para formar novas cores quando misturado.

representação gráfica do HSV

Respondeu 04/08/2008 em 16:16
fonte usuário

votos
3

O artigo da Wikipedia sobre diferenças de cor enumera uma série de espaços de cor e métricas de distância destinados a concordar com a percepção humana de distâncias de cor.

Respondeu 24/08/2008 em 16:38
fonte usuário

votos
2

Como alguém que é cego cor que eu acredito que é bom para tentar adicionar mais separação, em seguida, a visão normal. A forma mais comum de daltonismo é a deficiência de vermelho / verde. Isso não significa que você não pode ver o vermelho ou verde, isso significa que é mais difícil de ver e mais difícil de ver as diferenças. Então, é preciso uma separação maior antes de uma cor pessoa cega pode dizer a diferença.

Respondeu 16/09/2008 em 17:45
fonte usuário

votos
2

Bem, como um primeiro ponto de chamada, eu diria das métricas comuns HSV (matiz, saturação e valor) ou de HSL são mais representativo de como os seres humanos percebem cor do que dizer RGB ou CYMK. Veja HSL, HSV na Wikipedia .

Suponho que, ingenuamente, eu plotar os pontos no espaço HSL para as duas cores e calcular a magnitude do vector diferença. No entanto, isso significaria que o verde amarelo e brilhante brilhante seria considerado tão diferentes como verde para verde escuro. Mas, em seguida, muitos consideram duas cores vermelho e rosa diferentes.

Além disso, os vectores de diferença na mesma direção neste espaço de parâmetros não são iguais. Por exemplo, o olho humano capta verde muito melhor do que outras cores. Uma mudança de tonalidade de verde pela mesma quantidade como uma mudança a partir de vermelho pode parecer maior. Também uma mudança na saturação de uma pequena quantidade de zero é a diferença entre cinza e rosa, em outros lugares a mudança seria a diferença entre dois tons de vermelho.

Do ponto programadores de vista, seria necessário traçar os vetores de diferença, mas modificado por uma matriz de proporcionalidade que ajustar os comprimentos de acordo em várias regiões do espaço HSL - isso seria bastante arbitrária e seria baseada em várias idéias teoria da cor, mas ser mexido bastante arbitrariamente, dependendo do que você queria aplicar isso a.

Mesmo melhor, você poderia ver se alguém já tenha feito tal coisa online ...

Respondeu 04/08/2008 em 16:37
fonte usuário

votos
2

O mais fácil distância seria, evidentemente, considerar apenas as cores como vetores 3d provenientes da mesma origem, e tomando a distância entre os pontos finais.

Se você precisa considerar esses fatores que o verde é mais proeminente no julgamento intensidade, você pode pesar os valores.

ImageMagic oferece as seguintes escalas:

  • vermelho: 0,3
  • verde: 0,6
  • azul: 0,1

Claro, valores como este só seria significativa em relação a outros valores para outras cores, não como algo que seria significativo para os seres humanos, então tudo que você poderia usar os valores para seria ordenação similaridade.

Respondeu 04/08/2008 em 16:14
fonte usuário

votos
2

Pode ser parecido com spam, mas não, esta ligação é realmente interessante para espaços de cor :)

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

Respondeu 04/08/2008 em 16:14
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more