Algorithm to compare the likeness of or distance between two colours

Started by
5 comments, last by u235 17 years, 8 months ago
Hi Gamedev, was just wandering if anyone knew of or could point me in the direction of any algorithms that can compare how alike two colours are like in a percentage or scale value or the distance between each one based on their rgb components. For example say I have a method called compare() I would use it like this likeness = compareColour(0xFF0000,0xFFFF00) the value in likeness could be a percentage or something else maybe Just wandering. Thanks in advance. DarkStar UK
---------------------------------------------You Only Live Once - Don't be afriad to take chances.
Advertisement
I'd be tempted to simply use the euclidean distance in [0,1]3. Then, you could go looking for a chart determining ocular precision (which is greater in some areas of the cube, and smaller in others) and scale your distance based on this.

Then again, any distance is a valid distance in theory. Now, if you need specific properties to be true for that distance...
It depends on what you mean by alike. For general purposes, just take the colors as 3D vectors and take the Euclidean distance between them as mentioned by ToohrVyk. Since RGB is an orthogonal space, it should be generally OK.

However, RGB is not a perceptually uniform space to human eyes (which is I think what ToohrVyk was getting at with ocular precision). Two colors that are an equal distance away from white might not look equally different from white, if that makes sense. Logluv is a perceptually uniform color space, if you really need it, but chances are all of this is overkill and RGB distance is good enough.
maybe something like this, just a weighted euclidean distance...

(r1,g1,b1 and r2,g2,b2 float channels for the two colours)

float r3 = r1 - r2;
float g3 = g1 - g2;
float b3 = b1 - b2;

return sqrt( 0.2126f * r3 * r3 + 0.7152f * g3 * g3 + 0.0722f * b3 * b3 );
I think the best you could do would be to convert from RGB to YUV, and then take the Eucledian distance as proposed above. A bit pseudo-code:
Y = 0.299R + 0.587G + 0.114B;U  = 0.492(B - Y);V  = 0.877(R - Y);clamp( Y, 0, 255 );clamp( U, 0, 255 );clamp( V, 0, 255 );dist = sqrt( (Y1-Y2)*(Y1-Y2) + (U1-U2)*(U1-U2) + (V1-V2)*(V1-V2) );


Hi,

Just done this myself.

As others have stated a simple weighting/distance check will work, although you can drop the squareroot since you're comparing the same things. You may also want to try doing this with luminace and not actual colours, depending on the 'type' of matches you are looking for.

Also don't get fooled into checking for a 'near' distance fit, as this can lead to poor results. For example if you use (r*r)+(g*g)+(b*b) < 15 then both a colour that is 15 units out on the red, but not green or blue, will pass just as if each red,green,blue is out say 3 units each - i.e its the overall closeness of the components that is examined, not the closeness on a per component basis. So always look for a 'bestfit' its slower, but you'll get better results.


If you want to get more advanced have a look at Colour Metric and the C code snippet on that page. You might also want to browse through the colour space FAQ
Quote:Orignial post by noisecrime
Also don't get fooled into checking for a 'near' distance fit, as this can lead to poor results. For example if you use (r*r)+(g*g)+(b*b) < 15 then both a colour that is 15 units out on the red, but not green or blue, will pass just as if each red,green,blue is out say 3 units each - i.e its the overall closeness of the components that is examined, not the closeness on a per component basis. So always look for a 'bestfit' its slower, but you'll get better results.



This my thought when I first read the OP. Here's what I came up with just now as something that might work:

int r, g, b;r = abs(r1 - r2);g = abs(g1 - g2);b = abs(b1 - b2);if (r / 100 > 5)   return false;if (g / 100 > 5)   return false;if (b / 100 > 5)   return false;return true;


This checks that all component values are within 5 percent and returns false otherwise. Hope this help you out some [smile].

-AJ
V/R,-AJThere are 10 kinds of people in the world: Those who understand binary and those who don't...

This topic is closed to new replies.

Advertisement