algorithm समानता/अंतर के लिए दो रंगों की तुलना कैसे करें




colors compare (12)

वास्तव में मैं कुछ महीने पहले एक ही रास्ते पर चला गया। इस सवाल का कोई सही जवाब नहीं है (जिसे here कुछ समय से पूछा गया था) लेकिन एक और परिष्कृत है तो एसकर्ट (आरआर) इत्यादि उत्तर और आरजीबी के साथ सीधे सभी प्रकार के वैकल्पिक रंगों को स्थानांतरित किए बिना इम्प्लांट करना अधिक आसान है। मुझे यह सूत्र here मिला here जो काफी जटिल वास्तविक formula का कम लागत अनुमान formula (सीआईई द्वारा जो रंग का डब्ल्यू 3 सी है, क्योंकि यह एक पूर्ण खोज नहीं है, आप वहां पुराने और सरल रंग अंतर समीकरण पा सकते हैं)। सौभाग्य

संपादित करें: वंशावली के लिए, यहां प्रासंगिक सी कोड है:

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

मैं एक प्रोग्राम तैयार करना चाहता हूं जो मुझे 5 पूर्व-परिभाषित रंगों के बीच आकलन करने में मदद कर सकता है, जो एक परिवर्तनीय रंग के समान है, और किस प्रतिशत के साथ। बात यह है कि मुझे नहीं पता कि मैन्युअल रूप से कदम से कैसे कदम उठाना है। तो एक कार्यक्रम के बारे में सोचना और भी मुश्किल है।

अधिक जानकारी: रंग जेल के साथ ट्यूबों की तस्वीरों से हैं जो विभिन्न रंगों के रूप में हैं। मेरे पास अलग-अलग रंगों के साथ 5 ट्यूब हैं जिनमें से प्रत्येक 5 स्तरों में से 1 का प्रतिनिधि है। मैं अन्य नमूनों की तस्वीर लेना चाहता हूं और कंप्यूटर पर आकलन करना चाहता हूं कि नमूना रंगों की तुलना करके कौन सा स्तर है, और मैं जानना चाहता हूं कि अनुमान के प्रतिशत के साथ भी। मुझे ऐसा प्रोग्राम चाहिए जो ऐसा कुछ करता है: http://www.colortools.net/color_matcher.html

यदि आप मुझे बता सकते हैं कि कौन से कदम उठाने हैं, भले ही वे मेरे लिए सोचें और मैन्युअल रूप से करें। यह बहुत उपयोगी होगा।


जल्दी और गंदे के लिए, आप कर सकते हैं

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

रंगों को मापने के लिए पूर्णांक विभाजन का उपयोग करना।


नीचे दिए गए सभी विधियों के परिणामस्वरूप 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://.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;
    }
}

बस एक और जवाब, हालांकि यह Supr के समान है - बस एक अलग रंग स्थान।

बात यह है कि: मनुष्य रंग में अंतर को समान रूप से नहीं समझते हैं और आरजीबी रंग की जगह इसे अनदेखा कर रही है। नतीजतन यदि आप आरजीबी कलर स्पेस का उपयोग करते हैं और सिर्फ 2 रंगों के बीच यूक्लिडियन दूरी की गणना करते हैं तो आपको एक अंतर मिल सकता है जो गणितीय रूप से बिल्कुल सही है, लेकिन मनुष्य जो आपको बताएगा उसके साथ मेल नहीं खाएगा।

यह कोई समस्या नहीं हो सकती है - अंतर इतना बड़ा नहीं है, लेकिन यदि आप इसे "बेहतर" हल करना चाहते हैं तो आपको अपने आरजीबी रंगों को एक रंगीन जगह में परिवर्तित करना चाहिए जो विशेष रूप से उपरोक्त समस्या से बचने के लिए डिज़ाइन किया गया था। कई मॉडल हैं, पहले के मॉडल से सुधार (चूंकि यह मानव धारणा पर आधारित है, हमें प्रयोगात्मक डेटा के आधार पर "सही" मानों को मापने की आवश्यकता है)। लैब रंगस्थान है जो मुझे लगता है कि यह सबसे अच्छा होगा हालांकि इसे बदलने के लिए थोड़ा जटिल है। सरल सीआईई XYZ एक होगा।

यहां एक ऐसी साइट है जो फॉर्मूला को विभिन्न रंग रिक्त स्थानों के बीच कनवर्ट करने के लिए सूचीबद्ध करती है ताकि आप थोड़ा प्रयोग कर सकें।


एक रंग मान में एक से अधिक आयाम होते हैं, इसलिए दो रंगों की तुलना करने का कोई आंतरिक तरीका नहीं है। आपको अपने उपयोग के मामले को रंगों का अर्थ निर्धारित करना होगा और इस प्रकार उनकी तुलना सर्वोत्तम तरीके से करें।

