web-dev-qa-db-fra.com

Comment comparer deux couleurs pour la similarité/différence

Je souhaite concevoir un programme qui puisse m'aider à évaluer entre 5 couleurs prédéfinies, laquelle ressemble le plus à une couleur variable et avec quel pourcentage. Le fait est que je ne sais pas comment le faire manuellement, étape par étape. Il est donc encore plus difficile de penser à un programme.

Plus de détails: Les couleurs proviennent de photographies de tubes avec gel de couleurs différentes. J'ai 5 tubes de couleurs différentes où chacun représente 1 des 5 niveaux. Je souhaite prendre des photos d'autres échantillons et évaluer sur ordinateur à quel niveau appartient cet échantillon en comparant les couleurs. Je souhaite également le savoir avec un pourcentage approximatif. Je voudrais un programme qui fait quelque chose comme ceci: http://www.colortools.net/color_matcher.html

Si vous pouvez me dire quelles sont les étapes à suivre, même si ce sont des choses pour moi de penser et de les faire manuellement. Ce serait très utile. 

151
Ana Fernandes

Voir l'article de Wikipedia sur Différence de couleurs pour les bons repères . Fondamentalement, vous voulez calculer une métrique de distance dans un espace colorimétrique multidimensionnel . Mais le RVB n'est pas "uniformément perceptuel", aussi votre métrique de distance RVB euclidienne suggéré par Vadim ne correspondra pas à la distance perçue par l’homme entre les couleurs. Pour commencer, La b * est censé être un espace colorimétrique perceptuellement uniforme, et la métrique deltaE est couramment utilisée. Mais il existe des espaces de couleurs plus raffinés et des formules deltaE plus raffinées qui se rapprochent de la perception humaine.

Vous devrez en apprendre davantage sur les espaces de couleurs et les illuminants pour effectuer les conversions. Mais pour une formule rapide meilleure que la métrique RVB euclidienne, procédez comme suit: supposez que vos valeurs RVB sont dans l’espace colorimétrique sRVB, recherchez les formules de conversion sRGB en La b *, convertissez vos couleurs sRVB en La b * et calculez deltaE entre vos deux valeurs La b *. Ce n'est pas coûteux en calcul, c'est juste des formules non linéaires et des multiplications et des ajouts.

118
Liudvikas Bukys

Juste une idée qui m'est venue à l’esprit (désolée si stupide)… .. Trois composantes de couleurs peuvent être supposées des coordonnées 3D de points et vous pouvez ensuite calculer la distance entre les points.

F.E. 

Point1 has R1 G1 B1
Point2 has R2 G2 B2

La distance entre les couleurs est 

d=sqrt((r2-r1)^2+(g2-g1)^2+(b2-b1)^2)

Le pourcentage est 

p=d/sqrt((255)^2+(255)^2+(255)^2)
39
Vadim Gulyakin

Une valeur de couleur a plus d'une dimension, il n'y a donc pas de moyen intrinsèque de comparer deux couleurs. Vous devez déterminer pour votre cas d'utilisation la signification des couleurs et par conséquent la meilleure façon de les comparer. 

Il est fort probable que vous souhaitiez comparer les propriétés de teinte, de saturation et/ou de luminosité des couleurs, par opposition aux composants rouge/vert/bleu. Si vous avez du mal à comprendre comment vous voulez les comparer, prenez quelques paires de couleurs et comparez-les mentalement, puis essayez de vous justifier/de vous expliquer pourquoi elles sont similaires/différentes. 

Une fois que vous avez identifié les propriétés/composants des couleurs que vous souhaitez comparer, vous devez déterminer comment extraire ces informations d’une couleur. 

Très probablement, vous aurez simplement besoin de convertir la couleur de la représentation courante RedGreenBlue en HueSaturationLightness, puis de calculer quelque chose comme: 

avghue = (color1.hue + color2.hue)/2
distance = abs(color1.hue-avghue)

