Răspundeți: Găsirea unei „distanța“ precisă între culori

voturi
44

Întrebarea originală

Caut o funcție care încearcă să cuantifice modul în care „la distanță“ (sau distincte), două culori sunt. Această întrebare este într-adevăr în două părți:

  1. Ce spațiu de culoare reprezintă cea mai bună viziune umană?
  2. Ce distanță metrică în acel spațiu reprezintă cel mai bine viziunea umană (euclidian?)
Întrebat 04/08/2008 la 16:08
sursa de către utilizator
În alte limbi...                            


8 răspunsuri

voturi
43

Conversia la La * b * (aka pur și simplu „Lab“, și veți vedea, de asemenea, referire la „CIELAB“). Un measaure bun rapid de diferența de culoare este

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

oamenii de știință de culoare au alte măsuri mai rafinate, care nu merită deranjul, în funcție de precizia necesară pentru ceea ce faci.

aȘi bvalorile culorilor opuse într reprezinta un mod similar cu modul în care funcționează conuri, și pot fi negative sau pozitive. Culorile neutre - alb, gri sunt a=0, b=0. LLuminozitatea este definită într - un anumit mod, de la (întuneric pur) la zero până la orice.

explicație brută: >> Având în vedere o culoare, ochii noștri se facă distincția între cele două game largi de lungimi de undă - albastre vs lungimi de undă mai lungi. și apoi, datorită unei mutații genetice mai recente, cele mai lungi conuri lungime de undă bifurcat în două, pentru a distinge noi roșu vs verde.

Apropo, va fi mare pentru cariera ta să se ridice deasupra dvs. Caveman de culoare colegii care știu doar „RGB“ sau „CMYK“, care sunt foarte bune pentru dispozitive, dar suge pentru o muncă serioasă percepție. Am lucrat pentru oamenii de știință de formare a imaginii care nu au știut nimic despre aceste lucruri!

Pentru mai multă distracție lectură la teoria diferență de culoare, încercați:

Mai multe detalii despre Lab la http://en.kioskea.net/video/cie-lab.php3 nu pot găsi în acest moment o pagină care nu este urât , care a avut de fapt formulele de conversie , dar eu sunt sigur că cineva va modifica acest răspundă pentru a include unul.

Publicat 16/09/2008 la 17:08
sursa de către utilizator

voturi
8

ca link - ul de mai sus cmetric.htm nu a reușit pentru mine, precum și multe alte implementări pentru distanță de culoare am găsit (după o jurney foarte lung ..) cum să calculeze distanța cea mai bună culoare și .. mai exacte punct de vedere științific una: Deltae și de la 2 (!) valorilor RGB folosind OpenCV:

Acest lucru este necesar 3 conversii spațiu de culoare + unele de conversie de cod de javascript ( http://svn.int64.org/viewvc/int64/colors/colors.js ) la C ++

Și, în sfârșit codul (pare să lucreze direct din cutie, sper nimeni nu găsește un bug serios acolo ... dar se pare bine, după o serie de teste)

#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 );
}

Sper că vă ajută cineva :)

Publicat 17/10/2013 la 02:39
sursa de către utilizator

voturi
4

HSL și HSV sunt mai bune pentru perceptia umana a culorii. Conform Wikipedia :

Este, uneori, de preferat în lucrul cu materiale de artă, imagini digitalizate sau alte suporturi media, de a utiliza modelul de culoare HSV sau HSL peste modele alternative, cum ar fi RGB sau CMYK, din cauza diferențelor în modul în care modelele imita modul in care oamenii percep culoarea. RGB și CMYK sunt modele aditive si substractive, respectiv, modelarea modul în care luminile de culoare primare sau pigmenți (respectiv) se combină pentru a forma noi culori atunci când sunt amestecate.

reprezentare grafică a HSV

Publicat 04/08/2008 la 16:16
sursa de către utilizator

voturi
3

Articolul Wikipedia privind diferențele de culoare enumeră o serie de spații de culoare și valori la distanță proiectate să fie de acord cu percepția umană a distanțelor de culoare.

Publicat 24/08/2008 la 16:38
sursa de către utilizator

voturi
2

Ca cineva care este orb de culoare cred că este bine să încercați să adăugați mai mult de separare, apoi viziune normală. Cea mai comună formă de orbire de culoare este roșu deficit / verde. Aceasta nu înseamnă că nu puteți vedea roșu sau verde, aceasta înseamnă că este mai dificil de a vedea și mai dificil de a vedea diferențele. Deci, este nevoie de o separare mai mare înainte de o culoare orb poate spune diferenta.

Publicat 16/09/2008 la 17:45
sursa de către utilizator

voturi
2

Ei bine, ca un prim punct de apel, aș spune comune valorile HSV (Hue, saturație și valoare) sau HSL sunt mai bine reprezentative pentru modul în care oamenii percep culoare decât spun RGB sau CYMK. A se vedea HSL, HSV pe Wikipedia .

Presupun cu naivitate aș complot puncte în spațiul HSL pentru cele două culori și se calculează mărimea vectorului diferență. Totuși, acest lucru ar însemna că luminos galben deschis și verde strălucitor ar fi considerat la fel de diferite ca verde la verde închis. Dar, apoi, mulți consideră că cele două culori roșu și roz diferite.

Mai mult, vectorii diferență în aceeași direcție în acest spațiu parametru nu sunt egale. De exemplu, ochiul uman preia verde mult mai bine decât alte culori. O schimbare în nuanță de verde, cu aceeași valoare ca și o trecere de la roșu poate părea mai mare. De asemenea, o schimbare în saturație dintr-o cantitate mică la zero este diferența dintre gri și roz, în altă parte trecerea ar fi diferența dintre două nuanțe de roșu.

Dintr-un punct de programatori de vedere, ar trebui să complot vectorii de diferență, dar modificată printr-o matrice de proporționalitate, care va ajusta lungimile în consecință, în diferite regiuni ale spațiului HSL - acest lucru ar fi destul de arbitrară și ar trebui să se bazeze pe diferite idei teoria culoare, dar să fie optimizat destul de arbitrar, în funcție de ceea ce ai vrut să aplice acest lucru.

Chiar mai bine, ai putea vedea dacă cineva a făcut deja un astfel de lucru on-line ...

Publicat 04/08/2008 la 16:37
sursa de către utilizator

voturi
2

Cea mai simplă distanță ar fi , desigur , să ia în considerare doar culorile ca vectori 3D care provin din aceeași origine, și luând distanța dintre punctele lor de capăt.

Dacă trebuie să ia în considerare astfel de factori ca verde este mai proeminent în intensitate judecând, puteți cântări valorile.

ImageMagic prevede următoarele scale:

  • roșu: 0.3
  • verde: 0.6
  • albastru: 0.1

Desigur, valori ca acest lucru ar fi doar semnificativ în raport cu alte valori pentru alte culori, nu ca ceva care ar fi relevante pentru oameni, astfel încât tot ceea ce ar putea folosi valorile pentru ar fi comanda similiarity.

Publicat 04/08/2008 la 16:14
sursa de către utilizator

voturi
2

Poate arata ca spam-ul, dar nu, acest link este foarte interesant pentru spații de culoare :)

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

Publicat 04/08/2008 la 16:14
sursa de către utilizator

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