Friday, December 21, 2012

Histogram equalization using OpenCV

          In image processing Histogram can be considered as the graphical representation of pixel value versus the pixel count. For example an 8 bit single channel gray-scale image histogram might be a 2-D graph of X axis with pixel value and Y axis with pixel count. Histogram equalization is the contrast adjustment using histogram of image. This method is useful when the image information is poor that is foreground and background both are dark or over exposed. The image below shows what we actually do with the histogram equalization. 

        Histogram equalization improves the contrast of an image by stretching it's intensity range. On the below image the first plot represent the histogram of the low contrast source image and on the second one is the histogram after equalization. So it is clearer that the Histogram equalization just stretch out the intensity range.


Graphical representation of Histogram equalization(Image from Wikipedia).









    OpenCV has inbuilt function for doing histogram equalization, like equalizeHist which has two arguments, source and destination image.

        Below is an example code which show the use of Histogram Equalization using OpenCV. Also the code draws the Histograms of the image before and after equalization.

The programm includes

1. Load image as single channel.
2. Create the histogram of the source image.
3. Perform histogram equalization of the source image.
4. Create the the histogram of the equalized image.
5. Show the results.

 Here is the source code
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include <iostream> 
#include <stdio.h> 

using namespace std;
using namespace std;
void create_histogram_image(IplImage*, IplImage*);

int main()
{
    // Set up images
    IplImage *img = cvLoadImage("src.jpg", 0);
    IplImage* out = cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 1 );
    // create new image structure to hold histogram image
    IplImage *hist1 = cvCreateImage(cvSize(640,480), 8, 1);
    cvSet( hist1, cvScalarAll(255), 0 );
    IplImage *hist2 = cvCreateImage(cvSize(640,480), 8, 1);
    cvSet( hist2, cvScalarAll(255), 0 );

       create_histogram_image(img, hist1);
       cvEqualizeHist( img, out );// Perform histogram equalization
       create_histogram_image(out, hist2);

    cvNamedWindow( "Original", 1) ;// Show original
    cvShowImage( "Original", img );
    cvNamedWindow( "Histogram before equalization", 1) ;//Show Histograms
    cvShowImage( "Histogram before equalization", hist1 );
    cvNamedWindow( "Histogram after equalization", 1) ;
    cvShowImage( "Histogram after equalization", hist2 );
    cvNamedWindow("Result", 1) ; // Show histogram equalized
    cvShowImage("Result", out );
    cvWaitKey(0);

    cvReleaseImage( &img );
    cvReleaseImage( &out );
    return 0;
}


/*******This function create histogram of the source image*******/


void create_histogram_image(IplImage* gray_img, IplImage* hist_img) {
  CvHistogram *hist;
  int hist_size = 256;
  float range[]={0,256};
  float* ranges[] = { range };
  float max_value = 0.0;
  float w_scale = 0.0000000;
 

hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);// create array to hold histogram values

cvCalcHist( &gray_img, hist, 0, NULL );// calculate histogram values

cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 ); // Get the minimum and maximum values of the histogram

cvScale( hist->bins, hist->bins, ((float)hist_img->height)/max_value, 0 );// set height by using maximim value

w_scale = ((float)hist_img->width)/hist_size;// calculate width


// plot the histogram
 for( int i = 0; i < hist_size; i++ ) {
 cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),
 cvPoint((int)(i+1)*w_scale, hist_img->height -    

 cvRound(cvGetReal1D(hist->bins,i))),
 cvScalar(0), -1, 8, 0 );
    }
}

/*************************************************************************** 



You can download C++ source from  here

Results:

Source image (Image from Wikipedia).


Histogram of source image.






Result after histogram equalization.


















Histogram of result.





5 comments:

  1. Hi Hari...very usefull for the beginners like me....

    I am new to Opencv and want to know more resources in Opencv.

    Please provide me links to any site for sample codes in opencv....

    my email id is ananthnath@gmail.com

    ReplyDelete
  2. Hello Haris.. Thanks for posting this...

    ReplyDelete
  3. Is there a way to match the brightness and contrast of two images..Say there are two images A and B which will be combined or part of Image A is replace by B. How do we reduce the impact of different brightness levels and contrast in the final image with out loosing color.

    ReplyDelete
    Replies
    1. You may need to calculate histogram of A and B and replace the the histograms each other. You can refer these links, how to do this.
      http://stackoverflow.com/questions/17207916/how-to-perform-skin-tone-matching
      http://stackoverflow.com/questions/17542521/swap-histogram-of-two-different-images

      Delete