Crop exact document paper from image by removing black border from photos in Java/Python

六眼飞鱼酱① 提交于 2020-06-27 19:39:27

问题


I have taken some pictures of index cards but now I have the problem that the photographing was not perfect of course and there is a black border on each photo. I would like to crop the photo so that only the index card is left without a border.

Online I could find a similar problem, but it was only about computer images, so you could assume that the black had RGB (0,0,0), which is not the case with me. In the middle there is also black text, which I don't want to cut out.

Do you have any ideas how I can approach this?

Here is an example picture (it is in German):


回答1:


The idea is to threshold the image to obtain a binary image then find contours and sort using contour area. The largest contour should be the index card. We can then apply a four point perspective transform to obtain a birds eye view of the image. Here's the results:

Binary image

Result

The result is dark so to increase the contrast look at Automatic contrast and brightness adjustment of a color photo of a sheet of paper with OpenCV. Also it's slightly skewed so you should perform skew correction. Take a look at Python OpenCV skew correction, How to de-skew an image, and Detect image orientation angle based on text direction

I'll leave these steps to you :)

Code

from imutils.perspective import four_point_transform
import cv2
import numpy

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread("1.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Find contours and sort for largest contour
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None

for c in cnts:
    # Perform contour approximation
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    if len(approx) == 4:
        displayCnt = approx
        break

# Obtain birds' eye view of image
warped = four_point_transform(image, displayCnt.reshape(4, 2))

cv2.imshow("thresh", thresh)
cv2.imshow("warped", warped)
cv2.imshow("image", image)
cv2.imwrite("thresh.png", thresh)
cv2.imwrite("warped.png", warped)
cv2.imwrite("image.png", image)
cv2.waitKey()



回答2:


Maybe, this previous post's answer is helpful https://stackoverflow.com/a/21568925/9851541 Further, this may also prove helpful

from PIL import ImageChops

     def trim(im, border):
         bg = Image.new(im.mode, im.size, border)
         diff = ImageChops.difference(im, bg)
         bbox = diff.getbbox()
         if bbox:
             return im.crop(bbox)
         else:
             # found no content
             raise ValueError("cannot trim; image was empty")


来源:https://stackoverflow.com/questions/60145395/crop-exact-document-paper-from-image-by-removing-black-border-from-photos-in-jav

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!