将.pdf或图像中的框检测并裁剪为单个图像

时间:2019-07-17 04:30:02

标签: python opencv image-processing computer-vision pypdf2

我有多页.pdf(扫描的图像),其中包含笔迹,我想将其裁剪并存储为新的单独图像。例如,在下面的视觉图中,我想将2个框内的笔迹提取为单独的图像。如何使用python自动为大型,多页.pdf文件执行此操作?

enter image description here

我尝试使用PyPDF2包根据(x,y)坐标裁剪其中一个手写框,但是这种方法对我不起作用,因为手写框的边界/坐标不会总是pdf中的每一页都相同。我相信检测盒子会是自动裁剪的更好方法。不知道它是否有用,但是下面是我用于(x,y)坐标方法的代码:

from PyPDF2 import PdfFileReader, PdfFileWriter

reader = PdfFileReader('data/samples.pdf', 'r')

# getting the first page
page = reader.getPage(0) 

writer = PdfFileWriter()

# Loop through all pages in pdf object to crop based on (x,y) coordinates
for i in range(reader.getNumPages()):
    page = reader.getPage(i)
    page.cropBox.setLowerLeft((42,115)) 
    page.cropBox.setUpperRight((500, 245)) 
    writer.addPage(page)

outstream = open('samples_cropped.pdf','wb')
writer.write(outstream)
outstream.close()

预先感谢您的帮助

1 个答案:

答案 0 :(得分:3)

这是使用OpenCV的简单方法

  • 将图像转换为灰度和高斯模糊
  • 阈值图像
  • 找到轮廓
  • 遍历轮廓并使用轮廓区域过滤
  • 提取投资回报率

提取ROI后,您可以将它们另存为单独的图像,然后使用pytesseract或其他工具执行OCR文本提取。


结果

enter image description here

enter image description here

您提到了

  

pdf页面中的每一页,手写框的边界/坐标都不会始终相同。

当前,您使用(x,y)坐标的方法不是很可靠,因为这些框可能位于图像上的任何位置。更好的方法是使用最小阈值轮廓区域进行过滤以检测框。根据要检测的盒子大小,您可以调整变量。如果要进行其他过滤以防止误报,可以将其添加到aspect ratio中作为另一种过滤机制。例如,计算每个轮廓的宽高比,然后,如果它在范围之内(例如,对于正方形/矩形ROI来说是0.81.2),那么它就是一个有效的框。

import cv2

image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
thresh = cv2.threshold(blurred, 230,255,cv2.THRESH_BINARY_INV)[1]

# Find contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

# Iterate thorugh contours and filter for ROI
image_number = 0
min_area = 10000
for c in cnts:
    area = cv2.contourArea(c)
    if area > min_area:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
        ROI = original[y:y+h, x:x+w]
        cv2.imwrite("ROI_{}.png".format(image_number), ROI)
        image_number += 1

cv2.imshow('image', image)
cv2.waitKey(0)