Home > Image Processing, Tips > 1D Histogram on OpenCV

1D Histogram on OpenCV

Histogram OpenCV
I started working on OpenCV this week, and it had been quite a journey.

I started with some easy programs. However, there is a new (at least for me is new) version of OpenCV with wrappers for C++. Therefore, the examples in the web, most of the time, do not work as they are.

So, today I will show you some of the work I’ve done deciphering the examples that work with the C code for the new wrappers.

OK, lets see. I wanted to do a simple histogram visualization of an image. But, all the examples in the web deal with two dimensional histograms, or with the old syntax. After checking a couple of webs I came up with a solution inspired by this post.

The idea is the same, but I change the functionality to work with OpenCV v2.2.

First, you need to create the histogram options, I think is really annoying, but it gives you more control over your final histogram.

  int nbins = 256; // lets hold 256 levels
  int hsize[] = { nbins }; // just one dimension
  float range[] = { 0, 255 };
  const float *ranges[] = { range };
  int chnls[] = {0};

with this code, you create only one dimensional histogram with 256 bins in the range of 0 to 255, and you specify to work with the channel 0 (the only channel). If you need more dimensions just add them in the hsize and ranges variables. If you see further, the histogram computation is designed to work with several dimensions, that’s why we need to pass arrays to it.

Then you just need to compute the histogram using

<pre>  calcHist(&colors[0], 1, chnls, Mat(), hist,1,hsize,ranges);</pre>

Note that the histogram image hist must be a MatND or a SparceMat. Then to render the histogram just compute the rectangles for each bin using the fillConvexPoly function. The full code looks like this. You can download the files here, please change the extension to rar to use them. It contains a CMakeLists to build it using CMake.

HTH :mrgreen:, I hope to be posting more on this topics soon.

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;

Mat imHist(Mat hist, float scaleX=1, float scaleY=1){
  double maxVal=0;
  minMaxLoc(hist, 0, &maxVal, 0, 0);
  int rows = 64; //default height size
  int cols = hist.rows; //get the width size from the histogram
  Mat histImg = Mat::zeros(rows*scaleX, cols*scaleY, CV_8UC3);
  //for each bin
  for(int i=0;i<cols-1;i++) {
    float histValue = hist.at<float>(i,0);
    float nextValue = hist.at<float>(i+1,0);
    Point pt1 = Point(i*scaleX, rows*scaleY);
    Point pt2 = Point(i*scaleX+scaleX, rows*scaleY);
    Point pt3 = Point(i*scaleX+scaleX, (rows-nextValue*rows/maxVal)*scaleY);
    Point pt4 = Point(i*scaleX, (rows-nextValue*rows/maxVal)*scaleY);

    int numPts = 5;
    Point pts[] = {pt1, pt2, pt3, pt4, pt1};

    fillConvexPoly(histImg, pts, numPts, Scalar(255,255,255));
  }
  return histImg;
}

int main( int argc, char** argv ) {
  // check for supplied argument
  if( argc < 2 ) {
    cout << "Usage: loadimg <filename>\n" << endl;
    return 1;
  }

  // load the image, load the image in grayscale
  Mat img = imread( argv[1], CV_LOAD_IMAGE_COLOR );

  // always check
  if( img.data == NULL ) {
    cout << "Cannot load file " << argv[1] << endl;
    return 1;
  }

  //Hold the histogram
  MatND hist;
  Mat histImg;
  int nbins = 256; // lets hold 256 levels
  int hsize[] = { nbins }; // just one dimension
  float range[] = { 0, 255 };
  const float *ranges[] = { range };
  int chnls[] = {0};

  // create colors channels
  vector<Mat> colors;
  split(img, colors);

  // compute for all colors
  calcHist(&colors[0], 1, chnls, Mat(), hist,1,hsize,ranges);
  histImg = imHist(hist,3,3);
  imshow("Blue",histImg);

  calcHist(&colors[1], 1, chnls, Mat(), hist,1,hsize,ranges);
  histImg = imHist(hist,3,3);
  imshow("Green",histImg);

  calcHist(&colors[2], 1, chnls, Mat(), hist,1,hsize,ranges);
  histImg = imHist(hist,3,3);
  imshow("Red",histImg);

  // show image
  imshow("Image", img);

  // wait until user press a key
  waitKey(0);

  // no need to release the memory, Mat do it for you
  return 0;
}
About these ads
  1. May 6, 2011 at 1:33 am | #1

    nice work..

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: