文档解析涉及检查文档中的数据并提取有用信息。它可以通过自动化减少大量的手工工作。一种流行的解析策略是将文档转换为图像并使用计算机视觉进行识别。虽然文档图像分析是指从文档图像的像素数据中获取信息的技术,但在某些情况下,对于预期结果应该是什么(文本、图像、图表、数字、表格、公式。..).OCR(OpticalCharacterRecognition,光学字符识别)是通过计算机视觉对图像中的文字进行检测和提取的过程。它是在第一次世界大战期间发明的,当时以色列科学家伊曼纽尔戈德堡创造了一种可以读取字符并将其转换为电报代码的机器。到目前为止,该领域已经达到了非常复杂的水平,混合了图像处理、文本定位、字符分割和字符识别。基本上是一种文本对象检测技术。在本文中,我将展示如何使用OCR进行文档解析。我将展示一些可以在其他类似情况下轻松使用的有用Python代码(只需复制、粘贴、运行),并提供完整的源代码下载。这里我们以PDF格式的上市公司财务报表为例(链接如下)。https://s2.q4cdn.com/470004039/files/doc_financials/2021/q4/_10-K-2021-(As-Filed).pdf检测提取PDF环境设置文档解析顺序中的文字、图形和表格令人恼火的是,针对不同类型的数据(文本、图形、表格)的工具太多了,但没有一个能完美运行。以下是一些最流行的方法和包:将文档作为文本处理:使用PyPDF2提取文本,使用Camelot或TabulaPy提取表格,使用PyMuPDF提取图形。将文档转换为图像(OCR):使用pdf2image进行转换,使用PyTesseract以及许多其他库来提取数据,或者只使用LayoutParser。也许你会问:“为什么不直接处理PDF文件,而是将页面转为图片呢?”你能行的。这种策略的主要缺点是编码问题:文档可以采用多种编码(即UTF-8、ASCII、Unicode),因此转换为文本可能会导致数据丢失。所以为了避免这个问题,我会使用OCR,并用pdf2image将页面转为图片,需要注意的是需要使用PDF渲染库Poppler。#使用pippipinstallpython-poppler#使用condacondainstall-cconda-forgepoppler你可以轻松读取文件:#READASIMAGEimportpdf2imagedoc=pdf2image.convert_from_path("doc_apple.pdf")len(doc)#<--checknumpagesdoc[0]#<--可视化一个页面和我们的截图一模一样,如果你想把页面图片保存到本地,可以使用下面的代码:#Saveimgsimportosfolder="doc"iffoldernotinos.listdir():os.makedirs(folder)p=1forpageindoc:image_name="page_"+str(p)+".jpg"page.save(os.path.join(folder,image_name),"JPEG")p=p+1最后,我们需要设置将要使用的CV引擎。LayoutParser似乎是第一个基于通用深度学习的OCR包。它使用两个著名的模型来完成任务:Detection:Facebook最先进的对象检测库(这里将使用第二个版本的Detectron2)。pipinstalllayoutparsertorchvision&&pipinstall"git+https://github.com/facebookresearch/detectron2.git@v0.5#egg=detectron2"Tesseract:最著名的OCR系统,HP于1985年创建,目前由Developed使用由谷歌。pipinstall"layoutparser[ocr]"现在准备启动OCR程序进行信息检测和提取。importlayoutparseraslpimportcv2importnumpyasnpiportioimportpandasaspdimportmatplotlib.pyplotasplt检测(目标)检测是在图片中查找信息片段并用矩形边框包围它们的过程。对于文档解析,这些信息是标题、文本、图形、表格……让我们看一个复杂的页面,它包含一些东西:这个页面以标题开头,有一个文本块,然后是一个图形和一个表格,所以我们需要一个训练有素的模型来识别这些物体。幸运的是,Detectron能够完成这项任务,我们只需要从这里选择一个模型并在代码中指定它的路径。我将使用的模型只能检测4个对象(文本、标题、列表、表格、图形)。因此,如果您需要识别其他事物(如方程式),则必须使用其他模型。##加载预训练模型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"})##将img转为arrayi=21img=np.asarray(doc[i])##predictedetected=model.detect(img)##plotlp.draw_box(img,detected,box_width=5,box_alpha=0.2,show_element_type=True)结果包含每个检测到的布局的细节,例如边界框的坐标。根据输出在页面上出现的顺序对输出进行排序很有用:##sortnew_detected=detected.sort(key=lambdax:x.coordinates[1])##assignidsdetected=lp.Layout([block.set(id=idx)foridx,blockinenumerate(new_detected)])##checkforblockindetected:print("---",str(block.id)+":",block.type,"---")print(block,end='\n\n')完成OCR的下一步是从检测到的内容中正确提取有用的信息。提取既然我们已经分割了图像,我们需要用另一个模型处理分割后的图像并将提取的输出保存到字典中。由于有不同类型的输出(文本、标题、图形、表格),因此这里准备了一个函数来显示结果。'''{'0-标题':'...','1-文本':'...','2-图':array([[[0,0,0],...]]),'3-Table':pd.DataFrame,}'''defparse_doc(dic):fork,vindic.items():if"Title"ink:print('\x1b[1;31m'+v+'\x1b[0m')elif"Figure"ink:plt.figure(figsize=(10,5))plt.imshow(v)plt.show()else:print(v)print("")首先看文字:#loadmodelmodel=lp.TesseractAgent(languages='eng')dic_predicted={}forblockin[blockforblockindetectedifblock.typein["Title","Text"]]:##分割segmented=block.pad(left=15,right=15,top=5,bottom=5).crop_image(img)##extractionextracted=model.detect(segmented)##savedic_predicted[str(block.id)+"-"+block.type]=extracted.replace('\n','').strip()#checkparse_doc(dic_predicted)再看图形报表forblockin[blockforblockindetectedifblock.type=="Figure"]:##分割segmented=block.pad(left=15,right=15,top=5,bottom=5).crop_image(img)##savedic_predicted[str(block.id)+"-"+block.type]=segmented#checkparse_doc(dic_predicted)上面两个看起来很好,就是因为这两个type比较简单,但是table要复杂的多,尤其是我们上面看到的那个,因为它的行和列都合并了。forblockin[blockforblockindetectedifblock.type=="Table"]:##segmentationsegmented=block.pad(left=15,right=15,top=5,bottom=5).crop_image(img)##提取extracted=model.detect(segmented)##保存dic_predicted[str(block.id)+"-"+block.type]=pd.read_csv(io.StringIO(extracted))#checkparse_doc(dic_predicted)预期的提取形式不是很好。好在Python有专门处理表格的包,我们可以直接处理,不用转成图片。这里使用了TabulaPy包:importtabulatables=tabula.read_pdf("doc_apple.pdf",pages=i+1)tables[0]结果更好了,但是名字还是错了,但是效果比直接好很多文字识别。总结本文是一个简单的教程,演示如何使用OCR进行文档解析。整个检测和提取过程是使用Layoutpars包执行的。并展示了如何处理PDF文档中的文本、数字和表格。