Cet exemple vous donnerait une simple valeur scalaire indiquant la distance entre le dégradé et la teinte des couleurs.

Voir HSL et HSV sur Wikipedia .

21
Supr

Si vous avez deux objets Colorc1 et c2, vous pouvez simplement comparer chaque valeur RVB de c1 à celle de c2.

int diffRed   = Math.abs(c1.getRed()   - c2.getRed());
int diffGreen = Math.abs(c1.getGreen() - c2.getGreen());
int diffBlue  = Math.abs(c1.getBlue()  - c2.getBlue());

Ces valeurs que vous pouvez simplement diviser par la quantité de saturation de différence (255), et vous obtiendrez la différence entre les deux.

float pctDiffRed   = (float)diffRed   / 255;
float pctDiffGreen = (float)diffGreen / 255;
float pctDiffBlue   = (float)diffBlue  / 255;

Après quoi, vous pouvez simplement trouver la différence de couleur moyenne en pourcentage.

(pctDiffRed + pctDiffGreen + pctDiffBlue) / 3 * 100

Ce qui vous donnerait une différence de pourcentage entre c1 et c2.

20
kba

en fait, j'ai emprunté le même chemin il y a deux mois. il n'y a pas de réponse parfaite à la question (cela a été demandé ici plusieurs fois), mais il existe une réponse plus sophistiquée que la réponse sqrt (rr), etc., et plus facile à implémenter directement avec RGB sans passer à tout type de alterner les espaces de couleur. J'ai trouvé cette formule ici qui est une approximation peu coûteuse du réel relativement compliqué formule (par la CIE qui est le W3C de couleur, puisqu'il s'agit d'une quête non terminée, vous pouvez la trouver plus ancienne et plus simple. équations de différence de couleur là-bas). bonne chance

Edit: Pour la postérité, voici le code C correspondant:

typedef struct {
     unsigned char r, g, b;
} RGB;

double ColourDistance(RGB e1, RGB e2)
{
    long rmean = ( (long)e1.r + (long)e2.r ) / 2;
    long r = (long)e1.r - (long)e2.r;
    long g = (long)e1.g - (long)e2.g;
    long b = (long)e1.b - (long)e2.b;
    return sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
}
16
alonisser

Juste une autre réponse, même si elle ressemble à celle de Supr - juste un espace colorimétrique différent.

Le problème est le suivant: les humains ne perçoivent pas la différence de couleur de manière non uniforme et l’espace colorimétrique RVB l’ignore. En conséquence, si vous utilisez l'espace colorimétrique RVB et calculez simplement la distance euclidienne entre 2 couleurs, vous obtiendrez peut-être une différence mathématiquement tout à fait correcte, mais qui ne correspondrait pas à ce que les humains vous diraient.

Ce n’est peut-être pas un problème - la différence n’est pas très grande, mais si vous voulez résoudre ce problème, vous devez convertir vos couleurs RVB en un espace colorimétrique spécialement conçu pour éviter le problème susmentionné. Il y en a plusieurs, des améliorations par rapport aux modèles précédents (puisque ceci est basé sur la perception humaine, nous devons mesurer les valeurs "correctes" sur la base de données expérimentales). Il y a l'espace de couleurs Lab qui, à mon avis, serait le meilleur bien qu'il soit un peu compliqué de le convertir. Le plus simple serait le CIE XYZ .

Voici un site qui répertorie les formules à convertir entre différents espaces colorimétriques afin que vous puissiez expérimenter un peu.

9
Voo

Toutes les méthodes ci-dessous donnent une échelle de 0 à 100.

internal static class ColorDifference
{
    internal enum Method
    {
        Binary, // true or false, 0 is false
        Square,
        Dimensional,
        CIE76
    }

    public static double Calculate(Method method, int argb1, int argb2)
    {
        int[] c1 = ColorConversion.ArgbToArray(argb1);
        int[] c2 = ColorConversion.ArgbToArray(argb2);
        return Calculate(method, c1[1], c2[1], c1[2], c2[2], c1[3], c2[3], c1[0], c2[0]);
    }

