I decided that this blog needs another post, preferably on subject with some real applications. Unlike my Mandelbrot log-map experiments or allRGB mini “game”. Because why would anyone read about those boring useless things… And, since I am cooking real application here that tracks real colored blobs, the subject today will be color matching.
If you have been searching for this stuff before ending up here, you could notice that cool guys never do color matching in RGB, but instead go with HSV or similar hue-based color space. The idea here is, probably, that when you pull all color information into one coordinate, you can forget about other two. Unfortunately you can’t :( It’s not to say that there is some kind of a problem here, not at all. With tools like pixel bender on your belt, you just write a shader that converts to HSV and applies thresholds in one breath, and voila – you get your blobs to track. But, for some reason, this kind of blind belief in hue dogma just doesn’t sit well with me.
So, as the saying goes, “know your enemy”. Let us first look at hue color wheel for a moment (on your left). Immediately we note one special thing about hue – it is measured in degrees. Which means it is an angle. And since it is an angle, there has to be corresponding axis in 3D color space, let’s see… Ha! In both HSL and HSV spaces this axis spans colors that go from black to white.
What a coincidence, but RGB space also has same axis. It is RGB cube diagonal that goes from R=0 G=0 B=0 to R=255 G=255 B=255. So what does RGB cube look like, when you look at it along this direction? Well, here comes another handy picture from wikimedia (on your right).
Needless to say, the similarity is… obvious. Ok, maybe not so obvious when you look at raw R, G, B numbers, scratching your head and thinking what to do with them, and there are time-tested HSV solutions waiting for you all over the internet… So, inspired by this little discovery, I went straight to code. My 1st thought was to simply project target RGB color onto this “ortho-white” plane (btw, does it have some kind of real name, anyone?), thus obtaining three-dimensional “hue” vector in RGB, and then use ColorMatrixFilter to compute dot product with that projected vector. It resulted into this kind of picture:
Almost there, but no cigar. Thresholding this image has an effect of cutting a slice along hue wheel chord. In other words, it tends to select irrelevant colors. So I had to try again, this time with two different dot products to cut a sector-shaped slice and somewhat limit selected colors range:
This worked somewhat better and, thanks to automatic color clamping, I got yellow blobs ready to be tracked out of single ColorMatrixFilter:
In this case, just like like with hue-based approach, you get a lot of noise from grey pixels near cube diagonal. So in the end I had to combine it with 1st approach using remaining free blue channel, and got myself white blobs to track:
Well, that’s about it for the post. Check out the code, come back with your own ideas :) To sum up, RGB space is just as good as hue-based space for color matching and, since that’s the space flash is using, there is absolutely no reason to ignore it.