于本文里面将会运用来演示怎么样去解析文档(像是pdf这般), 并把文本, 图形, 表格等之类的信息提取出来。
需对文档展开解析, 这其中涵盖检查文档里的数据, 以及提取有用的信息, 它能够借助自动化, 从而减少了数量众多的手工工作。一种十分流行的解析策略乃是把文档转变为图像, 进而运用计算机视觉予以识别。而文档图像分析, 也就是 Image , 所指的是从文档的图像的像素数据当中获取信息的技术, 在某些情形之下, 预期结果究竟会是怎样的, 并没有清晰明确的答案, 诸如文本、图像、图表、数字、表格、公式等等。
OCR , 也就是光学字符识别, 是借助计算机视觉针对图像里的文本展开检测以及提取的进程, 它是于第一次世界大战时期发明的, 那时以色列科学家伊曼纽尔·戈德堡发明了一台能够读取字符并把它转换为电报代码的机器, 到如今该领域已然达到了一个极其复杂的水准, 涵盖混合图像处理、文本定位、字符分割以及字符识别, 基本上属于一种针对文本的对象检测技术。
在这篇文章里头, 我会呈现怎样运用OCR去开展文档解析, 我会展现若干有用的代码, 这些代码能够轻易地被用于其他类似情形(仅仅需复制、粘贴、运行就行), 并给出完整的源代码下载。
这里将以一家上市公司的PDF格式的财务报表为例
检测和提取该PDF中的 文本、图形和表格
环境设置
让人感到烦恼的是文档解析这一部分, 其表现为有的针对各种各样不同类型数据(类似文本、图形、表格这样的数据)所使用的工具实在数量太多, 然而却没有任何一个所展现出来的工作状态会是完美无瑕尽善尽美的。底下呈现所列举的是作为一些最为流行的方法以及软件包之事:
也许你曾问, 为什么不直接对付那PDF文件, 却要把页面转作图像呢, 你能够这么去做。此策略的首要缺点是编码方面的问题, 文档能够采纳好些种编码, 像UTF-8、ASCII等, 所以转成文本没准会致使数据丢失。所以为避开生出这问题, 我会运用OCR, 并把页面转为图像, 留意PDF渲染库是必要的。
# with pip pip install python-poppler # with conda conda install -c conda-forge poppler你可以很容易地读取文件:
# READ AS IMAGE import pdf2imagedoc = pdf2image.convert_from_path("doc_apple.pdf") len(doc) #<-- check num pages doc[0] #<-- visualize a page与咱们所具有的截图完全相同, 要是打算把页面图像储存为本地形式的话, 能够运用这般的代码:
# Save imgs import osfolder = "doc" if folder not in os.listdir(): os.makedirs(folder)p = 1 for page in doc: image_name = "page_"+str(p)+".jpg" page.save(os.path.join(folder, image_name), "JPEG") p = p+1最后, 我们要对即将予以运用的CV引擎进行设置 , 它好像是首个基于深度学习的OCR通用包。它借助两个知名的模型来达成任务:。
: 最先进的目标检测库(这里将使用第二个版本)。
pip install layoutparser torchvision && pip install "git+https://github.com/facebookresearch/detectron2.git@v0.5#egg=detectron2"知名度最高的OCR系统, 起先由惠普公司于1985年创立, 当前则是由谷歌在所进行开发。
pip install "layoutparser[ocr]"现在已经准备好开始OCR程序进行信息检测和提取了。
import layoutparser as lp import cv2 import numpy as np import io import pandas as pd import matplotlib.pyplot as plt检测
检测目标, 是于图片里寻觅信息片段, 之后借由矩形边框将其予以包围的进程。针对文档解析而言, 这些信息涵盖标题、文本、图形、表……
让我们来看一个复杂的页面,它包含了一些东西:
这个页面起始于一个标题, 那儿存在着一个文本块, 接着是一幅图与一张表, 所以我们需要一个受过训练的模型去辨识这些对象, 所幸的是, 要完成此项任务, 我们仅需从这儿挑选一个模型, 并于代码里面指定它的路径。
我即将择用的模型, 仅仅能够检测4个对象, 它们为文本、标题、列表、表格、图形。所以, 要是你有识别其他事物的需求, 比方像方程之类的, 那你就得去运用别的模型。
## load pre-trained model model = lp.Detectron2LayoutModel( "lp://PubLayNet/mask_rcnn_X_101_32x8d_FPN_3x/config", extra_config=["MODEL.ROI_HEADS.SCORE_THRESH_TEST", 0.8], label_map={0:"Text", 1:"Title", 2:"List", 3:"Table", 4:"Figure"}) ## turn img into array i = 21 img = np.asarray(doc[i]) ## predict detected = model.detect(img) ## plot lp.draw_box(img, detected, box_width=5, box_alpha=0.2, show_element_type=True)结果涵盖每个被检测出的布局的详情, 像是边界框的坐标。将输出依照页面上呈现的顺序予以排序是颇具用处的:
## sort new_detected = detected.sort(key=lambda x: x.coordinates[1]) ## assign ids detected = lp.Layout([block.set(id=idx) for idx,block in enumerate(new_detected)])## check for block in detected: print("---", str(block.id)+":", block.type, "---") print(block, end='\n\n')完成OCR的下一步是正确提取检测到内容中的有用信息。
提取
我们对图像进行了分割, 之后, 要运用另外一个模型去处理分段后的图像, 并且要把提取的输出保存至字典当中。
因为具备不一样类型的输出, 这种输出涵盖文本、标题、图形以及表格, 所以在此预备了一个函数, 该函数的用途是用以展示结果。
''' {'0-Title': '...', '1-Text': '...', '2-Figure': array([[ [0,0,0], ...]]), '3-Table': pd.DataFrame, } ''' def parse_doc(dic): for k,v in dic.items(): if "Title" in k: print('\x1b[1;31m'+ v +'\x1b[0m') elif "Figure" in k: plt.figure(figsize=(10,5)) plt.imshow(v) plt.show() else: print(v) print(" ")首先看看文字:
# load model model = lp.TesseractAgent(languages='eng') dic_predicted = {} for block in [block for block in detected if block.type in ["Title","Text"]]: ## segmentation segmented = block.pad(left=15, right=15, top=5, bottom=5).crop_image(img) ## extraction extracted = model.detect(segmented) ## save dic_predicted[str(block.id)+"-"+block.type] = extracted.replace('\n',' ').strip() # check parse_doc(dic_predicted)再看看图形报表
for block in [block for block in detected if block.type == "Figure"]: ## segmentation segmented = block.pad(left=15, right=15, top=5, bottom=5).crop_image(img) ## save dic_predicted[str(block.id)+"-"+block.type] = segmented # check parse_doc(dic_predicted)上面那两个瞅着相当不错, 这是由于这两种类别相对而言较为简单, 然而表格可要复杂许多, 特别是我们方才瞧见的这个, 鉴于它的行与列都是在合并之后才生成的。
for block in [block for block in detected if block.type == "Table"]: ## segmentation segmented = block.pad(left=15, right=15, top=5, bottom=5).crop_image(img) ## extraction extracted = model.detect(segmented) ## save dic_predicted[str(block.id)+"-"+block.type] = pd.read_csv( io.StringIO(extracted) ) # check parse_doc(dic_predicted)犹如我们所料想的那样, 提取出来的表格并非十分理想, 还好存在能够专门处理表格的包, 借助这个包我们能够直接对表格进行处理, 不必把它转换成为图像, 这里运用的便是该包:
import tabula tables = tabula.read_pdf("doc_apple.pdf", pages=i+1) tables[0]后果会较为好些, 然而称谓依旧有误, 只是成效比径直采用OCR要好得多。
总结
此文乃一简易教程, 演示了怎样运用OCR开展文档解析, 借助软件包实施了整个检测与提取进程, 且展示了如何处置PDF文档里的文本、数字以及表格。