    public static double Calculate(Method method, int r1, int r2, int g1, int g2, int b1, int b2, int a1 = -1, int a2 = -1)
    {
        switch (method)
        {
            case Method.Binary:
                return (r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2) ? 0 : 100;
            case Method.CIE76:
                return CalculateCIE76(r1, r2, g1, g2, b1, b2);
            case Method.Dimensional:
                if (a1 == -1 || a2 == -1) return Calculate3D(r1, r2, g1, g2, b1, b2);
                else return Calculate4D(r1, r2, g1, g2, b1, b2, a1, a2);
            case Method.Square:
                return CalculateSquare(r1, r2, g1, g2, b1, b2, a1, a2);
            default:
                throw new InvalidOperationException();
        }
    }

    public static double Calculate(Method method, Color c1, Color c2, bool alpha)
    {
        switch (method)
        {
            case Method.Binary:
                return (c1.R == c2.R && c1.G == c2.G && c1.B == c2.B && (!alpha || c1.A == c2.A)) ? 0 : 100;
            case Method.CIE76:
                if (alpha) throw new InvalidOperationException();
                return CalculateCIE76(c1, c2);
            case Method.Dimensional:
                if (alpha) return Calculate4D(c1, c2);
                else return Calculate3D(c1, c2);
            case Method.Square:
                if (alpha) return CalculateSquareAlpha(c1, c2);
                else return CalculateSquare(c1, c2);
            default:
                throw new InvalidOperationException();
        }
    }

    // A simple idea, based on on a Square
    public static double CalculateSquare(int argb1, int argb2)
    {
        int[] c1 = ColorConversion.ArgbToArray(argb1);
        int[] c2 = ColorConversion.ArgbToArray(argb2);
        return CalculateSquare(c1[1], c2[1], c1[2], c2[2], c1[3], c2[3]);
    }

    public static double CalculateSquare(Color c1, Color c2)
    {
        return CalculateSquare(c1.R, c2.R, c1.G, c2.G, c1.B, c2.B);
    }

    public static double CalculateSquareAlpha(int argb1, int argb2)
    {
        int[] c1 = ColorConversion.ArgbToArray(argb1);
        int[] c2 = ColorConversion.ArgbToArray(argb2);
        return CalculateSquare(c1[1], c2[1], c1[2], c2[2], c1[3], c2[3], c1[0], c2[0]);
    }

    public static double CalculateSquareAlpha(Color c1, Color c2)
    {
        return CalculateSquare(c1.R, c2.R, c1.G, c2.G, c1.B, c2.B, c1.A, c2.A);
    }

    public static double CalculateSquare(int r1, int r2, int g1, int g2, int b1, int b2, int a1 = -1, int a2 = -1)
    {
        if (a1 == -1 || a2 == -1) return (Math.Abs(r1 - r2) + Math.Abs(g1 - g2) + Math.Abs(b1 - b2)) / 7.65;
        else return (Math.Abs(r1 - r2) + Math.Abs(g1 - g2) + Math.Abs(b1 - b2) + Math.Abs(a1 - a2)) / 10.2;
    }

    // from:http://stackoverflow.com/questions/9018016/how-to-compare-two-colors
    public static double Calculate3D(int argb1, int argb2)
    {
        int[] c1 = ColorConversion.ArgbToArray(argb1);
        int[] c2 = ColorConversion.ArgbToArray(argb2);
        return Calculate3D(c1[1], c2[1], c1[2], c2[2], c1[3], c2[3]);
    }

    public static double Calculate3D(Color c1, Color c2)
    {
        return Calculate3D(c1.R, c2.R, c1.G, c2.G, c1.B, c2.B);
    }

    public static double Calculate3D(int r1, int r2, int g1, int g2, int b1, int b2)
    {
        return Math.Sqrt(Math.Pow(Math.Abs(r1 - r2), 2) + Math.Pow(Math.Abs(g1 - g2), 2) + Math.Pow(Math.Abs(b1 - b2), 2)) / 4.41672955930063709849498817084;
    }

