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.
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.
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
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.