सबसे अधिक संभावना है कि आप लाल / हरे / नीले रंग के घटकों के विपरीत रंगों के रंग, संतृप्ति और / या हल्के गुणों की तुलना करना चाहते हैं। यदि आपको यह पता लगाने में परेशानी हो रही है कि आप उनकी तुलना कैसे करना चाहते हैं, तो नमूना रंगों के कुछ जोड़े लें और मानसिक रूप से उनकी तुलना करें, फिर अपने आप को उचित / समझाएं कि वे समान / अलग क्यों हैं।

एक बार जब आप जानते हैं कि रंगों के कौन से गुण / घटक आप तुलना करना चाहते हैं, तो आपको यह पता लगाना होगा कि उस जानकारी को रंग से कैसे निकालना है।

सबसे अधिक संभावना है कि आपको रंग को सामान्य RedGreenBlue प्रतिनिधित्व से HueSaturationLightness में परिवर्तित करने की आवश्यकता होगी, और उसके बाद कुछ की गणना करें

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

यह उदाहरण आपको एक साधारण स्केलर मान देगा जो दर्शाता है कि रंगों के ढाल / रंग एक-दूसरे से कितने दूर हैं।

विकिपीडिया पर एचएसएल और एचएसवी देखें।


सबसे अच्छा तरीका डेल्टा है। डेल्टाई एक संख्या है जो रंगों का अंतर दिखाती है। यदि डेल्टा <1 तो अंतर मानव आंखों द्वारा पहचाना नहीं जा सकता है। मैंने आरजीबी को प्रयोगशाला में परिवर्तित करने के लिए कैनवास और जेएस में एक कोड लिखा और फिर डेल्टा ई की गणना की। इस उदाहरण पर कोड पिक्सेल को पहचान रहा है जिसमें मूल रंग के साथ अलग रंग है जिसे मैंने LAB1 के रूप में सहेजा था। और फिर यदि यह अलग है तो उन पिक्सल लाल हो जाता है। आप डेल्टा ई की स्वीकार्य सीमा को बढ़ाने या घटाने के साथ रंग अंतर की संवेदनशीलता को बढ़ा या घटा सकते हैं। इस उदाहरण में मैंने लाइन में डेल्टा के लिए 10 को असाइन किया था जिसे मैंने लिखा था (डेल्टा <= 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>

सही लीड के लिए en.wikipedia.org/wiki/Color_difference पर विकिपीडिया का आलेख देखें। असल में, आप कुछ बहुआयामी रंगस्थान में दूरी मीट्रिक की गणना करना चाहते हैं। लेकिन आरजीबी "अवधारणात्मक वर्दी" नहीं है, इसलिए वादिम द्वारा सुझाए गए यूक्लिडियन आरजीबी दूरी मीट्रिक रंगों के बीच मानव-अनुमानित दूरी से मेल नहीं खाएगा। शुरुआत के लिए, एल बी * एक अवधारणात्मक वर्दी स्पेस होने का इरादा है, और डेल्टा मेट्रिक का आमतौर पर उपयोग किया जाता है। लेकिन वहां अधिक परिष्कृत रंगस्थान और अधिक परिष्कृत डेल्टा सूत्र हैं जो मानव धारणा से मेल खाते हैं।

आपको रूपांतरण करने के लिए रंगों और प्रकाशकों के बारे में और जानना होगा। लेकिन यूक्लिडियन आरजीबी मीट्रिक से बेहतर एक त्वरित सूत्र के लिए, बस ऐसा करें: मान लीजिए कि आपके आरजीबी मूल्य एसआरबीबी रंगस्थान में हैं, एसआरबीबी को एल बी * रूपांतरण सूत्रों में ढूंढें, अपने एसआरबीबी रंगों को एल बी * में परिवर्तित करें, और अपने दो एल बी * मानों के बीच डेल्टा की गणना करें। यह कम्प्यूटेशनल रूप से महंगा नहीं है, यह केवल कुछ nonlinear सूत्र हैं और कुछ गुणा और जोड़ता है।


मानव धारणा से दो रंगों की तुलना करने के सर्वोत्तम तरीकों में से एक सीआईई 76 है। अंतर डेल्टा-ई कहा जाता है। जब यह 1 से कम होता है, तो मानव आंख अंतर को पहचान नहीं सकती है।

अद्भुत कलर यूटिलिटीज क्लास कलरयूट्स (नीचे कोड) है, जिसमें सीआईई 76 तुलना विधियां शामिल हैं। यह ड्यूरि स्ट्रेबेल, ज़्यूरिख विश्वविद्यालय द्वारा लिखा गया है।

ColorUtils.class से मैं विधि का उपयोग करता हूं:

static double colorDifference(int r1, int g1, int b1, int r2, int g2, int b2)

आर 1, जी 1, बी 1 - पहले रंग के आरजीबी मूल्य

आर 2, जी 2, बी 2 - आरजीबी मूल्य दूसरे रंग के बराबर है जिसे आप तुलना करना चाहते हैं

यदि आप एंड्रॉइड के साथ काम करते हैं, तो आप इन मानों को इस तरह प्राप्त कर सकते हैं:

r1 = Color.red(pixel);

g1 = Color.green(pixel);

b1 = Color.blue(pixel);

डैनियल स्ट्रेबेल, ज़्यूरिख विश्वविद्यालय द्वारा ColorUtils.class:

import android.graphics.Color;

public class ColorUtil {
public static int argb(int R, int G, int B) {
    return argb(Byte.MAX_VALUE, R, G, B);
}

public static int argb(int A, int R, int G, int B) {
    byte[] colorByteArr = {(byte) A, (byte) R, (byte) G, (byte) B};
    return byteArrToInt(colorByteArr);
}

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

public static int byteArrToInt(byte[] colorByteArr) {
    return (colorByteArr[0] << 24) + ((colorByteArr[1] & 0xFF) << 16)
            + ((colorByteArr[2] & 0xFF) << 8) + (colorByteArr[3] & 0xFF);
}

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

    float r, g, b, X, Y, Z, fx, fy, fz, xr, yr, zr;
    float Ls, as, bs;
    float eps = 216.f / 24389.f;
    float k = 24389.f / 27.f;

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

    // RGB to XYZ
    r = R / 255.f; //R 0..1
    g = G / 255.f; //G 0..1
    b = B / 255.f; //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.);
    else
        fx = (float) ((k * xr + 16.) / 116.);

    if (yr > eps)
        fy = (float) Math.pow(yr, 1 / 3.);
    else
        fy = (float) ((k * yr + 16.) / 116.);

    if (zr > eps)
        fz = (float) Math.pow(zr, 1 / 3.);
    else
        fz = (float) ((k * zr + 16.) / 116);

    Ls = (116 * fy) - 16;
    as = 500 * (fx - fy);
    bs = 200 * (fy - fz);

    int[] lab = new int[3];
    lab[0] = (int) (2.55 * Ls + .5);
    lab[1] = (int) (as + .5);
    lab[2] = (int) (bs + .5);
    return lab;
}

/**
 * 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 getColorDifference(int a, int b) {
    int r1, g1, b1, r2, g2, b2;
    r1 = Color.red(a);
    g1 = Color.green(a);
    b1 = Color.blue(a);
    r2 = Color.red(b);
    g2 = Color.green(b);
    b2 = Color.blue(b);
    int[] lab1 = rgb2lab(r1, g1, b1);
    int[] lab2 = rgb2lab(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));
}
}

रंगों की तुलना करने का एकमात्र "सही" तरीका यह है कि इसे CIELab या CIELuv में डेल्टा के साथ करना है।

लेकिन बहुत सारे अनुप्रयोगों के लिए मुझे लगता है कि यह काफी अच्छा अनुमान है:

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

मुझे लगता है कि रंगों की तुलना करते समय भारित मैनहट्टन दूरी बहुत अधिक समझ में आता है। याद रखें कि रंग प्राइमरी केवल हमारे सिर में हैं। उनके पास कोई भौतिक महत्व नहीं है। CIELab और CIELuv रंग की हमारी धारणा से सांख्यिकीय रूप से मॉडलिंग किया गया है।


सिर्फ एक विचार है कि पहले मेरे दिमाग में आया था (माफ करना अगर बेवकूफ)। रंगों के तीन घटकों को अंक के 3 डी निर्देशांक माना जा सकता है और फिर आप अंक के बीच दूरी की गणना कर सकते हैं।

एफई

Point1 has R1 G1 B1
Point2 has R2 G2 B2

रंगों के बीच दूरी है

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

प्रतिशत है

p=d/sqrt((255)^2+(255)^2+(255)^2)

एक साधारण विधि जो केवल आरजीबी का उपयोग करती है

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)

मैंने इसे थोड़ी देर के लिए इस्तेमाल किया है, और यह ज्यादातर उद्देश्यों के लिए काफी अच्छा काम करता है।


आपको किसी भी आरजीबी रंग को लैब कलर स्पेस में कनवर्ट करने की आवश्यकता होगी ताकि उन्हें उन तरीकों से तुलना करने में सक्षम बनाया जा सके जो मनुष्य उन्हें देखते हैं। अन्यथा आपको आरजीबी रंग मिलेंगे जो कुछ अजीब तरीके से 'मैच' करते हैं।

en.wikipedia.org/wiki/Color_difference पर विकिपीडिया लिंक आपको विभिन्न लैब रंग अंतरिक्ष अंतर एल्गोरिदम में एक परिचय देता है जिसे वर्षों से परिभाषित किया गया है। सबसे आसान है कि केवल दो प्रयोगशाला रंगों की यूक्लिडियन दूरी की जांच करता है, लेकिन कुछ त्रुटियां हैं।

सुविधाजनक रूप से OpenIMAJ प्रोजेक्ट में अधिक परिष्कृत CIEDE2000 एल्गोरिदम का जावा कार्यान्वयन है। इसे लैब रंगों के अपने दो सेट प्रदान करें और यह आपको एकल दूरी मान वापस देगा।







hsv