* Use the OpenCV function :split:`split <>` to divide an image into its correspondent planes.
* To calculate histograms of arrays of images by using the OpenCV function :calc_hist:`calcHist <>`
* To normalize an array by using the function :normalize:`normalize <>`
..note::
In the last tutorial (:ref:`histogram_equalization`) we talked about a particular kind of histogram called *Image histogram*. Now we will considerate it in its more general concept. Read on!
What are histograms?
--------------------
..container:: enumeratevisibleitemswithsquare
* Histograms are collected *counts* of data organized into a set of predefined *bins*
* When we say *data* we are not restricting it to be intensity values (as we saw in the previous Tutorial). The data collected can be whatever feature you find useful to describe your image.
* Let's see an example. Imagine that a Matrix contains information of an image (i.e. intensity in the range :math:`0-255`):
* What happens if we want to *count* this data in an organized way? Since we know that the *range* of information value for this case is 256 values, we can segment our range in subparts (called **bins**) like:
and we can keep count of the number of pixels that fall in the range of each :math:`bin_{i}`. Applying this to the example above we get the image below ( axis x represents the bins and axis y the number of pixels in each of them).
* This was just a simple example of how an histogram works and why it is useful. An histogram can keep count not only of color intensities, but of whatever image features that we want to measure (i.e. gradients, directions, etc).
* Let's identify some parts of the histogram:
a. **dims**: The number of parameters you want to collect data of. In our example, **dims = 1** because we are only counting the intensity values of each pixel (in a greyscale image).
b. **bins**: It is the number of **subdivisions** in each dim. In our example, **bins = 16**
c.**range**: The limits for the values to be measured. In this case: **range = [0,255]**
* What if you want to count two features? In this case your resulting histogram would be a 3D plot (in which x and y would be :math:`bin_{x}` and :math:`bin_{y}` for each feature and z would be the number of counts for each combination of :math:`(bin_{x}, bin_{y})`. The same would apply for more features (of course it gets trickier).
What OpenCV offers you
-----------------------
For simple purposes, OpenCV implements the function :calc_hist:`calcHist <>`, which calculates the histogram of a set of arrays (usually images or image planes). It can operate with up to 32 dimensions. We will see it in the code below!
Code
====
..container:: enumeratevisibleitemswithsquare
***What does this program do?**
..container:: enumeratevisibleitemswithsquare
* Loads an image
* Splits the image into its R, G and B planes using the function :split:`split <>`
* Calculate the Histogram of each 1-channel plane by calling the function :calc_hist:`calcHist <>`
#. Separate the source image in its three R,G and B planes. For this we use the OpenCV function :split:`split <>`:
..code-block:: cpp
vector<Mat> rgb_planes;
split( src, rgb_planes );
our input is the image to be divided (this case with three channels) and the output is a vector of Mat )
#. Now we are ready to start configuring the **histograms** for each plane. Since we are working with the R, G and B planes, we know that our values will range in the interval :math:`[0,255]`
a. Establish number of bins (5, 10...):
..code-block:: cpp
int histSize = 255;
b. Set the range of values (as we said, between 0 and 255 )
..code-block:: cpp
/// Set the ranges ( for R,G,B) )
float range[] = { 0, 255 } ;
const float* histRange = { range };
c. We want our bins to have the same size (uniform) and to clear the histograms in the beginning, so:
..code-block:: cpp
bool uniform = true; bool accumulate = false;
d. Finally, we create the Mat objects to save our histograms. Creating 3 (one for each plane):
..code-block:: cpp
Mat r_hist, g_hist, b_hist;
e. We proceed to calculate the histograms by using the OpenCV function :calc_hist:`calcHist <>`: