Follow-up: Het vinden van een nauwkeurige "afstand" tussen kleuren

stemmen
44

Original Question

Ik ben op zoek naar een functie die probeert te kwantificeren hoe ver (of verschillende) twee kleuren zijn. Deze vraag is eigenlijk in twee delen:

  1. Welke kleur ruimte het best overeenkomt met het menselijk gezichtsvermogen?
  2. Welke afstand metric in die ruimte het best overeenkomt met het menselijk gezichtsvermogen (euclidean?)
De vraag is gesteld op 04/08/2008 om 16:08
bron van user
In andere talen...                            


8 antwoorden

stemmen
43

Converteren naar La * b * (aka gewoon "Lab", en je ziet ook verwijzing naar "CIELAB"). Een goede snelle measaure van kleur verschil is

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

Kleur wetenschappers hebben andere, meer verfijnde maatregelen, die niet de moeite waard kan zijn de moeite, afhankelijk van de nauwkeurigheid die nodig is voor wat je doet.

De aen bwaarden vertegenwoordigen tegengestelde kleuren op een manier vergelijkbaar met hoe kegels werken, en kan positief of negatief zijn. Neutrale kleuren - wit, grijs zijn a=0, b=0. Het Lis helderheid gedefinieerd op een bepaalde wijze van nul (zuivere donker) tot wat.

Ruwe verklaring: >> Gegeven een kleur, onze ogen onderscheid te maken tussen twee grote reeksen van golflengte - blauwe vs langere golflengten. en dan, dankzij een meer recente genetische mutatie, de langere golflengte kegels gesplitst in twee, onderscheiden voor ons rood vs. groen.

By the way, het zal geweldig zijn voor je carrière tot boven je kleur holbewoner collega's die weten van enige "RGB" of "CMYK", die zeer geschikt voor apparaten stijgen, maar zuigen voor serieuze perceptie werk. Ik heb gewerkt voor imaging wetenschappers die niets over dit soort dingen wist!

Voor meer plezier lezen op kleurverschil theorie, probeer:

Meer details over Lab aan http://en.kioskea.net/video/cie-lab.php3 Ik kan op dit moment niet het vinden van een niet-lelijk pagina die eigenlijk de omzettingsformules gehad, maar ik weet zeker dat iemand zal dit bewerken antwoord op één bevatten.

antwoordde op 16/09/2008 om 17:08
bron van user

stemmen
8

zoals cmetric.htm bovenstaande link mislukt voor mij, evenals vele andere implementaties voor kleurenafstand vond ik (na een zeer lange jurney ..) hoe je de beste kleur afstand te berekenen, en .. wetenschappelijk meest accurate één: DeltaE en 2 (!) RGB waarden met behulp van OpenCV:

Dit vereist 3 kleurruimte omzettingen + wat code conversie van Javascript ( http://svn.int64.org/viewvc/int64/colors/colors.js ) tot C ++

En tot slot de code (lijkt te werken direct uit de doos, hoop dat niemand een serieuze bug vindt daar ... maar het lijkt prima na een aantal tests)

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

Hoop dat iemand helpt :)

antwoordde op 17/10/2013 om 02:39
bron van user

stemmen
4

HSL en HSV zijn beter voor de menselijke perceptie van kleur. Volgens Wikipedia :

Het is soms de voorkeur in het werken met kunst materialen, gedigitaliseerde afbeeldingen, of andere media, om de HSV of HSL kleur model over alternatieve modellen zoals RGB of CMYK te gebruiken, omdat de verschillen in de manieren waarop de modellen na te bootsen hoe mensen kleur waarnemen. RGB en CMYK zijn additieve en subtractieve modellen, respectievelijk, het modelleren van de manier waarop de primaire kleuren licht of pigmenten (respectievelijk) combineren om nieuwe kleuren te vormen wanneer gemengd.

Grafische voorstelling van HSV

antwoordde op 04/08/2008 om 16:16
bron van user

stemmen
3

De Wikipedia-artikel over kleurverschillen somt een aantal kleurruimten en afstand metrics ontworpen om in te stemmen met de menselijke perceptie van kleur afstanden.

antwoordde op 24/08/2008 om 16:38
bron van user

stemmen
2

Als iemand die kleurenblind Ik denk dat het goed is om te proberen om meer afscheiding dan normaal zicht toe te voegen. De meest voorkomende vorm van kleurenblindheid is rood / groen-deficiëntie. Het betekent niet dat je niet rood of groen kan zien, betekent dit dat het moeilijker is om te zien het steeds moeilijker om de verschillen te zien. Dus het duurt een grotere scheiding voordat een kleur kan blinde persoon het verschil te vertellen.

antwoordde op 16/09/2008 om 17:45
bron van user

stemmen
2

Nou, als een eerste aanspreekpunt, zou ik zeggen van de gemeenschappelijke metrics HSV (tint, verzadiging en waarde) of HSL beter representatief zijn voor hoe mensen waarnemen kleur dan zeggen RGB of CMYK. Zie HSL, HSV op Wikipedia .

Ik denk dat naïef zou ik de punten plot in de HSL-ruimte voor de twee kleuren en het berekenen van de grootte van het verschil vector. Toch zou dit betekenen dat helder geel en helder groen net zo verschillend als groen tot donkergroen zou worden beschouwd. Maar dan velen beschouwen rood en roze twee verschillende kleuren.

Bovendien verschilvectoren in dezelfde richting in deze parameterruimte niet gelijk. Bijvoorbeeld, het menselijk oog pikt groen veel beter dan andere kleuren. Een verschuiving in de tint van groen met hetzelfde bedrag als een verschuiving van rood kan groter lijken. Ook een verschuiving in de verzadiging van een kleine hoeveelheid aan nul is het verschil tussen grijs en roze, elders de verschuiving zou het verschil tussen de twee tinten van rood.

Vanuit een programmeurs oogpunt, zou je nodig hebt om te plotten het verschil vectoren, maar gewijzigd door een evenredigheid matrix dat de lengtes dienovereenkomstig in verschillende regio's van de HSL-ruimte zou passen - dat zou nogal willekeurig zijn en zou worden op basis van verschillende kleur theorie ideeën, maar tamelijk willekeurig worden getweakt, afhankelijk van wat je wilde dit toepassen op.

Nog beter, je kon zien of iemand al zoiets online heeft gedaan ...

antwoordde op 04/08/2008 om 16:37
bron van user

stemmen
2

De makkelijkste afstand zou natuurlijk zijn om gewoon rekening houden met de kleuren als 3D-vectoren die afkomstig zijn van dezelfde oorsprong, en het nemen van de afstand tussen hun eindpunten.

Als u dergelijke factoren zijn van mening dat groen is meer prominent in het beoordelen van de intensiteit, kunt u de waarden wegen.

Imagemagick biedt de volgende schalen:

  • rood: 0,3
  • groen: 0,6
  • blauw: 0,1

Natuurlijk, waarden als dit zou alleen zinvol in relatie tot andere waarden voor andere kleuren, niet als iets dat zinvol is voor de mens zou zijn, dus alles wat je kon de waarden voor gelijkenis bestellen zou zijn.

antwoordde op 04/08/2008 om 16:14
bron van user

stemmen
2

Kan lijken op spam maar nee, deze link is echt interessant voor kleurruimten :)

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

antwoordde op 04/08/2008 om 16:14
bron van user

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