2

Out of an image, I need to extract a sheet of paper, just like camscanner app does, https://www.camscanner.com/

I know that I can do this by detecting the edges of the sheet of paper i want to detect. And later performing perspective transform. I use openCV library in python. This is the image in which I'm trying to find the sheet of paper:

sheet of paper to detect

Here is what I already tried:

Method 1: (using thresholding)

  1. Preprocessing the image with image smoothening (guassian blur/bilateral blur)
  2. splitting image into h,s,v channels
  3. adaptive thresholding on the saturation channel
  4. some morphological operations like dilation and erosion
  5. finding contours, identifying the largest contour and finding the corner points

I've implemented this method based on a stackoverflow answer: Detecting a sheet of paper / Square Detection

I'm able to find the paper sheet for some images, but it fails for images like this:

failed paper detection

Method 2: (using sobel gradient operator)

  1. Preprocessing the image by converting into grayscale, image smoothening (guassian blur/bilateral blur)
  2. Finding the gradients of the image
  3. downsampling and upsampling the image
  4. After this I don't know how to find the appropriate boundary enclosing the image.

I've implemented this method based on a stackoverflow answer: detect paper from background almost same as paper color

Here's how far I got with the image:

sobel gradient result

Method 3: (using canny edge detector)

According to the posts I've read on this community seems that everyone prefers canny edge method to extract the edges, but in my case the results are not satisfactory. Here's what I did:

  1. Preprocessing the image by converting into grayscale, image smoothening (guassian blur/bilateral blur)
  2. Finding the edges using canny edge
  3. some morphological operations like dilation and erosion
  4. But the edges obtained from canny are really not up to the mark.

I've implemented this method based on a stackoverflow answer: Detecting a sheet of paper / Square Detection, also I didn't quite what he does by iterating over multiple channels in this answer. Here's how far I got with the image:

canny result

Here's some code on the method1(thresholding):

#READING IMAGE INTO BGR SPACE
image = cv2.imread("./images/sheet3.png")
#BILATERAL FILTERING TO SMOOTHEN THE IMAGE BUT NOT THE EDGES
img = cv2.bilateralFilter(image,20,75,75)
#CONVERTING BGR TO HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#SPLITTING THE HSV CHANNELS
h,s,v = cv2.split(hsv)
#DOUBLING THE SATURATION CHANNEL
gray_s = cv2.addWeighted(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 0.0, s, 2.0, 0)
#THRESHOLDING USING ADAPTIVETHRESHOLDING
threshed = cv2.adaptiveThreshold(gray_s, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 109, 10)
#APPLYING MORPHOLOGICAL OPERATIONS OF DILATION AND EROSION
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
morph = cv2.morphologyEx(threshed, cv2.MORPH_OPEN, kernel)
#FINDING ALL THE CONTOURS
cnts = cv2.findContours(morph, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
canvas  = img.copy()
#SORTING THE CONTOURS AND TAKING THE LARGEST CONTOUR
cnts = sorted(cnts, key = cv2.contourArea)
cnt = cnts[-1]
#FINDING THE PERIMETER OF THE CONTOUR
arclen = cv2.arcLength(cnt, True)
#FINDING THE END POINTS OF THE CONTOUR BY APPROX POLY DP
approx = cv2.approxPolyDP(cnt, 0.02* arclen, True)
cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA)
cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imwrite("detected.png", canvas)  

I'm kind of new to image processing and openCV. Please share some insights on how to take this further and obtain results more accurately. TIA.

Burak
  • 2,251
  • 1
  • 16
  • 33
Beeti Sushruth
  • 321
  • 2
  • 12
  • Edge detection performs usually poorly for such problems. Prefer region detection, like in method 1 (possibly with adaptive thresholding, and exploiting color where possible). For a case like https://i.imgur.com/S905YGL.jpg, just drop the idea, nothing will work reliably. –  Aug 22 '19 at 10:11
  • @YvesDaoust I was thinking the same, as you can see in the code i mentioned above, I've used adaptive thresholding, because threshold changes at every pixel, the above method also doesn't yield accurate result, for example this image: https://i.imgur.com/XcTydIL.jpg, this is the thresholded image: https://i.imgur.com/e6tVjaR.png – Beeti Sushruth Aug 22 '19 at 10:28
  • Don't expect miracles, but use a larger filter (don't content yourself with a single attempt). Also have a look at other segmentation methods. –  Aug 22 '19 at 10:30
  • please search for existing questions and answers. I feel like detecting a sheet of paper is brought here like twice a day. – Piglet Aug 22 '19 at 11:20
  • @Piglet all the above code which I've written is from previous answers, although as I've mentioned, the answers don't hold for some images For example: i.imgur.com/e6tVjaR.png. I'm only asking for additional processing that needs to be done. Thanks – Beeti Sushruth Aug 22 '19 at 11:43

0 Answers0