    // Same as above, but made 4D to include alpha channel
    public static double Calculate4D(int argb1, int argb2)
    {
        int[] c1 = ColorConversion.ArgbToArray(argb1);
        int[] c2 = ColorConversion.ArgbToArray(argb2);
        return Calculate4D(c1[1], c2[1], c1[2], c2[2], c1[3], c2[3], c1[0], c2[0]);
    }

    public static double Calculate4D(Color c1, Color c2)
    {
        return Calculate4D(c1.R, c2.R, c1.G, c2.G, c1.B, c2.B, c1.A, c2.A);
    }

    public static double Calculate4D(int r1, int r2, int g1, int g2, int b1, int b2, int a1, int a2)
    {
        return Math.Sqrt(Math.Pow(Math.Abs(r1 - r2), 2) + Math.Pow(Math.Abs(g1 - g2), 2) + Math.Pow(Math.Abs(b1 - b2), 2) + Math.Pow(Math.Abs(a1 - a2), 2)) / 5.1;
    }

    /**
    * Computes the difference between two RGB colors by converting them to the L*a*b scale and
    * comparing them using the CIE76 algorithm { http://en.wikipedia.org/wiki/Color_difference#CIE76}
    */
    public static double CalculateCIE76(int argb1, int argb2)
    {
        return CalculateCIE76(Color.FromArgb(argb1), Color.FromArgb(argb2));
    }

    public static double CalculateCIE76(Color c1, Color c2)
    {
        return CalculateCIE76(c1.R, c2.R, c1.G, c2.G, c1.B, c2.B);
    }

    public static double CalculateCIE76(int r1, int r2, int g1, int g2, int b1, int b2)
    {
        int[] lab1 = ColorConversion.ColorToLab(r1, g1, b1);
        int[] lab2 = ColorConversion.ColorToLab(r2, g2, b2);
        return Math.Sqrt(Math.Pow(lab2[0] - lab1[0], 2) + Math.Pow(lab2[1] - lab1[1], 2) + Math.Pow(lab2[2] - lab1[2], 2)) / 2.55;
    }
}


internal static class ColorConversion
{

    public static int[] ArgbToArray(int argb)
    {
        return new int[] { (argb >> 24), (argb >> 16) & 0xFF, (argb >> 8) & 0xFF, argb & 0xFF };
    }

    public static int[] ColorToLab(int R, int G, int B)
    {
        // http://www.brucelindbloom.com

        double r, g, b, X, Y, Z, fx, fy, fz, xr, yr, zr;
        double Ls, fas, fbs;
        double eps = 216.0f / 24389.0f;
        double k = 24389.0f / 27.0f;

        double Xr = 0.964221f;  // reference white D50
        double Yr = 1.0f;
        double Zr = 0.825211f;

        // RGB to XYZ
        r = R / 255.0f; //R 0..1
        g = G / 255.0f; //G 0..1
        b = B / 255.0f; //B 0..1

        // assuming sRGB (D65)
        if (r <= 0.04045) r = r / 12;
        else r = (float)Math.Pow((r + 0.055) / 1.055, 2.4);

        if (g <= 0.04045) g = g / 12;
        else g = (float)Math.Pow((g + 0.055) / 1.055, 2.4);

        if (b <= 0.04045) b = b / 12;
        else b = (float)Math.Pow((b + 0.055) / 1.055, 2.4);

        X = 0.436052025f * r + 0.385081593f * g + 0.143087414f * b;
        Y = 0.222491598f * r + 0.71688606f * g + 0.060621486f * b;
        Z = 0.013929122f * r + 0.097097002f * g + 0.71418547f * b;

        // XYZ to Lab
        xr = X / Xr;
        yr = Y / Yr;
        zr = Z / Zr;

        if (xr > eps) fx = (float)Math.Pow(xr, 1 / 3.0);
        else fx = (float)((k * xr + 16.0) / 116.0);

        if (yr > eps) fy = (float)Math.Pow(yr, 1 / 3.0);
        else fy = (float)((k * yr + 16.0) / 116.0);

        if (zr > eps) fz = (float)Math.Pow(zr, 1 / 3.0);
        else fz = (float)((k * zr + 16.0) / 116);

        Ls = (116 * fy) - 16;
        fas = 500 * (fx - fy);
        fbs = 200 * (fy - fz);

        int[] lab = new int[3];
        lab[0] = (int)(2.55 * Ls + 0.5);
        lab[1] = (int)(fas + 0.5);
        lab[2] = (int)(fbs + 0.5);
        return lab;
    }
}
2
Vozzie

