3

This question may be more to do with human psychology

I am trying to make a program that recreates a bit map image using a limited colour palette. I naively thought that I could simply find the squared difference of the Red/Green/Blue values and use that to quantify the squared difference between colours. However in practice this doesn't seem to work very well, shades of red are being matched to shades of purple and so on.

Does anyone have any suggestions of alternate comparison methods I could use?

int squaredDistance(colour a, colour b)
{
    return (a.r - b.r)*(a.r - b.r) + (a.g - b.g)*(a.g - b.g) + (a.b - b.b)*(a.r - b.b);
}

int findClosestColour(colour a) //Returns id of colour that most closely matches
{
    int smallestColourDistance = 195075;
    int colourId = -1;
    for(int i=0; i<NUMOFCOLOURS; i++)
    {
        if( squaredDistance(a, coloursById[i]) < smallestColourDistance)
        {
            smallestColourDistance = squaredDistance(a, coloursById[i]);
            colourId = i;
            if(smallestColourDistance == 0)
                break;
        }
    }
    return colourId;
}
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
  • 1
    have you looked at: http://stackoverflow.com/questions/5392061/algorithm-to-check-similarity-of-colors-based-on-rgb-values-or-maybe-hsv? – NathanOliver Aug 07 '15 at 13:43
  • Oops, sorry thank you :) that looks like it will help allot. – Bradley Pymm Aug 07 '15 at 13:49
  • 1
    Firstly, I'd caution against working in the RGB colour-space, since it's awful to work with from a human perspective - I'd suggest the HSV/HSL or the YUV ones as being more suitable. I'd also recommend the following article: http://www.iquilezles.org/www/articles/wavelet/wavelet.htm While it is on using wavelet compression on images, there's an interesting section in it on the way we perceive images and colours. Specifically, it demonstrates how much more sensitive we are to light/dark than we are to actual Hue. It's a good read - try starting at "Color Images" – enhzflep Aug 07 '15 at 14:56
  • Also, another good read is the following forum post: http://codegolf.stackexchange.com/questions/33172/american-gothic-in-the-palette-of-mona-lisa-rearrange-the-pixels – enhzflep Aug 07 '15 at 15:01
  • Those are related questions: http://stackoverflow.com/questions/8160663/c-c-library-for-computing-color-difference-delta-e-and-color-space-conversio, http://stackoverflow.com/questions/5774152/calculate-how-humans-perceive-similarity-between-different-colours?rq=1 – Kel Solaar Aug 08 '15 at 11:40

2 Answers2

2

This is called colour difference in colour science and there are multiple algorithms to compute it, here are a few of them:

  • Delta E CIE 1976
  • Delta E CIE 1994
  • Delta E CIE 2000
  • Delta E CMC

Bruce Lindbloom has a calculator and Colour provides a vectorised Python implementation. You will have to convert your RGB values to CIE Lab before being able to use any Delta E implementation.

There are also available colour difference computations implemented on top of CIECAM02 colour appearance model, and especially CAM02-UCS colourspace that is a more uniform version of CIECAM02 underlying colourspace.

Kel Solaar
  • 3,660
  • 1
  • 23
  • 29
0

This is an old question, but in case anyone comes across it...

I had a similar problem where I wanted to calculate the difference between two randomly picked colors (foreground and background) to make sure the foreground is readable. So I made my research and wrote this little C++ library that calculates delta-E using CIE76:

https://github.com/ThunderStruct/Color-Utilities

Sample:

// Colors' Construction
ColorUtils::rgbColor c1(1.0f, 1.0f, 1.0f), c2(0.5f, 0.5f, 0.5f);

// Calculate Delta-E
std::cout << ColorUtils::getColorDeltaE(c1, c2) << '\n';

This outputs 46.8072, which can be validated using this calculator

ThunderStruct
  • 1,504
  • 6
  • 23
  • 32