OpenCV - canny edge detection not working properly

ImLearning picture ImLearning · Jan 27, 2017 · Viewed 9.9k times · Source

I am new to OpenCV with Android. I am currently working on document detection demo app. What I did so far is as below:

Original image -> Gray scale image -> GaussianBlur -> Canny edge detection -> finding contours -> draw Contours

I am able to detect paper sheet perfectly as you can see in below image .

enter image description here

But it does not detect some documents. Below is one of them

enter image description here

I researched a lot about that and found that the problem lies in canny edge detection and below is the canny image :

enter image description here

As you can see , the edge detection is not perfectly linked and it does not connect edges at some point. That is the reason for that .

I have gone through the similar issue at : How to select the best set of parameters in Canny Edge detection algorithm implemented in OpenCV? I have followed the solution but it didn't worked for me.

My canny detection code is as follow :

double otsu_thresold = Imgproc.threshold(mGray,edged,0,255, Imgproc.THRESH_OTSU);
Imgproc.Canny(mRgba, edged, otsu_thresold*0.5,otsu_thresold);

I don't know where I am wrong! What should I do to perfectly detect the document?

Answer

Jeru Luke picture Jeru Luke · Jan 27, 2017

First the method of performing Canny edge detection has to change. You are setting a lower and higher threshold in cv2.Canny()manually. You can do this automatically. I used THIS LINK as reference.

Use the following snippet:

v = np.median(gray_image)

#---- apply automatic Canny edge detection using the computed median----
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edged = cv2.Canny(gray_image, lower, upper)
cv2.imshow('Edges',edged)

So what am I doing here?

I am taking the median value of the gray scale image. The sigma value of 0.33 is chosen to set the lower and upper threshold. 0.33 value is generally used by statisticians for data science. So it is considered here as well.

This is what I got:

enter image description here

To enhance this edge information I performed morphological dilation using the cv2.MORPH_CROSS kernel:

enter image description here

Now just perform the usual cv2.findContours() operation and draw the biggest contour.

:)