16.2.PDF
Windows 10
Python 3.7.7 @ MSC v.1916 64 bit (AMD64)
Latest build date 2020.09.17
pdfminer version: 20191125
PDF 文档虽然经常被用到,但是 PDF 可以说是邪恶的,因为 PDF 格式十分复杂,想通过编程的方式精确地提取PDF文档中的信息相当困难。用于提取PDF文档信息的Python库有很多,但是大部分的库现在都不怎么更新了,常用的库有PyPDF2
、pdfminer
、pdfminer3k
等。pdfminer
的最新版本更新时间在2019年。
pyPdf
包早在2005年就发布了,应该是最早(较早)用于解析PDF的Python库, 但是pyPdf
在2010年就停止更新,且不支持Python3。 在pyPDF
停止更新后的一年左右,由Phasit公司在pyPdf
的基础上开发了PyPDF2
, 该代码被设计为与pyPdf
兼容,最后一个版本发布于2016年。 然后在2018年出现了名为PyPDF3
的库, 在更新了几个版本之后,PyPDF3
项目被重命名为PyPDF4
。 这些项目几乎都做着相同的事情,但是PyPDF2+
的项目添加了Python3的支持。还有一个从原始的
pyPdf
项目fork出来的pyPdf
for Python 3项目,但已夭折多年。
pdfminer
pdfminer
是一个可以从PDF文档中提取信息的工具。与其他PDF相关的工具不同,它注重的是获取和分析文本数据,所以pdfminer
提取PDF的表格和图片的效果都不太好。
pdfminer
允许你获取某一页中文本的准确位置和一些诸如字体、行数的信息。它包括一个PDF转换器,可以把PDF文件转换成HTML等格式,只是转换后的格式没眼看。它还有一个扩展的PDF解析器,可以用于除文本分析以外的其他用途。
由于PDF文件具有庞大和复杂的结构,完整解析 PDF 文件很费时间,pdfminer
采用了一个懒惰分析的策略,即显式指定分析内容时才进行分析,即根据需要只解析出所需的内容。
下面这个图表示了 pdfminer
各模块之间的关系:
模块名 | 说明 |
---|---|
PDFParser |
从文件中获取数据 |
PDFDocument |
存储文档数据结构到内存中 |
PDFPageInterpreter |
解析page内容 |
PDFDevice |
把解析到的内容转化为你需要的东西 |
PDFResourceManager |
存储共享资源,例如字体或图片等 |
在代码中使用
下面这段代码给出了pdfminer
解析 PDF 文档的基本方法。首先打开 PDF 文件,创建解析对象,存储文档结构,创建资源管理对象以及共享资源,然后再创建 device 对象,最后再创建文档解析对象,并处理文档中的每一页。
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfdevice import PDFDevice, PDFTextDevice
from pdfminer.pdfpage import PDFPage, PDFTextExtractionNotAllowed
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfinterp import PDFPageInterpreter
pdf_path = "datasets/file/毕业设计-页面-14.pdf"
with open(pdf_path, "rb") as f:
# Create a PDF parser object associated with the file object.
parser = PDFParser(f)
# Create a PDF document object associated with the parser object.
document = PDFDocument(parser=parser, password="")
# Check if the PDF is text-based
# pdfminer is not working for scanned PDF
if not document.is_extractable:
raise PDFTextExtractionNotAllowed
# Create a PDF resource manager object that stores shared resources.
pdf_manager = PDFResourceManager()
# Create a PDF device object.
device = PDFDevice(pdf_manager)
# device = PDFTextDevice(pdf_manager)
# Create a PDF interpreter object.
interpreter = PDFPageInterpreter(pdf_manager, device)
# Process each page contained in the document.
for page in PDFPage.create_pages(document):
interpreter.process_page(page)
这是官方文档给出的示例代码,不过说实话,我不是很明白这段代码在干嘛,因为上面的代码好像没办法拿到PDFPageInterpreter
解析得到的结果。可能这段示例代码仅仅是展示pdfminer
处理PDF的流程。
下面是获取页面解析结果的示例代码:
可以看到,我们需要调用PDFDevice
对象的get_result
方法去获取解析后得到的对象。第一段示例代码的 PDFDevice
对象应该只是一个接口类(只是声明接口,没有具体实现),是没有get_result
方法的,所以第一段示例代码没办法取得解析结果。PDFPageAggregator
是PDFDevice
的子类,具有get_result
方法。
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage, PDFTextExtractionNotAllowed
from pdfminer.converter import PDFPageAggregator
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.layout import LAParams, LTTextBox, LTTextLine
pdf_path = "datasets/file/毕业设计-页面-14.pdf"
with open(pdf_path, "rb") as f:
# Create a PDF parser object associated with the file object.
parser = PDFParser(f)
# Create a PDF document object associated with the parser object.
document = PDFDocument(parser=parser, password="")
if not document.is_extractable:
raise PDFTextExtractionNotAllowed
# Create a PDF resource manager object that stores shared resources.
pdf_manager = PDFResourceManager()
# Create a PDF device object.
laparams = LAParams()
device = PDFPageAggregator(pdf_manager, laparams=laparams)
# Create a PDF interpreter object.
interpreter = PDFPageInterpreter(pdf_manager, device)
# Process each page contained in the document.
for page in PDFPage.create_pages(document):
interpreter.process_page(page)
# receive the LTPage object for the page.
layout = device.get_result()
for num, element in enumerate(layout):
if isinstance(element, LTTextBox) or isinstance(element, LTTextLine):
print(element.get_text())
哈尔滨工业大学(深圳)本科毕业设计(论文)
锚框的模型 CornerNet。CornerNet 使用一个卷积网络生成两组特征图,一个负责
预测左上角,另一组负责预测右下角,以两个关键点生成候选框。CornerNet 还引
入了一种新型的 corner pooling 帮助网络更好地定位边界框的角点。单阶段模型结
构如图 1-8 所示:
图 1-8 单阶段检测模型[14]
1.2.2 小目标检测的研究现状
目前学界还没有给小目标一个具体的定义,因为小和大是一个相对概念。同一
个物体在相机的远处和近处拍摄呈现的大小结果是不同的。图片中的小目标可能
是物体自身的物理尺寸过小或者是拍摄距离较远导致的。虽然小目标的判定没有
一个统一的标准,但是在特定的数据集内,小目标可以人为地给出准确定义。比
如 MS COCO 数据集内规定尺寸在 32 32 之内的目标可以认为是小目标。如表 1-1
所示:
表 1-1 COCO 数据集对目标尺度的定义
小尺度目标
中尺度目标
大尺度目标
最小面积
0 0
32 32
96 96
最大面积
32 32
96 96
为了提高小目标检测的精度,各路学者提出了许多行之有效的方案。
Lin 等[17]从损失函数方面出发,提出了 RetinaNet。RetinaNet 主要解决了单阶
段模型正负样本不平衡的问题。通常情况下,一张图仅有几个目标,而产生的候
选框却是成千上百,负样本对总体损失函数的影响远远大于正样本。如此一来,
模型便会过分关注负样本,也更容易发生对正样本的漏检现象。RetinaNet 使用的
Focal Loss 提高了对少量样本的关注,很好地解决了正负样本不平衡的问题。
- 8 -
一个布局分析器(layout analyzer)为PDF的每一页返回一个LTPage
对象。这个LTPage
对象包含位于页面内的子对象,形成一个树形结构。
下图展示了这些对象之间的关系:
如果我们想获得PDF之中的文字,那么就需要迭代LTPage
对象包含的子对象,判断子对象是否为LTTextBox
或LTTextLine
对象,如果是的话,则调用子对象的get_text()
方法获取文字。
下面的表格是各对象的具体说明:
对象名 | 对象说明 | 备注 |
---|---|---|
LTPage |
代表一个完整的页面,可以包含子对象 | 例如:LTTextBox , LTFigure , LTImage , LTRect , LTCurve 和LTLine |
LTTextBox |
它包含 LTTextLine 对象的列表,代表一组被包含在矩形区域中的文本 |
注意:该box是根据几何学分析得到的,并不一定准确地表现为该文本的逻辑范围,get_text()方法可以返回文本内容 |
LTTextLine |
包含一个LTChar 对象的列表,表现为单行文本 |
字符表现为一行或一列,取决于文本书写方式,get_text()方法返回文本内容 |
LTChar |
表示一个在文本中的真实的字母,作为一个unicode字符串 | LTChar 对象有真实的分隔符 |
LTAnno |
表示一个在文本中的真实的字母,作为一个unicode字符串 | LTAnno 对象没有,是虚拟分隔符,按照两个字符之间的关系,布局分析器插入虚拟分隔符 |
LTFigure |
表示一个被 PDF Form 对象使用的区域 | pdf form适用于目前的图表(present figures)或者页面中植入的另一个pdf文档图片,LTFigure 对象可以递归 |
LTImage |
表示一个图形对象,可以是JPEG或者其他格式 | |
LTLine |
表示一根直线 | 用来分割文本或图表(figures) |
LTRect |
表示一个矩形 | 用来框住别的图片或者图表 |
LTCurve |
代表一个贝塞尔曲线 |
命令行工具
除了以import
的方式使用,pdfminer
还提供了两个命令行工具:pdf2txt.py
和dumppdf.py
:
- pdf2txt.py: 从PDF文件中提取所有文本内容。但不能识别画成图片的文本。对于加密的PDF需要提供密码才能解析,对于没有提取权限的PDF文档则无法提取文本。
- dumppdf.py: 把PDF文件内容变成准XML格式。这个程序主要用于debug,但是它也可能用于提取一些有意义的内容(比如图片)。
使用类似这样的命令调用就可以了: pdf2txt.py [options] files
。
下面是pdf2txt.py
的参数说明。
实际使用的可选参数取决于用户使用的版本,和官网上的参数可能有出入。
-o
value :指定输出文件名,否则标准输出。没有-t
选项指定类型时根据后缀名判定类型。-t
value :指定输出类型:text (默认)、html、xml、tag。不指定会根据文件名后缀判定。-p
value :指定输出某些页,例如1,2,3
输出1到3页 (分隔符,
无空格!).默认全部页输出。内部会转成一个set类型对象。-m
value :指定提取最多m页。默认提取所有。-O
value :给ImageWriter的参数,输出图片到相应文件夹,默认不输出图片。-C
:压制使用缓存,会减少内存消耗但减慢分析过程。这个缓存会在多文件时使用之前的一些信息(例如格式、文字大小等)作为本文件处理,可能会出问题,建议压制缓存。-P
value :指定操作pdf需要的密码-c
value :codec,就是使用的编码(默认utf-8
)。-d
:增加debug级数。
以下参数和layout分析相关 (实际使用LAParams
对象进行储存参数并传递给主要的函数)
-n
:取消layout分析。-A
:强制进行所有文本字符串的layout分析,包括图片内的。-V
:允许垂直书写的的检测。-M
value :char_margin,控制作为一个text chunks的最大字符间距. 小于该距离为归为一组。实际距离值取决于字符大小。-L
value :line_margin,控制作为一个text box的最大行距. 小于该距离为归为一个box。-W
value :word_margin,控制两个词之间是否插入空格的最小间距。-F
value :boxes_flow,控制box order?值应该是-1 (只考虑水平) 到1 (只考虑垂直)之间,默认0.5。-Y
value :输出到HTML时的layout的模式,默认normal(保持相应位置和换行),还可以exact (准确保持每个字符位置,HTML变大且混乱)和loose (保持text block位置)。-s
value :控制输出的缩放比例,只能用于HTML格式。-R
value :控制旋转度数(360制)。
- 不同版本的
M, L, W
参数的默认值可能不同。- 同时处理多个文件时,不使用
-C
参数可能会出现一些问题。