Followup: Trouver une « distance » précise entre les couleurs

voix
44

question d'origine

Je cherche une fonction qui tente de quantifier la « distance » (ou distincts) deux couleurs. Cette question est vraiment en deux parties:

  1. Quel espace couleur représente le mieux la vision humaine?
  2. Quelle distance métrique dans cet espace représente le mieux la vision humaine (euclidienne?)
Créé 04/08/2008 à 16:08
source utilisateur
Dans d'autres langues...                            


8 réponses

voix
43

Convertir à La * b * (alias tout simplement « Lab », et vous verrez également référence à « CIELAB »). Une bonne measaure rapide de différence de couleur est

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

les scientifiques de couleur ont d'autres mesures plus raffinées, qui peuvent ne pas être vaut le dérange pas, en fonction de la précision nécessaire pour ce que vous faites.

Les aet les bvaleurs représentent des couleurs opposées d'une manière similaire à la façon dont les cônes fonctionnent et peuvent être négatifs ou positifs. Les couleurs neutres - blanc, gris sont a=0, b=0. La Lest la luminosité définie d'une manière particulière, à partir de zéro (obscurité pure) jusqu'à que ce soit.

explication brute: >> En raison d'une couleur, nos yeux font la distinction entre deux grandes gammes de longueurs d'onde - bleu vs longueurs d'onde plus longues. puis, grâce à une mutation génétique plus récente, les cônes de longueur d'onde plus bifurqué en deux, pour nous distinguer rouge vs vert.

Soit dit en passant, ce sera grand pour votre carrière à élever au-dessus de vos couleurs homme des cavernes qui connaissent collegues que « RVB » ou « CMJN » qui sont grands pour les appareils mais sucent pour le travail de perception sérieuse. J'ai travaillé pour les scientifiques d'imagerie qui ne connaissent pas une chose à propos de ce genre de choses!

Pour plus de plaisir à lire sur la théorie de la différence de couleur, essayez:

Plus de détails sur Lab http://en.kioskea.net/video/cie-lab.php3 je ne peux pas à ce moment trouver une page non-laid qui avait fait les formules de conversion , mais je suis sûr que quelqu'un va modifier ce répondre à inclure un.

Créé 16/09/2008 à 17:08
source utilisateur

voix
8

comme lien cmetric.htm moi a échoué pour ci - dessus, ainsi que beaucoup d' autres implémentations pour la distance de couleur que je trouve (après une très longue jurney ..) comment calculer la meilleure distance de couleur, et .. plus scientifiquement précise un: deltaE et de 2 (!) valeurs RVB en utilisant OpenCV:

Cela a nécessité 3 conversions d'espace couleur + une conversion de code de javascript ( http://svn.int64.org/viewvc/int64/colors/colors.js ) à C ++

Et enfin le code (semble fonctionner dès la sortie de la boîte, l'espoir ne trouve un bug sérieux là-bas ... mais il semble bien après un certain nombre de 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 );
}

Il aide quelqu'un l'espoir :)

Créé 17/10/2013 à 02:39
source utilisateur

voix
4

HSL et HSV sont meilleurs pour la perception humaine des couleurs. Selon Wikipedia :

Il est parfois préférable de travailler avec des matériaux d'art, des images numérisées, ou d'autres médias, d'utiliser le modèle de couleur HSV ou HSL par rapport aux modèles alternatifs tels que RVB ou CMJN, en raison des différences dans la façon dont les modèles imitent la façon dont les humains perçoivent les couleurs. RGB et CMYK sont des modèles additifs et soustractifs, respectivement, la modélisation de la façon que les lumières de couleurs primaires ou de pigments (respectivement) se combinent pour former de nouvelles couleurs lorsqu'ils sont mélangés.

Représentation graphique du HSV

Créé 04/08/2008 à 16:16
source utilisateur

voix
3

L' article de Wikipédia sur les différences de couleurs énumère un certain nombre d'espaces de couleurs et de métriques de distance conçus pour convenir avec la perception humaine des distances de couleur.

Créé 24/08/2008 à 16:38
source utilisateur

voix
2

Comme quelqu'un qui est daltonien Je crois qu'il est bon d'essayer d'ajouter plus de séparation puis une vision normale. La forme la plus courante de daltonisme est une carence rouge / vert. Cela ne signifie pas que vous ne pouvez pas voir rouge ou vert, cela signifie qu'il est plus difficile de voir et plus difficile de voir les différences. Il faut donc une séparation plus grande avant qu'une personne aveugle couleur peut faire la différence.

Créé 16/09/2008 à 17:45
source utilisateur

voix
2

Eh bien, comme un premier point d'appel, je dirais que des mesures communes HSV (teinte, saturation et valeur) ou HSL sont mieux représentatifs de la façon dont les humains perçoivent les couleurs que dire RVB ou CMJN. Voir HSL, HSV sur Wikipedia .

Je suppose naïvement je tracer les points dans l'espace HSL pour les deux couleurs et calculer l'amplitude du vecteur de différence. Cependant, cela signifierait que serait considéré comme jaune vif et vert clair aussi différent que le vert au vert foncé. Mais beaucoup considèrent deux couleurs différentes rouges et roses.

De plus, les vecteurs de différence dans la même direction dans cet espace de paramètres ne sont pas égales. Par exemple, l'œil humain prend vert beaucoup mieux que d'autres couleurs. Un changement de teinte de vert par la même quantité que le passage du rouge peut sembler plus grand. En outre un changement de saturation d'une petite quantité à zéro est la différence entre gris et rose, ailleurs le changement serait la différence entre deux nuances de rouge.

D'un point de vue de programmeurs, vous devez tracer les vecteurs de différence, mais modifiée par une matrice de proportionnalité qui ajuster les longueurs en conséquence dans les différentes régions de l'espace HSL - ce serait assez arbitraire et serait basée sur différentes idées de la théorie des couleurs, mais être modifié en fonction assez arbitraire sur ce que vous vouliez appliquer à.

Mieux encore, vous pouvez voir si quelqu'un a déjà fait une telle chose en ligne ...

Créé 04/08/2008 à 16:37
source utilisateur

voix
2

Le moyen le plus loin serait bien sûr de considérer que les couleurs en tant que vecteurs 3D provenant de la même origine, et en prenant la distance entre leurs points d'extrémité.

Si vous devez tenir compte de facteurs tels que le vert est plus important pour juger de l'intensité, vous pouvez peser les valeurs.

ImageMagic fournit les échelles suivantes:

  • rouge: 0,3
  • vert: 0,6
  • bleu: 0,1

Bien sûr, des valeurs comme celle-ci ne seraient significatives par rapport à d'autres valeurs pour d'autres couleurs, non pas comme quelque chose qui serait utile à l'homme, tout ce que vous pouvez utiliser les valeurs serait similiarity ordre.

Créé 04/08/2008 à 16:14
source utilisateur

voix
2

Peut ressembler à spam, mais non, ce lien est vraiment intéressant pour les espaces de couleur :)

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

Créé 04/08/2008 à 16:14
source utilisateur

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