26

We are building a sports application and would like to incorporate team colors in various portions of the app.

Now each team can be represented using several different colors.

What I would like to do is to perform a check to verify whether the two team colors are within a certain range of each other, so that I do not display two similar colors.

So, if team 1's primary team color has a value of rgb(255,0,0) (or #FF0000), and team 2's primary color is similar, say rgb(250,0,0), then we would choose a different color for one of the teams.

If possible, what approach could I take to perform the check?

Thanks

BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
Steve
  • 53,375
  • 33
  • 96
  • 141

7 Answers7

42

Here is a theoretical explanation

And the algo in C:

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));
}
pgras
  • 12,614
  • 4
  • 38
  • 46
  • 1
    are the rgb values normalized to the interval 0..1 or regular values int he range 0..255? – Thariama Sep 19 '12 at 10:29
  • It would be great to add a note how this algorithm compares to the techniques described in Wikipedia's [color difference](http://en.wikipedia.org/wiki/Color_difference) article, eg. CIEDE2000. – bluenote10 Mar 21 '14 at 16:30
  • Is this algorithm work to find closest color among of predefined colors? – sam_k Jun 02 '15 at 14:45
  • 1
    @Thariama they are 0-255 as indicated by the unsigned char (1 byte) – gremwell Mar 15 '17 at 05:03
  • 1
    @bluenote10 I wrote a blog post on this a few years back. ( https://godsnotwheregodsnot.blogspot.com/2012/09/color-space-comparisons.html ) the guy who wrote it did a fantastic job. It actually compares very favorably with CIEdE2k for being a fraction of the size. It basically does a solid job capturing the biggest most important fix to the color space and the weighting. – Tatarize Jun 11 '19 at 03:59
27

Here is pgras' algorithm in Java:

public double ColourDistance(Color c1, Color c2)
{
    double rmean = ( c1.getRed() + c2.getRed() )/2;
    int r = c1.getRed() - c2.getRed();
    int g = c1.getGreen() - c2.getGreen();
    int b = c1.getBlue() - c2.getBlue();
    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);
} 
Alp
  • 29,274
  • 27
  • 120
  • 198
BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
5

I would use 3d distance between two colors where x,y,z are R,G,B values.

Take a look at this Perl Library:

http://metacpan.org/pod/Color::Similarity::RGB

This is easy to implement yourself.

Just make sure that (R1-R2)^2 + (G1-G2)^2 + (B1-B2)^2 >= threshold^2

szabgab
  • 6,202
  • 11
  • 50
  • 64
Hamish Grubijan
  • 10,562
  • 23
  • 99
  • 147
  • I have to admit that this worked quite well for computer vision, but I am not really taking anatomy into account with this answer. – Hamish Grubijan Jan 20 '10 at 17:28
  • 2
    Yeah, I'd say for how similar two colors LOOK (rather than how similar they ARE), I'd use pgras' algorithm. Human eyes are far from perfect: we're more sensitive to green than red or blue, our brightness perception is logrithmic, etc. – BlueRaja - Danny Pflughoeft Jan 20 '10 at 17:37
  • Depending on your application you can use different algorithms. This one is the simplest. You can also scale the RGB factors by 22,43,35 and get a bit better results. The redmean formula called pgras' here though written by Thiadmer Riemersma is a step up. Then you move on to CIEdE2000 which starts stretching and pulling the colorspace to be more and more uniform with eyes. It also depends on things like XYZ which lets you account for stuff like colorblindness more easily. – Tatarize Jun 11 '19 at 04:10
5

Most answers for this question will suggest calculating the distance between two colors when mapping the RGB values into a 3D space. The problem with this technique is that two colors with similar hues, but different saturation or brightness levels may map further away from each other in 3D RGB space than two colors with different hues, but very similar saturation and brightness levels. In other words, a blue and a green may be closer in 3D RGB space than two shades of a Red. In this application, ensuring team colors differ, hue differences should weigh much more heavily than brightness and saturation.

So I would convert the color mapping from RGB to hue, saturation, and brightness levels, and then check just the hue values for sufficient distance.

Wikipedia has an explanation for converting RGB to HSV. LiteratePrograms has some sample code.

Mr. Berna
  • 10,525
  • 1
  • 39
  • 42
  • 1
    I missed the Java tag on first reading. The java.awt.Color class has an RGBtoHSB method for the conversion. – Mr. Berna Jan 20 '10 at 18:12
  • That is sufficient if the OP has only half-a-dozen teams; but if there are 20 or 30+, then he **has** to take saturation and brightness into account. The link pgras gave claims their algorithm gives better results (which is of course subjective) than HSV-distance. – BlueRaja - Danny Pflughoeft Jan 20 '10 at 19:58
  • As the OP says, the goal is to compare just two colors at at time. I suggested this method is an alternative to try if the RGB distance methods give insufficient results. As I think more on this, comparing just hue values will give good results when comparing colors with higher saturation and brightness values, and fail when comparing colors with either low brightness or low saturation. An improvement to this method would be to check that at least one of the colors has sufficiently high saturation and brightness values before checking hue differences. – Mr. Berna Jan 21 '10 at 13:59
4

Wikipedia has details on a number of algorithms which can be used for this.

There is also this previous StackOverflow question: Finding an accurate “distance” between colors

Community
  • 1
  • 1
matt b
  • 138,234
  • 66
  • 282
  • 345
2

From an algorithm viewpoint, this is fairly simple. Each color represents a point in a 3D space, and the difference between colors is the distance between those points.

Presumably the point here is to ensure that the colors are visibly different. If that's the case, deciding on the minimum distance is probably going to be fairly difficult. The problem is that (at least for people with normal vision) some differences are easier to see than others. For example, most people are more sensitive to small differences in shades of green than equally small changes in shades of red or blue. There are algorithms to take this into account, but they're based on average human vision, so none of them is guaranteed to be precisely correct for any one person.

Just for fun, you might want to take a look at X-rite's online color vision test.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

I have used the algorithms given in the first replies although results did not meet expectations until I have found DeltaE library, which calculates the distance between colors much better.

It's for Node.js, check it here.