【发布时间】:2020-11-27 15:20:05
【问题描述】:
我正在尝试从图像中删除水平线和垂直线。此图像是使用 pdf2jpg 库从 pdf 生成的。在移除水平线和垂直线后,该图像将被馈送到 pytesseract 以提取单词及其各自的坐标。这里我只是为了测试目的而提取全文。 我是 OpenCV 的新手。我通过累积来自不同网站的代码 sn-ps 编写了这段代码,包括堆栈溢出。除了偶尔有一些垂直线残留外,该代码几乎可以完美运行。这些残余物混淆了正方体,有时被视为 I、1 或 |。此外,对于处理后的图像,tesseract 的误读次数(如 s 被读取为 5,I 被读取为 1 或 | 反之亦然)似乎高于原始图像。我认为原因是字体清晰度低于我们开始使用的原始图像。可以对此代码进行哪些更改,以删除那些垂直线的残余而不影响字体清晰度。任何正确方向的建议或指导将不胜感激。提前致谢
from importlib import invalidate_caches
from pytesseract import image_to_string
#from pdf2image import convert_from_path
from pdf2jpg.pdf2jpg import convert_pdf2jpg
from PIL import Image
import sys
import cv2
import numpy
def pre_process(image):
if isinstance(image, str):
image = cv2.imread(image, cv2.IMREAD_GRAYSCALE)
else:
# image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
pass
#Convert the image to true black n white from grayscale
threshold, image_bin = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
#Invert the image to change white to black and vice versa
image_inv = 255-image_bin
#Define kernels for horizontal and vertical lines
kernel_len = numpy.array(image).shape[1]//100
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_len))
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_len, 1))
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
#Remove anything that is not a vertical line
image_inv1 = cv2.erode(image_inv, vertical_kernel, iterations=3)
vertical_lines = cv2.dilate(image_inv1, vertical_kernel, iterations=3)
#Remove anything that is not a horizontal line
image_inv2 = cv2.erode(image_inv, horizontal_kernel, iterations=3)
horizontal_lines = cv2.dilate(image_inv2, horizontal_kernel, iterations=3)
#Add horizontal and vertical lines to get all lines
image_vh = cv2.addWeighted(vertical_lines, 0.5, horizontal_lines, 0.5, 0.0)
image_vh = cv2.erode(~image_vh, kernel, iterations=2)
threshold, image_vh = cv2.threshold(image_vh, 128, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
# Make a inverted copy of original grayscale image
org_img_inv = cv2.bitwise_not(image)
#Apply mask of all lines
final_image_inv = cv2.bitwise_and(org_img_inv, org_img_inv, mask=image_vh)
#Invert again to get clean image without lines
image = cv2.bitwise_not(final_image_inv)
cv2.imshow("final", image)
cv2.waitKey(0)
return image
if __name__ =="__main__":
pdf_path = sys.argv[1]
images = convert_pdf2jpg(pdf_path, "temp", dpi=100, pages="ALL")
result = ""
for image_path in images[0]["output_jpgfiles"]:
# with Image.open(image_path) as image:
# text = image_to_string(image)
# result = "\n".join((result, text))
image = pre_process(image_path)
#image = pre_process(image)
text = image_to_string(image)
result = "\n".join((result, text))
# print(result)
with open("text.txt", "w") as out:
out.write(result)
# pre_process(image_path)
# break
请找到随附的 pdf,我将其用作代码的输入 pdf 和处理图像的片段以供参考。代码可以使用命令提示符触发
python .\read_pdf_ocr.py path_to_pdf_file
环境详情:
- Python:3.7.9
- 库:
- opencv-python:4.4.0.46
- pdf2jpg:1.0
- pytesseract:0.3.6
- Tesseract-OCR - 开源 OCR 引擎:v5.0.0-alpha.20200328
【问题讨论】:
-
我赞成你的问题,但请确保代码是minimal reproducible example。另外,请考虑在代码中添加一些 cmets 以帮助其他人。
-
要去除水平和垂直线条,您的图像需要先旋转,使线条更加水平和垂直。
-
作为中间解决方案,您可以指明文本所在的区域。这将消除对更多处理的需要。
-
@Suthiro - 非常感谢。这是我在 Stack Overflow 上的第一篇文章。我会在一段时间内添加 cmets。此代码将成为我正在构建的更大代码库的一部分,以从 pdf 创建数据提取框架。我已经在git中上传了代码,并计划在它稳定时将其公开。我已经提供了我认为重新创建场景所需的最少部分。
-
@fmw42- 是的,这是真的。如果您检查随附的 PDF,您会发现它们是完全水平和垂直的,但它们仍然会留下我无法摆脱的微弱线条标记。我尝试使用内核大小但没有运气。水平线似乎消失了,但垂直线仍然存在。可以在处理图像的片段中看到输出图像。对于带有倾斜扫描图像的 PDF,我们将不得不合并这种旋转。感谢您的想法
标签: python python-3.x opencv python-tesseract