I\'m trying to find a way to compare two colors to find out how much they are alike. I can\'t seem to find any resources about the subject so I\'m hoping to get some pointer
Converting the RGB color to the HSL color space often produces good results. Check wikipedia for the conversion formula. It is up to you to assign weights to the differences in H, the color, S, how 'deep' the color is and L, how bright it is.
Colors have different weights affecting human eye. So convert the colors to grayscale using their calculated weights:
Gray Color = .11 * B + .59 * G + .30 * R
And your difference will be
difference = (GrayColor1 - GrayColor2) * 100.0 / 255.0
with difference ranging from 0-100.
This is actually commonly used and very simple approach thats used calculating image differences in image procesing.
-edit this is the very simple and still usable formula - even in commercial applications. If you want to go deep you should check out the color difference methods called: CIE1976, CIE1994, CIE2000 and CMC Here you can find some more detailed info: http://en.wikipedia.org/wiki/Color_difference
I found a interesting approach called Colour metric and adapted it to C#
public static double ColourDistance(Color e1, Color 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 Math.Sqrt((((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8));
}
Something like this:
public static int CompareColors(Color a, Color b)
{
return 100 * (int)(
1.0 - ((double)(
Math.Abs(a.R - b.R) +
Math.Abs(a.G - b.G) +
Math.Abs(a.B - b.B)
) / (256.0 * 3))
);
}
I've translated the code for DeltaE2000 on Bruce Lindbloom's page into C.
Here:
//
// deltae2000.c
//
// Translated by Dr Cube on 10/1/16.
// Translated to C from this javascript code written by Bruce LindBloom:
// http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE2000.html
// http://www.brucelindbloom.com/javascript/ColorDiff.js
#include <stdio.h>
#include <math.h>
#define Lab2k struct Lab2kStruct
Lab2k
{
float L;
float a;
float b;
};
// function expects Lab where: 0 >= L <=100.0 , -100 >=a <= 100.0 and -100 >= b <= 100.0
float
DeltaE2000(Lab2k Lab1,Lab2k Lab2)
{
float kL = 1.0;
float kC = 1.0;
float kH = 1.0;
float lBarPrime = 0.5 * (Lab1.L + Lab2.L);
float c1 = sqrtf(Lab1.a * Lab1.a + Lab1.b * Lab1.b);
float c2 = sqrtf(Lab2.a * Lab2.a + Lab2.b * Lab2.b);
float cBar = 0.5 * (c1 + c2);
float cBar7 = cBar * cBar * cBar * cBar * cBar * cBar * cBar;
float g = 0.5 * (1.0 - sqrtf(cBar7 / (cBar7 + 6103515625.0))); /* 6103515625 = 25^7 */
float a1Prime = Lab1.a * (1.0 + g);
float a2Prime = Lab2.a * (1.0 + g);
float c1Prime = sqrtf(a1Prime * a1Prime + Lab1.b * Lab1.b);
float c2Prime = sqrtf(a2Prime * a2Prime + Lab2.b * Lab2.b);
float cBarPrime = 0.5 * (c1Prime + c2Prime);
float h1Prime = (atan2f(Lab1.b, a1Prime) * 180.0) / M_PI;
float dhPrime; // not initialized on purpose
if (h1Prime < 0.0)
h1Prime += 360.0;
float h2Prime = (atan2f(Lab2.b, a2Prime) * 180.0) / M_PI;
if (h2Prime < 0.0)
h2Prime += 360.0;
float hBarPrime = (fabsf(h1Prime - h2Prime) > 180.0) ? (0.5 * (h1Prime + h2Prime + 360.0)) : (0.5 * (h1Prime + h2Prime));
float t = 1.0 -
0.17 * cosf(M_PI * ( hBarPrime - 30.0) / 180.0) +
0.24 * cosf(M_PI * (2.0 * hBarPrime ) / 180.0) +
0.32 * cosf(M_PI * (3.0 * hBarPrime + 6.0) / 180.0) -
0.20 * cosf(M_PI * (4.0 * hBarPrime - 63.0) / 180.0);
if (fabsf(h2Prime - h1Prime) <= 180.0)
dhPrime = h2Prime - h1Prime;
else
dhPrime = (h2Prime <= h1Prime) ? (h2Prime - h1Prime + 360.0) : (h2Prime - h1Prime - 360.0);
float dLPrime = Lab2.L - Lab1.L;
float dCPrime = c2Prime - c1Prime;
float dHPrime = 2.0 * sqrtf(c1Prime * c2Prime) * sinf(M_PI * (0.5 * dhPrime) / 180.0);
float sL = 1.0 + ((0.015 * (lBarPrime - 50.0) * (lBarPrime - 50.0)) / sqrtf(20.0 + (lBarPrime - 50.0) * (lBarPrime - 50.0)));
float sC = 1.0 + 0.045 * cBarPrime;
float sH = 1.0 + 0.015 * cBarPrime * t;
float dTheta = 30.0 * expf(-((hBarPrime - 275.0) / 25.0) * ((hBarPrime - 275.0) / 25.0));
float cBarPrime7 = cBarPrime * cBarPrime * cBarPrime * cBarPrime * cBarPrime * cBarPrime * cBarPrime;
float rC = sqrtf(cBarPrime7 / (cBarPrime7 + 6103515625.0));
float rT = -2.0 * rC * sinf(M_PI * (2.0 * dTheta) / 180.0);
return(sqrtf(
(dLPrime / (kL * sL)) * (dLPrime / (kL * sL)) +
(dCPrime / (kC * sC)) * (dCPrime / (kC * sC)) +
(dHPrime / (kH * sH)) * (dHPrime / (kH * sH)) +
(dCPrime / (kC * sC)) * (dHPrime / (kH * sH)) * rT
)
);
}
Colour perception depends on many factors and similarity can be measured in many ways. Just comparing how similar the R, G and B components are generally gives results humans won't agree with.
There's some general material on colour comparisons in wikipedia, and on working with natural colour spaces in C# in this question.