Displaying histograms

Quite obviously, trying to display the resulting histogram using a function, such as imshow, is futile since the raw format of the stored histogram is similar to a single column matrix that has bins number of rows in it. Each row, or, in other words, each element, of the histogram corresponds to the number of pixels that fall into that specific bin. Considering this, we can draw the calculated histogram by using drawing functions from Chapter 4, Drawing, Filtering, and Transformation.

Here's an example that shows how we can display the histogram that we calculated in the previous code sample as a graph with custom size and properties:

int gRows = 200; // height 
int gCol = 500; // width 
Scalar backGroundColor = Scalar(0, 255, 255); // yellow 
Scalar graphColor = Scalar(0, 0, 0); // black 
int thickness = 2; 
LineTypes lineType = LINE_AA; 
 
Mat theGraph(gRows, gCol, CV_8UC(3), backGroundColor); 
 
Point p1(0,0), p2(0,0); 
for(int i=0; i<bins; i++) 
{ 
    float value = histogram.at<float>(i,0); 
    value = maxVal - value; // invert 
    value = value / maxVal * theGraph.rows; // scale 
    line(theGraph, 
         p1, 
         Point(p1.x,value), 
         graphColor, 
         thickness, 
         lineType); 
    p1.y = p2.y = value; 
    p2.x = float(i+1) * float(theGraph.cols) / float(bins); 
    line(theGraph, 
         p1, p2, 
         Scalar(0,0,0)); 
    p1.x = p2.x; 
} 

In the preceding code, gRow and gCol refer to the height and width of the resulting graph, respectively. The rest of the parameters are either self-explanatory (backgroundColor and so on), or you have already learned about them in the previous chapters. Notice how each value in histogram is used to calculate the position of the line that needs to be drawn. In the preceding code, maxVal is simply used to scale the results to the visible range. Here's how maxVal itself is calculated:

double maxVal = 0; 
minMaxLoc(histogram, 
          0, 
          &maxVal, 
          0, 
          0);

Refer to Chapter 3, Array and Matrix Operations, if you need to refresh your memory about how the minMaxLoc function is used. In our example, we only need the value of the biggest element in the histogram, so we ignore the rest of the parameters by passing zero to them.

Here is the result of the preceding example codes:

You can easily change the background or the graph color using the provided backGroundColor or graphColor parameters, or make the graph thinner or thicker by changing the thickness parameter, and so on.

Interpretation of a histogram is extremely important, especially in photography and photo-editing applications, so being able to visualize them is essential for easier interpretation of the results. For instance, in the preceding example, it can be easily noticed from the resulting histogram that the source image contains more tones of darker colors than brighter ones. We'll see more examples of darker and brighter images later on, but before that, let's see how changing the number of bins would affect the result.

The following are the resulting histograms of the same image as the previous example, with 150, 80, and 25 bins, from left to right, drawn using a bar chart visualization method:

You can easily notice that the lower the bins value is, the more grouped together the pixels are. Even though this might seem more like a lower resolution of the same data (from left to right), it is actually better to use a lower number of bins to group similar pixels together. Note that the bar-chart visualization in the preceding example is produced by replacing the for loop from the previous example code with the following:

Point p1(0,0), p2(0, theGraph.rows-1); 
for(int i=0; i<bins; i++) 
{ 
    float value = histogram.at<float>(i,0); 
    value *= 0.95f; // 5% empty at top 
    value = maxVal - value; // invert 
    value = value / (maxVal) * theGraph.rows; // scale 
    p1.y = value; 
    p2.x = float(i+1) * float(theGraph.cols) / float(bins); 
    rectangle(theGraph, 
              p1, 
              p2, 
              graphColor, 
              CV_FILLED, 
              lineType); 
    p1.x = p2.x; 
} 

Both of these visualizations (graph or bar-chart) have their own pros and cons, which will be more obvious as you try calculating histograms of different types of images. Let's try calculating the histogram of a color image. We'll need to calculate the histogram of individual channels, as was mentioned previously. Here's an example code that demonstrates how it's done:

Mat image = imread("Test.png"); 
if(image.empty()) 
{ 
    cout << "Empty input image!"; 
    return -1; 
} 
 
Mat imgChannels[3]; 
Mat histograms[3]; 
split(image, imgChannels); 
 
// each imgChannels element is an individual 1-channel image

You can download the complete source code for the preceding example from the online source code repository for this chapter. The example project containing the full source code of the preceding code snippet is called CvHistGraphColor, and running it would produce a result similar to what is seen in the following diagram:

As you can see in the preceding example code, the split function is used to create three individual images, each containing a single channel, out of our source color image (BGR by default). The part of the code that is mentioned with the commented line in the preceding code is simply a for loop that iterates over the elements of imgChannels and draws each graph using the exact same code as you saw before, but with each graph having its own unique color that is calculated using the following code in the loop:

Scalar graphColor = Scalar(i == 0 ? 255 : 0, 
                           i == 1 ? 255 : 0, 
                           i == 2 ? 255 : 0); 

Depending on the value of igraphColor is set to blue, green, or red, hence the resulting histography depicted in the previous picture.

Besides interpreting the content of an image, or to seeing how pixel values are distributed in an image, histograms have many use cases. In the following sections, we'll be learning about back-projection and other algorithms that are used for utilizing histograms in our applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.138.178