1

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:

(https://i.imgur.com/0FxnfOe.jpg) Here is what I already tried:

Method 1: (using thresholding)

  1. Preprocessing the image with image smoothening (guassian blur/bilateralblur)
  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: Link: https://stackoverflow.com/a/47898407/10337002 I'm able to find the paper sheet for some images, but it fails for images like this:

(https://i.imgur.com/S905YGL.jpg)

Method 2: (using sobel gradient operator)

  1. Preprocessing the image by converting into grayscale, image smoothening (guassian blur/bilateralblur)
  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: Link: https://stackoverflow.com/a/31888883/10337002 Here's how far I got with the image:

(https://i.imgur.com/499bJFN.png)

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/bilateralblur)
  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: Link: https://stackoverflow.com/a/8863060/10337002, 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:

(https://i.imgur.com/alx7qYh.png)

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.

Beeti Sushruth
  • 191
  • 1
  • 8
  • 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. – Yves Daoust 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. – Yves Daoust 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