I found this article about color spaces is very useful and important when we do something related to image processing, color tracking, etc… with OpenCV, Matlab or even microcontroller that could be implemented in further projects. This could give you a basic understanding on how to distinguish various types of color spaces.
This post is originally from Utkarsh Sinha, http://www.aishack.in/tutorials/color-spaces-1/
Images are stored in memory in various different colour spaces. You might have heard of one, the RGB colour space. That is the one Windows uses a lot. For image processing purposes, one often needs other colour spaces that better suit the purpose of the application.
In this article, I’ll go through the RGB and HSI colour spaces in detail, and briefly touch the Y’CbCr colour space too.
Exactly how is an image stored?
Before we get to the colour spaces, you need to know exactly how OpenCV (or any other program/API) stores images in the RAM.
We’ll start simple… with a grayscale image. A grayscale picture just needs intensity information – how bright is a particular pixel. The higher the value, the greater the intensity. Current displays support 256 distinct shades of gray. Each one just a little bit lighter than the previous one!
So for a grayscale image, all you need is one single byte for each pixel. One byte (or 8-bits) can store a value from 0 to 255, and thus you’d cover all possible shades of gray.
So in the memory, a grayscale image is represented by a two dimensional array of bytes. The size of the array being equal to the height and width of the image. Technically, this array is a “channel”. So, a grayscale image has only one channel. And this channel represents the intensity of whites. An example grayscale image:
When colour is added, things get trickier. More information needs to be stored. Its no more just about what shade. Its about what shade of which “colour”.
Non transparent image support 16,581,375 (that is around 16million) distinct colours. To be able to distinguish these different shades, you need 3 bytes for each pixel (3 bytes, or 24-bits, can store a value upto 255255255… which is equal to 16,581,375).
Now think about this: You have 16 million numbers to assign to different shades of colours. If you just randomly assigned colours to each number, things would get wierd. (say, 1=brightest red, 2=brightest green, 45780=dullest yellow, etc).
So people figured out different “colour spaces” to systematically assign numbers to the HUGE number of colours.
The RGB colour space
We’ll start off simple, with the most common colour space: RGB. The 3 bytes of data for each pixel is split into 3 different parts: one byte for the amount of red, another for the amount of green and the third for the amount of blue.
Red, green and blue being primary colours can be mixed and different proportions to form any colour.
You have 256 different shades of red, green and blue (1 byte can store a value from 0 to 255). So you mix these colours in different proportions, and you get your desired colour. This colour space is quite intuitive. You’ve probably used it all the time without realizing what all was going on behind the scenes.
And since you’ve “dedicated” one byte of each pixel to red, the second byte to green and the last byte to blue… it makes sense to club these bytes together.
That is, all the “dedicated red” bytes together… the “dedicated green” bytes together at another place… and the blue ones at another location. And, behold, you get the red channel, the green channel and the blue channel!!
Here are some visuals that will explain this better:
See the red, green and blue channels? The red regions have 0 “blue content”. They’re pure red. And, the channels is a grayscale image (because each channel has 1-byte for each pixel).
RGB is good for humans. We can intuitively use it, and generate any colour we want.
But lets say you’re taking part in some image processing robotics competition (maybe, robocup). And you want your program to detect the position of your robots… you’ve probably put identity tags on top of them… something like this:
You can see the bots (red and blue, with white circles). And you want your program to identify their locations.
Your first idea would be something like: Take the red channel… and find out the regions with high intensity of red. Then, take the blue channel… and find out the regions with a high intensity of blue.
There are a few flaws in what you think:
- The “high intensity” regions won’t be uniform. They’ll vary because of factors you can’t control… like lighting, texture, etc
- And what exactly does “high intensity” mean? Does it mean a value of red greater than 128? or 64? You might have guess by now, using the RGB colour space for image processing is often tough. So the HSV colourspace was invented!
The HSV colour space
The HSV colour space also has 3 channels: the Hue, the Saturation and the Value, or intensity.
The Hue channel represents the “colour”. For example, “red” would be a colour. Light red/dark red would not be a colour.
The saturation channel is the “amount” of colour (this differentiates between a pale green and pure green). And intensity is the brightness of the colour (light green or dark green).
The visual below might help clarify what each channel represents:
As you can see in the Hue channel, each colour has its own “value”… the entire “red” is a single value, and also the green and blue. The lightness or darkness of the colour does not affect the hue channel. This channel is of immense use in image processing competitions where the quality of blue or green is quite bad (which is usually the case).
In the saturation channel, each pixel has a high intensity… meaning that each of the colours is completely saturated (and that is the case… the picture was generated using a software. If you used a real photograph, you’d get varied saturations throughout the image).
The intensity channel shows the brightness of the colour. From this channel, it appears that somehow the red colour’s intensity is a bit lower than the rest of the two colours.
Using HSV in Matlab
Matlab’s image processing toolbox comes with a function that converts a given RGB image into an HSV image:
H = rgb2hsv(img);
Its as simple as that.
Using HSV in OpenCV
OpenCV also comes with a function that converts images between colour spaces:
cvCvtColor(source, destination, conversion_code);
Here, source is the image to be transformed. destination is where the transformed image will be stored and conversion_code specifies the type of conversion to be done (like CV_2) . In our case, it is CV_BGR2HSV. (I used a BGR because thats how OpenCV loads most images, yes BGR… not RGB).
The Y’CrCb colour space
I won’t go into the details of this colour space… But i’ll describe it briefly as an example of how different colour spaces are useful in different situations.
The Y’CrCb is quite useful considering the phosphor emission characteristics of newer CRT screens. And is hence used in televisions, HDTV, etc. Plus, two of the three channels can be highly compressed without much loss in detail in the final image. This helps save bandwidth.
The Y’ channel (luma) is basically the grayscale version of the original image. Human eye is more receptive to black and white images… so this channel isn’t compressed much. This preserves a lot of details. The Cr and Cb channels contain the colour information. They can be highly compressed.
Many variants of this colour space exist… each works great for some particular application.
In this two page article you learned about the RGB and HSV colour spaces in detail. You also got to know about how to convert images into other colour spaces in Matlab and OpenCV. And you also got a glimpse of the Y’CrCb colour space.
Hope you learned through this tutorial. If you have any ideas, suggestions or criticism, do leave comments below!