Color comparison

Hi All

I’m working on a little project related to colors. So the idea is this:

  • I use the camera from the device (a camera from an android device, or any other type),then I take the pixels from an area from that camera.
  • With that pixels a take the average between all the colors and get a scanned final color. This part is alright and done.
  • The tricky part comes now, I need to compare that color with a list of colors given in the editor. So my question is, what is the best way to compare colors? The problem comes because I only have 10 colors and they are pure. So, for instance, If I scan a color that my eye thinks is a yellow I need to get that the scanned color is yellow.
    Anybody has a good algorithm to compare color? I read a lot about this issue and it’s not easy.

Thanks in advance

This could be helpful

1 Like

Color can be represented not just in RGB, but also HSV, and bunch of others

in your case, you can convert the color to HSV which stands for Hue, saturation, Vibrance?(brightness)

Color input;
float hue;
float saturation;
float brightness;
Color.RGBToHSV(input, out hue, out saturation, out brightness)

after this, it is fairly easy to compare colors.
in your case, yellow is represented by hue in a range of about 40 to 70

1 Like

The problem here, that you still need to account for the brightness and saturation values because it’s great that you can easily compare greenish yellow or blueish yellow, but dark yellow and light yellow is still there

True, but OP was talking about finding the nearest colour to a list of 10 colors, that they describe as “pure” (whatever that means).

More information is needed from OP, but with such a short list, I suspect that the colour differences of the 10 colour palette is probably related to Hue rather than brightness or saturation.

So astrokoala’s HSV scenario could be used.

Of course, it’d be a very limited use, and if the colour palette ever changed the algorithm would have to be reconsidered. Where as a true colour difference algorithm would be better.

I think by pure he means, that rgb values are either 255 or 0, so pure green is 0 255 0, pure purple is 255 0 255 and so on

1 Like

we can guess what they mean all we want, we need more information from OP.

And if that is what they mean… then yes, astrokoala’s example would actually work.

But colors are float values. In case of red color(1, 0, 0) vs color(0.9999, 0, 0) difference would be so small anyone couldn’t tell. But it also speaks of comparison between float values, which you can’t do with equal sign ==.

Colours can be float values from 0->1, or they can be byte values (0->255).

And if you change into some colour spaces, you might have float values in a range of 0->360, because the colour space is defined radially.

It just happens the Unity ‘Color’ type stores them as floats from 0->1 in the RGB colour space. But ‘Color32’ stores them as integers in the ‘0->255’ range and in the RGB colour space. But you can convert from colour space relatively easily, as astrokoala showed where Unity has a built in RGBtoHSV method.

Not byte, hexadecimal
Originally, colours are discribed as a 6 digit hexadecimal number, 5F19A4 for example. This is divided into 3 2digit parts (5F, 19 and A4). Becuase it’s hexadecimal, there are 16^2=256 different values for these two digits. Because programming logic, it goes from 0 to 255 where 00 is 0 and FF is 255. The color I just wrote down is therefore (96, 25, 164) or in unity standards 255/96 = 2.65625, 255/25=10.2, 255/164=1,56

This is what you call true color, anything other than this WILL get rounded to the nearest value, this is why i think, that unity’s system is stupid, because you CAN’T have as many colors as you want, and showing them in a simple 0-255 style just makes life easier (if the difference in a 0-255 system is 1, so 00 to 01 for example, then that means, that for unity it’s 0,0039 in unity’s measurement)

An idea I found online is to convert the colors into HSL values and then just get the distance like you would with a normal Vector3:
d = Mathf.Sqrt(Mathf.Pow(c1.h - c2.h, 2), Mathf.Pow(…));
It’s not perfect because the human eye sees a lot more green shades than red shades, but for a small project it’s good enough

facepalm…

a 2-digit hexadecimal value has a max value of FF. Which is 16^2 - 1 (100 in hex is 16^2).

16^2 is 256, minus 1, it’s 255.

Why 16? It’s what hexadecimal means (hex is 6, deci is 10, it’s saying base 16).

We use base 16 because it’s shorter than writing binary, and 4 binary digits (bits) fit into one hex digit. So, 255 in binary is 11111111. Or 2^8 - 1.

Note how there’s 8 1’s in that…

What is an 8 digit binary value referred to as?

A BYTE

2 Likes

Since you are acquiring the pictures from a camera, it is almost certain that the color is altered (which is normal in photography). You would need to white balance your picture before comparing the colors to references. The best scenario would be to have a “pure” white object in your scene, have a way to detect it, white balance the picture relative to that object, only then you can compare the color with more reliability.