Wednesday, 13 February 2013

Entropy-based histogram thresholding

I read about entropy thresholding[1] and I wanted to give it a try. This technique was rather simple to implement in Matlab compared to other more complex methods and performed reasonably (see results).

Code

  1. function [A, T] = EntropyThresholding(img)
  2.  
  3. [h, ~] = imhist(img);
  4. h = h/sum(h); % Normalize the histogram so that it sums to 1.
  5. entropies = zeros(256, 1); % Intialize array for storing entropies.
  6. for t = 1:254
  7. White = h(1:t);
  8. Black = h(t+1:255);
  9. % Add 0.001 to prevent division by zero(nan) and log of zero(-inf).
  10. HB = sum((Black/(0.001+sum(Black))).*log((Black+0.001)/(0.001 +sum(Black))));
  11. HW = sum((White/(0.001+sum(White))).*log((White+0.001)/(0.001 +sum(White))));
  12. entropies(t) = HB+HW;
  13. end
  14. [~, T] = max(abs(entropies)); % The Maximal entropy determines the threshold.
  15. T = T - 1;
  16. A = img > T;

Results

References

1. J.N. Kapur, P.K. Sahoo and A.K.C. Wong, "A New Method for Gray-Level Picture Thresholding Using the Entropy of the Histogram", CVGIP, (29), pp.273-285 , 1985.

Saturday, 2 February 2013

Draw an OpenCV histogram using QWT

The QWT Library gives us the ability to create graphs, scale axes, insert legend and do a whole lot of graphing stuff, in a very easy manner. I wanted to show how easy it was to use so in this tutorial I plot an openCV histogram using QWT.
The set-up for this tutorial is similar to the one in my previous tutorial, only this time I also include the OpenCV library. So we can dive straight into the code.

Code

  1. #include <QApplication>
  2. #include <qwt_plot.h>
  3. #include <qwt_plot_curve.h>
  4. #include <qwt_plot_grid.h>
  5. #include <qwt_symbol.h>
  6. #include <qwt_legend.h>
  7. #include <opencv2/core/core.hpp>
  8. #include <opencv2/imgproc/imgproc.hpp>
  9. #include <opencv2/highgui/highgui.hpp>
  10.  
  11. int main(int argc, char *argv[])
  12. {
  13. QApplication a(argc, argv);
  14.  
  15. if (argc < 2)
  16. return 1;
  17. //Read input image
  18. cv::Mat img = cv::imread(argv[1]);
  19. //Convert to grayscale
  20. if (img.data && img.channels() == 3)
  21. cv::cvtColor(img, img, CV_BGR2GRAY);
  22. else
  23. return 1;
  24.  
  25. int histSize[1] = {256}; // number of bins
  26. float hranges[2] = {0.0, 255.0}; // min and max pixel value
  27. const float* ranges[1] = {hranges};
  28. int channels[1] = {0}; // only 1 channel used
  29.  
  30. cv::MatND hist;
  31. // Compute histogram
  32. cv::calcHist(&img, 1, channels, cv::Mat(), hist, 1, histSize,ranges);
  33.  
  34. double minVal, maxVal;
  35. cv::minMaxLoc(hist, &minVal, &maxVal);//Locate max and min values
  36. QwtPlot plot; //Create plot widget
  37. plot.setTitle( "Plot Demo" ); //Name the plot
  38. plot.setCanvasBackground( Qt::black ); //Set the Background colour
  39. plot.setAxisScale( QwtPlot::yLeft, minVal, maxVal ); //Scale the y-axis
  40. plot.setAxisScale(QwtPlot::xBottom,0,255); //Scale the x-axis
  41. plot.insertLegend(new QwtLegend()); //Insert a legend
  42.  
  43. QwtPlotCurve *curve = new QwtPlotCurve(); // Create a curve
  44. curve->setTitle("Count"); //Name the curve
  45. curve->setPen( Qt::white, 2);//Set colour and thickness for drawing the curve
  46. //Use Antialiasing to improve plot render quality
  47. curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
  48. /*Insert the points that should be plotted on the graph in a
  49. Vector of QPoints or a QPolgonF */
  50. QPolygonF points;
  51. for( int h = 0; h < histSize[0]; ++h) {
  52. float bin_value = hist.at<float>(h);
  53. points << QPointF((float)h, bin_value);
  54. }
  55.  
  56. curve->setSamples( points ); //pass points to be drawn on the curve
  57. curve->attach( &plot ); // Attach curve to the plot
  58. plot.resize( 600, 400 ); //Resize the plot
  59. plot.show(); //Show plot
  60.  
  61. return a.exec();
  62.  
  63. }
The code is well commented and is therefore self explanatory - no need for extra explanations. The result can be seen in the image below.