Ask Your Question

Extracting A4 sheet out of troubling backgrounds

asked 2017-09-14 02:33:12 -0500

maephisto gravatar image

updated 2017-09-14 02:34:42 -0500

So, my challenge is to extract a A4 paper document out of a mobile phone photo. I'm currently doing it using by applying gaussian blur and canny, find the contours and then pick the biggest most rectangle-ish contour. That works great for photos in which the document is having a uniform dark background but if the background is white or containing other shapes then the whole solution goes bananas.

Any suggestion how to get rid of this problem and be less vulnerable to unexpected backgrounds?

Below you can find two troubling images and my current implementation. I'm using python 2.7.9 and opencv

image with white background image description

    image = cv2.imread(args["image"])
  ratio = image.shape[0] / 500.0
  orig = image.copy()
  image = imutils.resize(image, height = 500)

  # convert the image to grayscale, blur it, and find edges
  # in the image
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  gray = cv2.GaussianBlur(gray, (5, 5), 0)
  edged = cv2.Canny(gray, 75, 200)

  (cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
  cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]

  # loop over the contours
  for c in cnts:
    # approximate the contour
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)

    # if our approximated contour has four points, then we
    # can assume that we have found our screen
    if len(approx) == 4:
      screenCnt = approx

  cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted

answered 2017-09-15 02:14:59 -0500

Ziri gravatar image

Performing Canny on noisy images will lead to bad results, It is preferable to choose better color space (Lab (*b)) and threshold or use another edge detector for example:

image description image description

You can find straight lines using hough transform ( eliminate unwanted lines) then find intersections. You can also use generalized hough to detect rectangle but that's not supported in Opencv.

Method 2 :

-Threshold and eliminate unwanted contours . - Use Minimum area rectangle.

edit flag offensive delete link more


Thank you for the advice, Ziri, it sounds like a good approach! Can I ask what ops/steps did you apply to get to the tow results you provided?

maephisto gravatar imagemaephisto ( 2017-09-15 03:12:01 -0500 )edit

Use cvtColor with CV_RGB2Lab (try other color spaces) then split to take single chanel ( b in this case) . Also try color thresholding using inRange

Ziri gravatar imageZiri ( 2017-09-15 07:44:34 -0500 )edit

You can use : lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)

flavienb gravatar imageflavienb ( 2019-04-13 17:10:30 -0500 )edit

answered 2017-09-15 00:15:09 -0500

gurankas gravatar image

I would suggest you follow this tutorial to make a scanner in Python with ease

As for the background problem, I too am stuck in the same problem. But I would suggest you to perform median blur followed by adaptive threshold as preprocessing before using canny on the image. It isolates the page from background quite effectively. Just play around with the threshold values. I used 21 for median blur and 41,7 with adaptive threshold

PS If you do get results, please upload your pre-canny resultant image and post-canny image so that I can debug my problem too ;)

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2017-09-14 02:33:12 -0500

Seen: 3,057 times

Last updated: Sep 15 '17