Le meilleur moyen est deltaE. DeltaE est un nombre qui montre la différence des couleurs. Si deltae <1, la différence ne peut pas être reconnue par les yeux humains. J'ai écrit un code dans canvas et js pour convertir rgb en laboratoire puis calculer delta e. Dans cet exemple, le code reconnaît les pixels de couleur différente avec une couleur de base que j'ai enregistrée sous LAB1. et si c'est différent, ces pixels deviennent rouges. Vous pouvez augmenter ou diminuer la sensibilité de la différence de couleur avec incrément ou réduire la plage acceptable de delta e. Dans cet exemple, j'ai affecté 10 à deltaE dans la ligne que j'ai écrite (deltae <= 10):

<script>   
  var constants = {
    canvasWidth: 700, // In pixels.
    canvasHeight: 600, // In pixels.
    colorMap: new Array() 
          };



  // -----------------------------------------------------------------------------------------------------

  function fillcolormap(imageObj1) {


    function rgbtoxyz(red1,green1,blue1){ // a converter for converting rgb model to xyz model
 var red2 = red1/255;
 var green2 = green1/255;
 var blue2 = blue1/255;
 if(red2>0.04045){
      red2 = (red2+0.055)/1.055;
      red2 = Math.pow(red2,2.4);
 }
 else{
      red2 = red2/12.92;
 }
 if(green2>0.04045){
      green2 = (green2+0.055)/1.055;
      green2 = Math.pow(green2,2.4);    
 }
 else{
      green2 = green2/12.92;
 }
 if(blue2>0.04045){
      blue2 = (blue2+0.055)/1.055;
      blue2 = Math.pow(blue2,2.4);    
 }
 else{
      blue2 = blue2/12.92;
 }
 red2 = (red2*100);
 green2 = (green2*100);
 blue2 = (blue2*100);
 var x = (red2 * 0.4124) + (green2 * 0.3576) + (blue2 * 0.1805);
 var y = (red2 * 0.2126) + (green2 * 0.7152) + (blue2 * 0.0722);
 var z = (red2 * 0.0193) + (green2 * 0.1192) + (blue2 * 0.9505);
 var xyzresult = new Array();
 xyzresult[0] = x;
 xyzresult[1] = y;
 xyzresult[2] = z;
 return(xyzresult);
} //end of rgb_to_xyz function
function xyztolab(xyz){ //a convertor from xyz to lab model
 var x = xyz[0];
 var y = xyz[1];
 var z = xyz[2];
 var x2 = x/95.047;
 var y2 = y/100;
 var z2 = z/108.883;
 if(x2>0.008856){
      x2 = Math.pow(x2,1/3);
 }
 else{
      x2 = (7.787*x2) + (16/116);
 }
 if(y2>0.008856){
      y2 = Math.pow(y2,1/3);
 }
 else{
      y2 = (7.787*y2) + (16/116);
 }
 if(z2>0.008856){
      z2 = Math.pow(z2,1/3);
 }
 else{
      z2 = (7.787*z2) + (16/116);
 }
 var l= 116*y2 - 16;
 var a= 500*(x2-y2);
 var b= 200*(y2-z2);
 var labresult = new Array();
 labresult[0] = l;
 labresult[1] = a;
 labresult[2] = b;
 return(labresult);

}

    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext('2d');
    var imageX = 0;
    var imageY = 0;

    context.drawImage(imageObj1, imageX, imageY, 240, 140);
    var imageData = context.getImageData(0, 0, 240, 140);
    var data = imageData.data;
    var n = data.length;
   // iterate over all pixels

    var m = 0;
    for (var i = 0; i < n; i += 4) {
      var red = data[i];
      var green = data[i + 1];
      var blue = data[i + 2];
    var xyzcolor = new Array();
    xyzcolor = rgbtoxyz(red,green,blue);
    var lab = new Array();
    lab = xyztolab(xyzcolor);
    constants.colorMap.Push(lab); //fill up the colormap array with lab colors.         
      } 

  }

