Kontynuacja: Znalezienie dokładnych „odległość” między kolorami

głosy
44

Oryginalny Pytanie

Szukam funkcji, która stara się określić ilościowo jak „odległy” (lub wyraźny) dwa kolory. To pytanie jest naprawdę na dwie części:

  1. Jaki kolor najlepiej reprezentuje przestrzeń ludzką wizję?
  2. Co odległość metryczny w tej przestrzeni najlepiej reprezentuje ludzkiego wzroku (euklidesowej?)
Utwórz 04/08/2008 o 16:08
źródło użytkownik
W innych językach...                            


8 odpowiedzi

głosy
43

Konwersja do La * b * (aka prostu „Lab”, a zobaczysz też odniesienie do „CIELAB”). Dobrym szybkie measaure różnicy kolorów jest

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

Naukowcy kolor mają inne środki bardziej wyrafinowane, które nie mogą być warte przeszkadza, w zależności od dokładności potrzebnej do tego, co robisz.

aI bwartości reprezentują przeciwstawne kolory w sposób podobny do tego, jak działa stożki i mogą być ujemne lub dodatnie. Neutralne kolory - biały, szarości są a=0, b=0. LJest jasność określona w sposób szczególny, od zera (czystej ciemności) do czegokolwiek.

Surowy wyjaśnienie: >> Biorąc pod uwagę kolor, nasze oczy rozróżnić dwóch szerokich zakresach długości fali - niebieski vs dłuższych falach. a następnie, dzięki nowszym mutacji genetycznej, tym dłużej szyszki długości fali rozwidlone na dwie części, z rozróżnieniem dla nas czerwony vs. zieleni.

Nawiasem mówiąc, to będzie wielkie za kariera wznieść się ponad swoimi kolegami jaskiniowiec kolorów, którzy znają się tylko z „RGB” lub „CMYK”, które są idealne do urządzeń ale ssać do poważnej pracy percepcji. Pracowałem dla obrazowania naukowcy, którzy nie wiedzą nic o tych rzeczy!

Aby uzyskać więcej zabawy, czytanie na kolor teorii różnicy, spróbuj:

Więcej szczegółów na Lab w http://en.kioskea.net/video/cie-lab.php3 Nie mogę w tej chwili znaleźć non-brzydką stronę, która rzeczywiście miała formuły przeliczeniowe, ale jestem pewien, że ktoś będzie zmodyfikować odpowiedzieć na to jedno.

Odpowiedział 16/09/2008 o 17:08
źródło użytkownik

głosy
8

jak wyżej związek cmetric.htm powiodło się dla mnie, jak i wielu innych implementacjach dla koloru odległości znalazłem (po bardzo długim jurney ..) Jak obliczyć najlepszą odległość kolorów i .. najbardziej naukowo dokładna jeden: Delta E i od 2 (!) wartości RGB za pomocą OpenCV:

Wymagało 3 konwersji przestrzeni kolorów + kilka konwersji kodu z JavaScript ( http://svn.int64.org/viewvc/int64/colors/colors.js ) do c ++

I wreszcie kod (wydaje się do pracy zaraz po wyjęciu z pudełka, nadzieję, że nikt nie znajdzie poważny błąd ... ale wydaje się w porządku, po szeregu testów)

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

Mam nadzieję, że ktoś pomoże :)

Odpowiedział 17/10/2013 o 02:39
źródło użytkownik

głosy
4

HSV są lepsze dla ludzkiej percepcji kolorów. Według Wikipedii :

Czasem jest korzystny w pracy z materiałami sztuki, obrazów cyfrowych i innych mediach, aby użyć kolorów modelu HSV lub HSL nad alternatywnymi modelami takimi jak RGB lub CMYK, z powodu różnic w sposobach modele naśladować jak ludzie postrzegają kolor. RGB i CMYK są modele addytywne i subtraktywnymi odpowiednio modelując sposób, że podstawowe barwy światła lub pigmenty (odpowiednio) łączą się, tworząc nowe kolory po zmieszaniu.

