Canny Edge Detection Auto Thresholding
In the example I gave in “Interfacing IPP with Magick++“, I illustrated how to use Intel’s Integrated Performance Primitives (IPP) to perform edge detection. One issue with Canny edge detection algorithm is that we need to specify a high threshold and a low threshold. How to select those threshold values affect the quality of the detected edge greatly. And in my previous example, the threshold values were chosen manually. In this blog post, I will examine a couple of simple methods that can be used to automatically determine the threshold values.
The simplest way is to use the mean value of the gray scale image pixel values. As a rule of thumb, we set the low threshold to 0.66*[mean value] and set the high threshold to 1.33*[mean value]. Another way is to use the median color in the gray scale image and uses 0.66*[median value] and 1.33*[median value] accordingly. For typical images, these two methods achieve comparable results.
For example, the following shows the picture of a building along with its histogram (original image from Microsoft Research Digital Image. Please see Microsoft Research Digital Image License Agreement for more information):
The following shows the edge detection results using Canny algorithm (left image uses mean value auto-thresholding, right image uses median value auto-thresholding) and the results exhibit very little visible differences.
However, for images has non-equalized histogram (see the picture of cloud and its histogram below):
Canny Edge detection result based on mean value auto-thresholding is pretty poor (see image on the left below), while edge detection based on median value auto-thresholding achieved much better result (see image on the right below)
Alternatively, we could have performed histogram equalization on the image first before applying Canny edge detection with mean auto-thresholding:
And after image equalization, both mean and median value auto-thresholding achieved similar results.
So the Canny edge detection using median value auto-thresholding seems to adapt to different types of images very well (note selecting the median value selection can be thought as equalizing the histogram, except that the pixel values are not changed during such operation).
The following is the code listing for the histogram calculation using IPP (based on the image class I created earlier)
/** @brief Get the min max mean value statistics for the current image * @param min, max, mean: these are output parameters that are passed * back by reference. */ void IPPGrayImage::MinMaxMean(float& min, float& max, double& mean) { IppStatus sts; IppiSize origImgSize = {_width, _height}; sts = ippiMinMax_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, &min, &max); assert(sts == ippStsNoErr); sts = ippiMean_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, &mean, ippAlgHintFast); assert(sts == ippStsNoErr); } /** @brief Calculate the histogram of the image * @param nLevel: the number of bins in the histogram * levels: this is the optional levels user can pass in (histogram will be then * calculated with these levels instead of the uniform levels by default. * @return an integer array which contains the histogram. * @note the histogram is by default calculated using uniform bins across the color range. */ unsigned int * IPPGrayImage::GetHistogram(unsigned int nLevel, float levels[]) { IppStatus sts; Ipp32f* l = new Ipp32f[nLevel]; IppiSize origImgSize = {_width, _height}; unsigned int* bins = new unsigned int[nLevel - 1]; float minVal = 0, maxVal = 0, stepVal = 0; double meanVal = 0; if (levels != NULL) { for (unsigned int i = 0; i < nLevel; i++) { l[i] = levels[i]; } } else { MinMaxMean(minVal, maxVal, meanVal); stepVal = (maxVal - minVal) / (float) nLevel; for (unsigned int i = 0; i < nLevel; i++) { l[i] = minVal + stepVal * i; } } sts = ippiHistogramRange_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, (Ipp32s*) bins, (Ipp32f*) l, nLevel); return bins; }
is there any vb6 code for canny autothresholding? tnx!
i need canny edge detection in vb(source code )
please help me
tnx
#include”stdafx.h”
#include “cv.h”
#include “cxcore.h”
#include”cvaux.h”
#include “highgui.h”
int main()
{
IplImage* newImg = NULL;
IplImage* grayImg = NULL;
IplImage* contourImg = NULL;
IplImage* cannyImg;
//parameters for the contour detection
CvMemStorage * storage = cvCreateMemStorage(0);
CvSeq * contour = 0;
int mode = CV_RETR_EXTERNAL;
mode = CV_RETR_CCOMP; //detect both outside and inside contour
cvNamedWindow(“src”, 1);
cvNamedWindow(“contour”,1);
//load original image
newImg = cvLoadImage(“C:/Documents and Settings/welcome/Desktop/tom2.jpg”,1);
//create a single channel 1 byte image (i.e. gray-level image)
grayImg = cvCreateImage( cvSize(newImg->width, newImg->height), IPL_DEPTH_8U, 1 );
//convert original color image (3 channel rgb color image) to gray-level image
cvCvtColor( newImg, grayImg, CV_BGR2GRAY );
cvShowImage( “src”, newImg );
cannyImg = cvCreateImage(cvGetSize(newImg), IPL_DEPTH_8U, 1);
// canny edge detection
cvCanny(grayImg, cannyImg, 50, 150, 3);
cvNamedWindow(“src”, 1);
cvNamedWindow(“canny”,1);
cvShowImage( “src”, newImg );
cvShowImage( “canny”, cannyImg );
cvReleaseImage( &newImg ); cvReleaseImage( &grayImg ); cvReleaseImage( &contourImg );
cvReleaseMemStorage(&storage);
return 0;
}
this code should be pasted in visual studio and also run opencv on ur sys to run the code. contact me on my e-mail if u hve any doubts, i did as my proj this sem so i can help u..
can i get your project about this?
pliss send to aliakbar.af92@gmail.com
thanx..
Your code will miss the values in the last bin i.e (maxVal-stepVal)->maxVal. your array only assigns bins between minVal and minVal+stepVal*(nLevel-1).
If you had 20 bins, a min of 20 a max of 220 you would have a step of 10 which would give you a max bin value of (20+10*(19))=210 so your histogram would never have any values for the bin between 210 and 220. The ippiHistogramRange_32f_C1R function requires the max value to be the last pLevels array.
try
unsigned int* bins = new unsigned int[nLevel];
for (unsigned int i = 0; i <= nLevel; i++)
{
l[i] = minVal + stepVal * i;
}
fogot to add
Ipp32f* l = new Ipp32f[nLevel+1];
hello sir/mam,
I am trying to detect blink in my project. I have thresholded the image and extracted the eye part. Now i want to count the number of pixels in sclera so that when i close my eyes i get reduced number of pixels and conclude that my eye is closed and apply blink function. But i am not able to do it. Could you please help me regarding this or suggest me any other way to implememnt it..
THANKYOU :)
[…] http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/ is one of the few resources that shows how to choose thresholds Tlow and […]
i need the full code for canny and auto thresholding
Hi,
I would like to know if there is any reference you can cite. I need to reference this method in a paper that I am writing.
This can’t work, you are using the mean of the image signal range when you are threshold a gradient information.
Kind regards,
Harold
hi sir,
I’m working on plant disease detection can you plz help me which algorithm is suitable for image processing
to extract features and how to pass these features to classification methods