Followup: Nalezení přesné „vzdálenosti“ mezi barvami

hlasů
44

původní Otázka

Mám zájem o funkci, která se snaží kvantifikovat, jak „vzdálené“ (nebo odlišný) dvě barvy. Tato otázka je ve skutečnosti skládá ze dvou částí:

  1. Jaký barevný prostor nejlépe reprezentuje lidský zrak?
  2. Jaké vzdálenosti metriky v tomto prostoru nejlépe reprezentuje lidský zrak (euklidovské?)
Položena 04/08/2008 v 16:08
zdroj uživatelem
V jiných jazycích...                            


8 odpovědí

hlasů
43

Převést na La * b * (aka prostě „Lab“, a budete také odkaz na „CIELAB“). Dobrý rychlý measaure barevného rozdílu je

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

Barevné vědci mají jiné jemnějších opatření, která nemusí být stojí za to obtěžovat v závislosti na přesnosti potřebné pro to, co děláte.

aA bhodnoty představují protichůdné barvy podobným způsobem, jak kužely fungovat a může být pozitivní nebo negativní. Neutrální barvy - bílá, šedé jsou a=0, b=0. LJe jas definován zvláštním způsobem, od nuly (čisté tmy) až do cokoliv.

Surové vysvětlení: >> Vzhledem k tomu, barvy, naše oči rozlišovat mezi dvěma širokými rozsahy vlnové délce - modrá vs delších vlnových délkách. a pak, díky novější genetické mutace, delší vlnová délka kužele rozštěpené do dvou, rozlišovat pro nás červená vs. zeleně.

Mimochodem, bude to skvělé pro vaše kariéra se povznést nad svou barvu barbar kolegům, kteří znají pouze „RGB“ nebo „CMYK“, které jsou ideální pro zařízení, ale sát pro seriózní vnímání práce. Pracoval jsem pro zobrazovací vědců, kteří nevěděli nic o této věci!

Pro více zábavy čtení na barevném teorii diference, vyzkoušejte následující postup:

Další detaily o Lab na http://en.kioskea.net/video/cie-lab.php3 nemohu v tuto chvíli najít non-ošklivé stránky, které ve skutečnosti měl vzorců konverze, ale jsem si jistý, že někdo bude upravovat tuto zodpovídat zahrnují jeden.

Odpovězeno 16/09/2008 v 17:08
zdroj uživatelem

hlasů
8

jak cmetric.htm výše uvedený odkaz se nezdařilo pro mě, stejně jako mnoho jiných implementacích pro barevnou vzdálenosti jsem našel (po velmi dlouhé jurney ..), jak vypočítat nejlepší barevnou vzdálenost, a .. nejvíce vědecky přesné jedno: Delta E a od 2 (!), RGB hodnoty pomocí OpenCV:

To vyžadovalo 3 barevný prostor konverze + nějaké konverzi kódu z JavaScriptu ( http://svn.int64.org/viewvc/int64/colors/colors.js ) na C ++

A nakonec kód (zdá se k práci hned po vybalení z krabice, doufám, že nikdo najde vážnou chybu tam ... ale zdá se v pořádku po řadě testů)

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

Doufám, že to někomu pomůže :)

Odpovězeno 17/10/2013 v 02:39
zdroj uživatelem

hlasů
4

HSV jsou lepší pro lidské vnímání barev. Podle Wikipedie :

Někdy je výhodnější pracovat s uměleckými materiály, digitalizovaných obrázků nebo jiných médií, použít barevný model HSV nebo HSL nad alternativních modelů, jako je RGB nebo CMYK, kvůli rozdílům ve způsobech, jakými modely napodobit, jak lidé vnímají barvy. RGB a CMYK jsou aditivní a subtraktivní modely, respektive modelování tak, že základní barva světla nebo pigmenty (v tomto pořadí) společně tvořit nové barvy při smíchání.

Grafické znázornění HSV

Odpovězeno 04/08/2008 v 16:16
zdroj uživatelem

hlasů
3

Wikipedia článek o barevné rozdíly uvádí řadu barevných prostorů a na dálku metriky, jejichž cílem je dohodnout s lidským vnímáním barev vzdálenosti.

Odpovězeno 24/08/2008 v 16:38
zdroj uživatelem

hlasů
2

Jako někdo, kdo je slepý barvy se domnívám, že je dobré pokusit se přidat další oddělení poté normální vidění. Nejběžnější forma barevné slepoty je červená / zelená deficit. To neznamená, že nemůžete vidět červeně nebo zeleně, znamená to, že je obtížnější vidět a hůře vidět rozdíly. Tak to trvá větší odloučení než barvu slepý člověk může poznat rozdíl.

Odpovězeno 16/09/2008 v 17:45
zdroj uživatelem

hlasů
2

No, jako první bod výzvy, řekl bych, že z běžných metrik HSV (odstín, sytost a hodnota) nebo HSL lépe vyjadřující, jak lidé vnímají barvu než říci, RGB nebo CYMK. Viz HSL, HSV na Wikipedii .

Myslím, že bych se naivně plot bodů v HSL prostor pro dvě barvy a vypočítat velikost rozdílu vektoru. To by však znamenalo, že zářivě žluté a světle zelené by bylo považováno za stejně tak odlišné, jak zelené až tmavě zelené. Ale pak mnozí považují červené a růžové dvě různé barvy.

Kromě toho, rozdíl vektory ve stejném směru, v tomto prostoru parametru nejsou stejné. Například, lidské oko zvedne zelený mnohem lépe než jiné barvy. Posun v odstínu od zelené o stejnou částku jako posun od červené může zdát větší. Také posun v saturaci z malého množství na nulu, je rozdíl mezi šedou a růžovou, jinde posun by byl rozdíl mezi dvěma odstíny červené.

Od programátorů pohledu, budete muset plot rozdílová vektorů, ale pozměněná úměrnosti matici, která by odpovídajícím způsobem upravit délky v různých regionech HSL prostoru - to by bylo dosti svévolné a bude na základě různých teorií barev nápady, ale být vylepšený poměrně libovolně v závislosti na tom, co jste chtěli aplikovat na.

Ještě lepší je, mohli jste vidět, jestli někdo již udělal takovou věc on-line ...

Odpovězeno 04/08/2008 v 16:37
zdroj uživatelem

hlasů
2

Nejjednodušší vzdálenost by samozřejmě bylo jen zvážit barvy jako 3d vektorů pocházejících ze stejného původu, a kteří se vzdálenost mezi svými koncovými body.

Potřebujete-li v úvahu takové faktory, které zelená je výraznější při posuzování intenzity, můžete vážit hodnot.

Imagemagick poskytuje následující váhy:

  • red: 0.3
  • green: 0.6
  • modrá: 0,1

Samozřejmě, že hodnoty, jako by to bylo smysluplné pouze ve vztahu k jiným hodnotám pro jiné barvy, nikoli jako něco, co by bylo smysluplné pro člověka, takže vše, co mohli použít hodnoty by similiarity uspořádání.

Odpovězeno 04/08/2008 v 16:14
zdroj uživatelem

hlasů
2

Může vypadat jako spam, ale ne, tento odkaz je opravdu zajímavé barevné prostory :)

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

Odpovězeno 04/08/2008 v 16:14
zdroj uživatelem

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