Oppfølging: Finne en nøyaktig "avstand" mellom farger

stemmer
44

Original Spørsmål

Jeg leter etter en funksjon som forsøker å kvantifisere hvor langt (eller distinkt) to farger er. Dette spørsmålet er egentlig i to deler:

  1. Hva fargerom best representerer menneskelige syn?
  2. Hvilken avstand beregning i det rommet best representerer det menneskelige øye (euclidean?)
Publisert på 04/08/2008 klokken 15:08
kilden bruker
På andre språk...                            


8 svar

stemmer
43

Konverter til La * b * (aka bare ren "Lab", og du vil også se referanse til "CIELAB"). En god rask measaure av fargeforskjell er

(L1-L2) ^ 2 + (a1-a2) ^ 2 + (B1-B2) ^ 2

Farge forskere har andre mer raffinerte tiltak, som kanskje ikke er verdt bryet, avhengig av nøyaktighet er nødvendig for hva du gjør.

Den aog bverdiene representerer motstående farger på en måte som ligner på hvordan kjegler arbeide, og kan være negativ eller positiv. Nøytrale farger - hvitt, grått er a=0, b=0. Det Ler lysstyrken definert på en spesiell måte, fra null (ren mørke) opp til hva.

Crude forklaring: >> Gitt en farge, våre øyne skille mellom to brede områder av bølgelengde - blå vs lengre bølgelengder. og da, takket være en nyere genetisk mutasjon, lengre bølgelengde kjegler splittnagler i to, skille for oss rød vs grønn.

Forresten, vil det være bra for karrieren din til å stige over fargehuleboer kolleger som vet om bare "RGB" eller "CMYK" som er flott for enheter, men suge for alvorlig oppfatning arbeid. Jeg har jobbet for bilde forskere som ikke visste noe om denne ting!

For mer moro å lese på fargeforskjell teori, prøve:

Flere detaljer om Lab på http://en.kioskea.net/video/cie-lab.php3 Jeg kan ikke på dette tidspunktet finne en ikke-stygg side som faktisk hadde konverteringsformler, men jeg er sikker på at noen vil redigere svar for å inkludere en.

Svarte 16/09/2008 kl. 16:08
kilden bruker

stemmer
8

som cmetric.htm linken over mislyktes for meg, så vel som mange andre implementeringer for farge avstand fant jeg (etter en veldig lang jurney ..) hvordan man skal beregne den beste fargen avstand, og .. mest vitenskapelig nøyaktige ett: deltaE og fra 2 (!) RGB-verdier ved anvendelse av OpenCV:

Dette kreves 3 fargerom konverteringer + noen kode konvertering fra javascript ( http://svn.int64.org/viewvc/int64/colors/colors.js ) til C ++

Og til slutt koden (synes å fungere rett ut av boksen, håper ingen finner en alvorlig feil der ... men det virker fint etter en rekke tester)

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

Håper det hjelper noen :)

Svarte 17/10/2013 kl. 01:39
kilden bruker

stemmer
4

HSL og HSV er bedre for menneskelig fargeoppfattelse. Ifølge Wikipedia :

Det er noen ganger å foretrekke å arbeide med kunstmaterialer, digitaliserte bilder eller andre medier, for å bruke den HSV eller HSL-fargemodellen fremfor alternative modeller som RGB eller CMYK, på grunn av forskjeller i hvordan de modellene etterligne hvordan mennesker oppfatter farge. RGB og CMYK er additiv og subtraktiv modeller, henholdsvis, å modellere den måten at primærfarge lys eller pigmenter (henholdsvis) kombinert for å danne nye farger når de blandes.

Grafisk fremstilling av HSV

Svarte 04/08/2008 kl. 15:16
kilden bruker

stemmer
3

Den Wikipedia artikkel om fargeforskjeller lister opp en rekke fargerom og avstandsberegninger designet for å være enig med menneskets oppfatning av farge avstander.

Svarte 24/08/2008 kl. 15:38
kilden bruker

stemmer
2

Som en som er fargeblinde Jeg tror det er bra å prøve å legge mer separasjon så normalt syn. Den vanligste formen for fargeblindhet er rød / grønn mangel. Det betyr ikke at du ikke kan se rødt eller grønt, det betyr at det er vanskeligere å se og mer vanskelig å se forskjellene. Så det tar en større separasjon før en fargeblind person kan se forskjellen.

Svarte 16/09/2008 kl. 16:45
kilden bruker

stemmer
2

Vel, som et første punktet i samtalen, vil jeg si de vanlige beregninger HSV (Hue, metning og verdi) eller HSL er bedre representant for hvordan mennesker oppfatter farger enn si RGB eller CYMK. Se HSL, HSV på Wikipedia .

Jeg antar naivt Jeg vil plotte punktene i HSL plass til de to fargene og beregne omfanget av forskjellen vektor. Men dette ville bety at lys gul og lys grønn ville bli betraktet like forskjellige som grønn til mørk grønn. Men så mange anser røde og rosa to forskjellige farger.

Videre forskjell vektorer i samme retning i denne parameterrommet ikke er like. For eksempel, plukker det menneskelige øyet grønt mye bedre enn andre farger. Et skifte i farge fra grønt med samme beløp som et skifte fra rød kan virke større. Også et skifte i metning fra en liten sum til null er forskjellen mellom grå og rosa, andre steder skiftet vil være forskjellen mellom to nyanser av rødt.

Fra et programmerere synspunkt, ville du trenger å plotte forskjellen vektorer, men modifisert av en proporsjonalitets matrise som ville justere lengder tilsvarende i ulike regioner av HSL plass - dette ville være ganske vilkårlig, og vil være basert på ulike fargeteori ideer, men bli forskjøvet ganske vilkårlig, avhengig av hva du ønsket å bruke dette til.

Enda bedre, kan du se om noen allerede har gjort noe slikt på nettet ...

Svarte 04/08/2008 kl. 15:37
kilden bruker

stemmer
2

Den enkleste avstand ville selvsagt være å bare vurdere fargene som 3d vektorer som stammer fra samme opprinnelse, og tar avstand mellom sine endepunkter.

Hvis du trenger å vurdere slike faktorer at grønn er mer fremtredende i bedømme intensitet, kan du veie verdier.

Imagemagic gir følgende skalaer:

  • red: 0,3
  • grønn: 0,6
  • blå: 0,1

Selvfølgelig ville verdiene som dette bare være meningsfylt i forhold til andre verdier for andre farger, ikke som noe som ville være meningsfull for mennesker, så alt du kan bruke verdiene for ville være similiarity bestilling.

Svarte 04/08/2008 kl. 15:14
kilden bruker

stemmer
2

Kan se ut som spam, men nei, det er veldig interessant for fargerom denne linken :)

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

Svarte 04/08/2008 kl. 15:14
kilden bruker

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