识别扫描的 PDF 图像中的页码
Recognizing page numbers in scanned PDF image
我有很多 PDF,基本上都是扫描的文档或书籍,所以每个 PDF 页面都有两个扫描图像,我必须拆分这些页面并根据页面上写的页数进行整理印刷。页面拆分不是问题(我正在使用 mutool 海报),问题是:“如何从页面(图像)的 PDF 部分检测页码?
这是一个页面示例
我试过 python + opencv + tesseract 但没有结果,因为我无法检测到数字的正确位置(它可以在任何角落)或者如果 opencv 检测到该位置然后 tesseract 可以'检测文本
这是一个方法
- 将图像转换为灰度并反转图像
- 扩张以获得单个轮廓的字母
- 寻找轮廓
- 裁剪每个轮廓的 ROI 并放入 Pytesseract
- 如果结果是数字则保存ROI
转换为灰度并反转图像
image = cv2.imread('2.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = 255 - gray
现在我们扩展以将 letters/contours 连接在一起。这个想法是页码轮廓将与页面上的其他字符分开,即使它可以在任何角落
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(gray, kernel, iterations=4)
我们从这里找到轮廓,然后提取 ROI。我们将每个 ROI 放入 Pytesseract。如果返回的结果都是数字那么我们已经检测到页码ROI所以我们可以用Numpy切片保存它
image_number = 0
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
ROI = original[y:y+h, x:x+w]
data = pytesseract.image_to_string(ROI, lang='eng', config='--psm 10')
if data.isdigit():
print('Page #: ', data)
cv2.imwrite("ROI_{}.png".format(image_number), ROI)
image_number += 1
这是 Pytesseract 的结果和提取的 ROI
Page #: 110
完整代码
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
image = cv2.imread('2.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = 255 - gray
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(gray, kernel, iterations=4)
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
image_number = 0
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
ROI = original[y:y+h, x:x+w]
data = pytesseract.image_to_string(ROI, lang='eng', config='--psm 10')
if data.isdigit():
print('Page #: ', data)
cv2.imwrite("ROI_{}.png".format(image_number), ROI)
image_number += 1
cv2.imshow('gray', gray)
cv2.imshow('dilate', dilate)
cv2.imshow('original', original)
cv2.waitKey()
我有很多 PDF,基本上都是扫描的文档或书籍,所以每个 PDF 页面都有两个扫描图像,我必须拆分这些页面并根据页面上写的页数进行整理印刷。页面拆分不是问题(我正在使用 mutool 海报),问题是:“如何从页面(图像)的 PDF 部分检测页码?
这是一个页面示例
我试过 python + opencv + tesseract 但没有结果,因为我无法检测到数字的正确位置(它可以在任何角落)或者如果 opencv 检测到该位置然后 tesseract 可以'检测文本
这是一个方法
- 将图像转换为灰度并反转图像
- 扩张以获得单个轮廓的字母
- 寻找轮廓
- 裁剪每个轮廓的 ROI 并放入 Pytesseract
- 如果结果是数字则保存ROI
转换为灰度并反转图像
image = cv2.imread('2.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = 255 - gray
现在我们扩展以将 letters/contours 连接在一起。这个想法是页码轮廓将与页面上的其他字符分开,即使它可以在任何角落
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(gray, kernel, iterations=4)
我们从这里找到轮廓,然后提取 ROI。我们将每个 ROI 放入 Pytesseract。如果返回的结果都是数字那么我们已经检测到页码ROI所以我们可以用Numpy切片保存它
image_number = 0
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
ROI = original[y:y+h, x:x+w]
data = pytesseract.image_to_string(ROI, lang='eng', config='--psm 10')
if data.isdigit():
print('Page #: ', data)
cv2.imwrite("ROI_{}.png".format(image_number), ROI)
image_number += 1
这是 Pytesseract 的结果和提取的 ROI
Page #: 110
完整代码
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
image = cv2.imread('2.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = 255 - gray
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(gray, kernel, iterations=4)
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
image_number = 0
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
ROI = original[y:y+h, x:x+w]
data = pytesseract.image_to_string(ROI, lang='eng', config='--psm 10')
if data.isdigit():
print('Page #: ', data)
cv2.imwrite("ROI_{}.png".format(image_number), ROI)
image_number += 1
cv2.imshow('gray', gray)
cv2.imshow('dilate', dilate)
cv2.imshow('original', original)
cv2.waitKey()