Reputation: 23961
One simple way is to say that when the RGB components are equal, they form a gray color. However, this is not the whole story, because if they only have a slight difference, they will still look gray.
Assuming the viewer has a healthy vision of color, how can I decide if the given values would be perceived as gray (presumably with an adjustable threshold level for "grayness")?
Upvotes: 4
Views: 944
Reputation: 27565
A relatively straightforward method would be to convert RGB value to HSV color space and use threshold on the saturation component, e.g. "if saturation < 0.05 then 'almost grey', else not grey".
Saturation is actually the "grayness/colorfulness" by definition.
This method is much more accurate than using differences between R, G and B channels (since human eye perceives saturation differently on light and dark colors). On the other hand, converting RGB to HSV is computationally intensive. It is up to you to decide what is of more value - precise answer (grey/not grey) or performance.
If you need an even more precise method, you may use L*a*b* color space and compute chroma as sqrt(a*a + b*b)
(see here), and then apply thresholding to this value. However, this would be even more computationally intensive.
You can also combine multiple methods:
Calculate simple differences between R, G, B components. If the color can be identified as definitely desaturated (e.g. max(abs(R-G), abs(R-B), abs(G-B)) <= 5
) or definitely saturated (e.g. max(abs(R-G), abs(R-B), abs(G-B)) > 100
), then stop.
Otherwise, convert to L*a*b*, compute chroma as sqrt(a*a + b*b)
and use thresholding on this value.
Upvotes: 4
Reputation: 48629
r = 160; g = 179; b = 151;
tolerance = 20;
if (Math.abs(r-g) < 20 && Math.abs(r-b) < 20) { #then perceived as gray }
Upvotes: 0