Thursday, February 19, 2015

Digital Image processing with c++ ( Chapter 3 ) - Color Histogram

Today I'm going explain about how to create color histogram using Gray scale image. Histogram represent color frequency of the image .
Another words it represents the number of pixels that have each colors in fixed list of color ranges.
Histogram is one of most useful things when we going to take decisions about image.Because image processing deal with colors .
So by using histogram we can identify dominant colors ,color distribution ,max occurrence ,Contrast stretching etc.
We will discuss these things in later .

Lets consider our image is like this .Each pixel represent a color from different 8 colors

1 4 6 7 7
2 0 5 5 4
1 7 2 0 2
6 4 7 5 2
0 0 5 2 1

We can summarize these information in to this table like this

Color Frequncy
0 4
1 3
2 5
3 0
4 3
5 4
6 2
7 4
Total 25


Then the relevant histogram would be like this



Now I think you have some kind of idea about what is Color Histogram
so then we can move to code.We are calculating and drawing histogram for Gray scale images.

#include 
#include 
#include 

using namespace cv;
using namespace std;

int main()
{
Mat RGBImage;

RGBImage =imread("c:/example_image.png");

Mat grayScaleImage(RGBImage.size(),CV_8UC1);

cvtColor(RGBImage,grayScaleImage,CV_RGB2GRAY);


Mat histogramTable(1,256,CV_32FC1);
histogramTable=Scalar(0);

int rows=grayScaleImage.rows;
int cols=grayScaleImage.cols;

 //enter pixel values to hitro map
for(int i=0;i
 for(int j=0;j
 int pixelValue=(int)grayScaleImage.at(i,j);
 int fre=(int)histogramTable.at<float>(0,pixelValue);
 fre++;
 histogramTable.at<float>(0,pixelValue)=fre;
  }
 }

 //find maximum value of histrogram
int maxFre=0;

for(int count=0;count<256;count++){
 int histoIndexValue=histogramTable.at<float>(0,count);

 if(histoIndexValue>maxFre){
  maxFre=histoIndexValue;
 }

 }

Mat scaledHistogramTable(1,256,CV_32FC1);
 //create scale histro
for(int count=0;count<256;count++){

float histroIndexValue=histogramTable.at<float>(0,count);

scaledHistogramTable.at<float>(0,count)=histroIndexValue/maxFre;

 }

Mat histogramDrawer(512,256,CV_8UC3);
histogramDrawer=Scalar(0);

 //Draw histogram
for(int count=0;count<256;count++){

float histoValue=511-scaledHistogramTable.at<float>(0,count)*512;               

line(histogramDrawer,Point(count,511),Point(count,histoValue),
Scalar(255,255,0));

 }

 namedWindow("HistoGram",1);
 namedWindow("GrayScaleImage",1);

 imshow("HistoGram",histogramDrawer);
 imshow("GrayScaleImage",grayScaleImage);

 waitKey();
 return 0;
}


Sometimes you will feel that this is a complex code but I will promise you after going through this steps carefully you will find this is very simple.
This code include that the concept I explained above.

In this code sometimes we have to use Mat objects that has 32 bit depth and floating point data types. Therefore you can see Mat objects like CV_32FC1


Mat histogramTable(1,256,CV_32FC1);
 histogramTable=Scalar(0);

 int rows=grayScaleImage.rows;
 int cols=grayScaleImage.cols;

 //enter pixel values to hitro map
for(int i=0;i
 for(int j=0;j
 int pixelValue=(int)grayScaleImage.at(i,j);  
        int fre=(int)histogramTable.at<float>(0,pixelValue);
 fre++;
 histogramTable.at<float>(0,pixelValue)=fre;
  }
 }


In this we have to get color value of each and every pixel and store it in histogramTable Mat object.Make sure make all values equal to zero before start this for loop by using


histogramTable=Scalar(0);


Then we have to scale histogram to 1 for that we divide each and every frequency by maximum frequency value


//find maximum value of histrogram

int maxFre=0;

for(int count=0;count<256;count++){
       int histoIndexValue =histogramTable.at<float>0,count);

  if(histoIndexValue>maxFre){
   maxFre=histoIndexValue;
  }

 }

 Mat scaledHistogramTable(1,256,CV_32FC1);

 //create scale histro

 for(int count=0;count<256;count++){

float histroIndexValue=histogramTable.at<float>(0,count);

scaledHistogramTable.at<float>(0,count)=histroIndexValue/maxFre;

 }


Then Scaled values stores in scaledHistogramTable Mat object.
After that we have to Draw Histogram.


Mat histogramDrawer(512,256,CV_8UC3);
 histogramDrawer=Scalar(0);

 //Draw histogram
 for(int count=0;count<256;count++){

float histoValue=511-scaledHistogramTable.at<float>(0,count)*512;
line(histogramDrawer,Point(count,511),Point(count,histoValue),Scalar(255,255,0));

 }


Size of our histogram is width=256 and height= 512.And for loop draw lines and complete histogram.


float histoValue=511-scaledHistogramTable.at<float>(0,count)*512;


Normally Mat object (0,0) start from top left corner .
But we draw histogram from bottom to top therefore we have to calculate relevant value by subtract from 511


line(histogramDrawer,Point(count,511),Point(count,histoValue),Scalar(255,255,0));


By using line function we can draw lines .
As first parameter we pass Mat object. Histogram will draw on it.
As 2nd parameter we pass starting point of the line and 3rd parameter is ending point .
As last parameter we enter color value of the line

Then we can get output like this



If you have Any question ,complain or suggestion please leave a comment .I always like to help you. :) See you soon .Thank you.