4
votes

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?

2
in order to enhance the edges use morphological dilation. See THIS PAGE.Jeru Luke

2 Answers

8
votes

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.

:)

3
votes

I've got better results with a small adaption of the algorithm posted by Jeru Luke.

On document detection, we rather search for the dark shadowy edges of a document:

  • For light images, like with white paper, median is high and "255 - median" performs better than just median
  • For small values sigma is too small to produce a wide enought range.

Here is my C#-algorithm:

    double s = 0.33;
    if (imageMedian > 191) // light images
    {
      cannyTh1 = (int)Math.Max(0, (1 - 2*s) * (255 - imageMedian));
      cannyTh2 = (int)Math.Max(85, (1 + 2*s) * (255 - imageMedian));
    }
    else if (imageMedian > 127)
    {
      cannyTh1 = (int)Math.Max(0, (1 - s) * (255 - imageMedian));
      cannyTh2 = (int)Math.Min(255, (1 + s) * (255 - imageMedian));
    }
    else if (imageMedian < 63) // dark images
    {
      cannyTh1 = (int)Math.Max(0, (1 - 2*s) * imageMedian);
      cannyTh2 = (int)Math.Max(85, (1 + 2*s) * imageMedian);
    }
    else
    {
      cannyTh1 = (int)Math.Max(0, (1 - s) * imageMedian);
      cannyTh2 = (int)Math.Min(255, (1 + s) * imageMedian);
    }

Additionally, the result can be improved for some documents by

  • sharpening the image after using the median filter
  • using stronger median filter
  • computing median and perform canny filter for seperate parts of the image, because shadow and light influence can differ largely on parts of the image