// ---------------------------------------------------- -------------------------------------------------- --- 

    function colorize(pixqty) {

         function deltae94(lab1,lab2){    //calculating Delta E 1994

         var c1 = Math.sqrt((lab1[1]*lab1[1])+(lab1[2]*lab1[2]));
         var c2 =  Math.sqrt((lab2[1]*lab2[1])+(lab2[2]*lab2[2]));
         var dc = c1-c2;
         var dl = lab1[0]-lab2[0];
         var da = lab1[1]-lab2[1];
         var db = lab1[2]-lab2[2];
         var dh = Math.sqrt((da*da)+(db*db)-(dc*dc));
         var first = dl;
         var second = dc/(1+(0.045*c1));
         var third = dh/(1+(0.015*c1));
         var deresult = Math.sqrt((first*first)+(second*second)+(third*third));
         return(deresult);
          } // end of deltae94 function
    var lab11 =  new Array("80","-4","21");
    var lab12 = new Array();
    var k2=0;
    var canvas = document.getElementById('myCanvas');
                                        var context = canvas.getContext('2d');
                                        var imageData = context.getImageData(0, 0, 240, 140);
                                        var data = imageData.data;

    for (var i=0; i<pixqty; i++) {

    lab12 = constants.colorMap[i];

    var deltae = deltae94(lab11,lab12);     
                                        if (deltae <= 10) {

                                        data[i*4] = 255;
                                        data[(i*4)+1] = 0;
                                        data[(i*4)+2] = 0;  
                                        k2++;
                                        } // end of if 
                                } //end of for loop
    context.clearRect(0,0,240,140);
    alert(k2);
    context.putImageData(imageData,0,0);
} 
// -----------------------------------------------------------------------------------------------------

$(window).load(function () {    
  var imageObj = new Image();
  imageObj.onload = function() {
  fillcolormap(imageObj);    
  }
  imageObj.src = './mixcolor.png';
});

// ---------------------------------------------------------------------------------------------------
 var pixno2 = 240*140; 
 </script>
2
Iman Sedighi

J'espère que vous souhaitez analyser une image complète à la fin, n'est-ce pas? Vous pouvez donc vérifier la différence la plus petite/la plus élevée par rapport à la matrice de couleurs d'identité. 

La plupart des opérations mathématiques de traitement graphique utilisent des matrices, car les algorithmes possibles les utilisant sont souvent plus rapides que les calculs classiques de distance par point et de comparisme. (par exemple, pour des opérations utilisant DirectX, OpenGL, ...)

Donc, je pense que vous devriez commencer ici:

http://en.wikipedia.org/wiki/Identity_matrix

http://en.wikipedia.org/wiki/Matrix_difference_equation

... et comme Beska a déjà commenté ci-dessus:

Cela peut ne pas donner la meilleure différence "visible" ...

Ce qui signifie également que votre algorithme dépend de votre définition de "similaire à" si vous traitez des images.

1
Beachwalker

Une méthode simple qui utilise uniquement RVB est

cR=R1-R2 
cG=G1-G2 
cB=B1-B2 
uR=R1+R2 
distance=cR*cR*(2+uR/256) + cG*cG*4 + cB*cB*(2+(255-uR)/256)