Graficznym przedstawieniem HSV

Odpowiedział 04/08/2008 o 16:16
źródło użytkownik

głosy
3

Artykuł Wikipedii różnic kolorystycznych wymienia szereg przestrzeni kolorów i metryki odległości zaprojektowanych zgodzić się z ludzkiej percepcji kolorów dystansach.

Odpowiedział 24/08/2008 o 16:38
źródło użytkownik

głosy
2

Jako ktoś, kto jest daltonistą uważam, że jest dobry, aby spróbować dodać więcej separację potem normalne widzenie. Najbardziej rozpowszechnioną formą ślepoty barw jest czerwony / zielony niedobór. To nie znaczy, że nie można zobaczyć na czerwono lub zielono, oznacza to, że trudniej jest zobaczyć i trudniej zobaczyć różnice. Więc zajmuje większą separację przed kolorze ślepy człowiek może odróżnić.

Odpowiedział 16/09/2008 o 17:45
źródło użytkownik

głosy
2

Cóż, jako pierwszego punktu poboru, powiedziałbym wspólnych metryk HSV (odcień, nasycenie i wartość) lub HSL są lepsze przedstawiciel w jaki sposób ludzie postrzegają kolor niż powiedzieć RGB lub cymk. Zobacz HSL, HSV na Wikipedii .

Przypuszczam naiwnie chciałbym wykreślić punkty w przestrzeni HSL dla dwóch kolorach i obliczyć wielkość wektora różnica. Jednak oznaczałoby to, że jasny żółty i zielony jasny, będą uważane za tak różne, jak zielony do ciemnej zieleni. Ale wielu uważa czerwone i różowe dwóch różnych kolorach.

Ponadto, wektory różnicowe w tym samym kierunku w tym miejscu parametrów nie są równe. Na przykład, ludzkie oko odbiera zielony znacznie lepiej niż inne kolory. Przesunięcie w odcieniu z zielonego o taką samą kwotę jak przejście od czerwieni może wydawać się większe. Również zmiana nasycenia z niewielkiej ilości do zera jest różnica między szarym i różowym, gdzie indziej zmiana byłaby różnica między dwoma odcieniami czerwieni.

Z punktu widzenia programisty widzenia, trzeba by wykreślić wektory różnicowe, ale zmodyfikowane przez macierz proporcjonalności, która dostosowania długości odpowiednio w różnych rejonach przestrzeni HSL - to byłoby dość arbitralne i powinno być oparte na różnych pomysłów teorii koloru, ale być manipulowane dość dowolnie w zależności od tego, czego chciał zastosować to do.

Jeszcze lepiej, można sprawdzić, czy ktoś już zrobił coś takiego w Internecie ...

Odpowiedział 04/08/2008 o 16:37
źródło użytkownik

głosy
2

Najprostszym odległość byłoby oczywiście tylko pod uwagę kolory jak 3d wektorów pochodzących od tego samego pochodzenia, a także biorąc dystans między ich punktów końcowych.

Jeśli wziąć pod uwagę takie czynniki, że zielony jest bardziej widoczne w ocenie intensywności, można ważyć wartości.

ImageMagick udostępnia następujące wagi:

  • czerwony: 0,3
  • zielony 0,6
  • niebieski: 0,1

Oczywiście, wartości takie jak ten byłby sens tylko w stosunku do innych wartości dla innych kolorów, a nie jako coś, co byłoby sensowne dla ludzi, więc wszystko można użyć wartości dla byłoby similiarity zamawiania.

Odpowiedział 04/08/2008 o 16:14
źródło użytkownik

głosy
2

Może wyglądać jak spam, ale nie, ten link jest naprawdę interesująca dla przestrzeni kolorów :)

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

Odpowiedział 04/08/2008 o 16:14
źródło użytkownik

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