0

I have the following picture and I would like to detect the border of the page and then to refocus to see "only" the page. How can I start to code this with opencv3 and Python 3 ?

enter image description here

projetmbc
  • 1,332
  • 11
  • 26

1 Answers1

3

You can simply use thresholding methods to seperate the paper from background. To demonstrate:

Read image and convert to gray.

image = cv2.imread("page.jpg")
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

check histogram to choose threshold values. More here

color = ('b','g','r')
fig = plt.figure(figsize=(12,12))
ax = fig.add_subplot(1,2,1)
ax.imshow(image)
ax1 = fig.add_subplot(1,2,2)
for i,col in enumerate(color):
    histogram = cv2.calcHist([image],[i],None,[256],[0,256])
    ax1.plot(histogram,color = col)
    ax1.set_xlim([0,256])

Use blur to get rid of the notebook's details.

blurred_gray_image = cv2.blur(gray_image,(21,21))

Do thresholding. Using values which we got from the histogram.

_,thresholded_blurry_image = cv2.threshold(blurred_gray_image,165,255,cv2.THRESH_BINARY)

Detect contours (which are undivided, closed shapes).

contours, hierarchy = cv2.findContours(thresholded_blurry_image,
cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Draw the biggest contour's outline to the copy of the original image if there are any contours.Source post for finding the biggest contour.

output = image.copy()
if len(contours) != 0:
    c = max(contours, key = cv2.contourArea)
    # coordinates of the contour
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(output,(x,y),(x+w,y+h),(0,255,0),2)

Show the result

output = cv2.cvtColor(output,cv2.COLOR_BGR2RGB)
plt.imshow(output)

Output

You can use cv2.imwrite() function to save the image. Hope this answer satisfies your question. But be aware that this method won't always work because we evaluate the histogram ourselves and pick the thresholding values by hand. If you want to take a more general approach try adaptive thresholding or evaluate histogram values with help of an algorithm. Best of luck.

Meto
  • 638
  • 7
  • 18