Je l'utilise depuis un moment et il fonctionne assez bien pour la plupart des objectifs.

1
Bob Pickle

Pour rapide et sale, vous pouvez faire

import Java.awt.Color;
private Color dropPrecision(Color c,int threshold){
    return new Color((c.getRed()/threshold),
                     (c.getGreen()/threshold),
                     (c.getBlue()/threshold));
}
public boolean inThreshold(Color _1,Color _2,int threshold){
    return dropPrecision(_1,threshold)==dropPrecision(_2,threshold);
}

utilisant la division entière pour quantifier les couleurs.

0
Austin_Anderson

La seule "bonne" façon de comparer les couleurs est de le faire avec deltaE dans CIELab ou CIELuv.

Mais pour beaucoup d'applications, je pense que c'est une approximation assez bonne:

distance = 3 * |dR| + 4 * |dG| + 3 * |dB|

Je pense qu'une distance pondérée de manhattan est beaucoup plus logique lorsque l'on compare des couleurs. Rappelez-vous que les couleurs primaires ne sont que dans notre tête. Ils n'ont aucune signification physique. CIELab et CIELuv sont modélisés statistiquement à partir de notre perception de la couleur.

0
onemasse

J'ai essayé diverses méthodes telles que l'espace colorimétrique LAB et les comparaisons HSV et j'ai constaté que la luminosité fonctionnait plutôt bien à cet effet.

Voici la version Python

def lum(c):
    def factor(component):
        component = component / 255;
        if (component <= 0.03928):
            component = component / 12.92;
        else:
            component = math.pow(((component + 0.055) / 1.055), 2.4);

        return component
    components = [factor(ci) for ci in c]

    return (components[0] * 0.2126 + components[1] * 0.7152 + components[2] * 0.0722) + 0.05;

def color_distance(c1, c2):

    l1 = lum(c1)
    l2 = lum(c2)
    higher = max(l1, l2)
    lower = min(l1, l2)

    return (higher - lower) / higher


c1 = ImageColor.getrgb('white')
c2 = ImageColor.getrgb('yellow')
print(color_distance(c1, c2))

Te donnera

0.0687619047619048
0
Tadas Šubonis

Je l'ai utilisé dans mon Android et cela semble satisfaisant bien que l'espace RGB ne soit pas recommandé:

    public double colourDistance(int red1,int green1, int blue1, int red2, int green2, int blue2)
{
      double rmean = ( red1 + red2 )/2;
    int r = red1 - red2;
    int g = green1 - green2;
    int b = blue1 - blue2;
    double weightR = 2 + rmean/256;
    double weightG = 4.0;
    double weightB = 2 + (255-rmean)/256;
    return Math.sqrt(weightR*r*r + weightG*g*g + weightB*b*b);
}

Ensuite, j'ai utilisé les éléments suivants pour obtenir un pourcentage de similarité:

double maxColDist = 764.8339663572415;
double d1 = colourDistance(red1,green1,blue1,red2,green2,blue2);
String s1 = (int) Math.round(((maxColDist-d1)/maxColDist)*100) + "% match";

Ça marche assez bien.

0
SimpleCoder

Vous devez convertir les couleurs RVB dans l'espace colorimétrique Lab pour pouvoir les comparer de la manière dont les humains les voient. Sinon, vous obtiendrez des couleurs RVB qui "correspondent" d'une manière très étrange.

Le lien wikipedia sur Différences de couleurs vous donne une introduction aux différents algorithmes de différence d'espaces de couleurs de Lab définis au fil des ans. Le plus simple qui vérifie simplement la distance euclidienne des deux couleurs de laboratoire fonctionne, mais présente quelques défauts. 

De manière pratique, il existe une implémentation Java de l'algorithme plus sophistiqué CIEDE2000 dans le projet OpenIMAJ . Fournissez-lui vos deux jeux de couleurs Lab et vous obtiendrez une valeur de distance unique.

0
AiTuDou