Pergunta

Pergunta Original

Eu estou olhando para uma função que tenta quantificar como "distante" (ou diferente), duas cores são.Esta questão é realmente em duas partes:

  1. Que espaço de cor melhor representa a visão humana?
  2. Que distância métrica no espaço que melhor representa a visão humana (euclidiana?)
Foi útil?

Solução

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

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

Cor cientistas têm outros mais refinados de medidas, que podem não valer a pena o incômodo, dependendo da precisão necessária para o que você está fazendo.

O a e b valores representam opostos cores em uma forma semelhante à forma como cones de trabalho, e pode ser negativo ou positivo.Cores neutras - branco, tons de cinza são a=0,b=0.O L é o brilho definido de uma maneira particular, a partir de zero (pura escuridão) até que quer que seja.

Bruto explicação :>> Dada uma cor, nossos olhos se distinguir entre dois grandes intervalos de comprimento de onda - azul vs comprimentos de onda mais longos.e então, graças a uma mais recente mutação genética, o maior comprimento de onda cones bifurcada em dois, distinguindo-se, para nós, vermelho vs.o verde.

Pelo jeito, vai ser ótimo para sua carreira para se elevar acima da sua cor caveman colegas que conhecem apenas "RGB" ou "CMYK" que são ótimos para dispositivos chupar mas para a percepção graves de trabalho.Eu trabalhei para a imagem que os cientistas que não sabe uma coisa sobre essas coisas!

Para mais diversão leitura sobre a diferença de cor da teoria, tente:

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

Outras dicas

como cmetric.htm o link acima não para mim, assim como muitas outras implementações de cor para a distância descobri (depois de muito tempo jurney..) como calcular a melhor cor de distância, e ..cientificamente mais precisos: deltaE e a partir de 2 RGB (!) valores usando OpenCV:

Este necessários 3 de espaço de cor, conversões de + alguns de conversão de código de javascript (http://svn.int64.org/viewvc/int64/colors/colors.js) para C++

E, finalmente, o código (parece funcionar para a direita fora da caixa, a esperança não encontra-se um grave erro aí ...mas ele parece muito 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 :)

HSL e HSV são melhores para a percepção humana da cor.De acordo com a Taxas:

Às vezes é preferível trabalhar com materiais de arte, imagens digitalizadas, ou outros meios de comunicação, a utilizar o HSV ou HSL modelo de cores nos modelos alternativos, tais como RGB ou CMYK, por causa das diferenças nas formas como os modelos de emular como os seres humanos percebem as cores.RGB e CMYK são aditivas e subtrativas modelos, respectivamente, a modelação da forma que cor primária de luz ou de pigmentos (respectivamente) combinam-se para formar novas cores, quando misturados.

Graphical depiction of HSV

O Artigo da wikipédia em diferenças de cor lista um número de espaços de cor e distância de métricas projetado para concordar com a percepção humana das cores distâncias.

Pode parecer spam, mas não, este link é muito interessante para espaços de cor :)

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

O mais fácil distância seria, é claro, para considerar apenas as cores como 3d vetores provenientes de uma mesma origem, e tomando a distância entre seus pontos de extremidade.

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

ImageMagic fornece 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 de outras cores, não como algo que fosse significativo para os seres humanos, então tudo que você poderia usar os valores para seriam similiarity pedido.

Bem, como primeiro ponto de chamada, eu diria que de comum métricas de HSV (Hue, Saturação e Valor) ou HSL são melhor representante de como os seres humanos percebem cor que dizer RGB ou CMYK.Ver HSL, HSV na Wikipédia.

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

Além disso, a diferença de vetores de 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 de outras cores.Uma mudança na tonalidade de verde pela mesma quantidade como uma mudança de vermelho pode parecer maior.Também uma mudança na saturação a partir de uma pequena quantidade a zero é a diferença entre o cinza e cor-de-rosa, em outros lugares a mudança seria a diferença entre dois tons de vermelho.

A partir de um programadores ponto de vista, seria necessário assinalar a diferença de vetores, mas modificado por uma proporcionalidade matriz que seria ajustar o comprimento de acordo em várias regiões do HSL espaço - isto pode ser bastante arbitrário e deve ser baseado em várias cores teoria idéias, mas ser mexido bastante arbitrariamente, dependendo do que você quiser aplicar este.

Mesmo melhor, você pode ver se alguém já fez tal coisa online...

Como alguém que é daltônico eu acredito que é bom para tentar adicionar mais separação, em seguida, a visão normal.A forma mais comum de daltonismo é vermelho/verde deficiência.Isso não significa que você não pode ver o vermelho ou o verde, que significa que é mais difícil de ver e mais difícil ver as diferenças.Portanto, é necessário um maior separação antes de uma pessoa daltônico pode dizer a diferença.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top