关于Python使用pdfminer库对PDF文件三线表中直线的识别,并返回相应的Y轴坐标
- 依赖库
- 测试文件
- 实现目标
- 识别原理介绍
- 1. 全部解析
- 2. 直线对象获取
- 3. 直线过滤
- 测试直线
- 具体代码
- LTRect对象介绍
- 可能存在的问题
- 最终效果
参考文章:
pdfminer官方文档 pdfminer源码
依赖库
pdfminer
测试文件
pdf文件一整页(含有5张三线表, 15条直线)
实现目标
获取所有直线对象,并获得其相应的Y轴坐标(5张表,共15条直线)
识别原理介绍
1. 全部解析
利用pdfminer库能获取单页PDF页面中的所有对象:包括
- LTPage代表一个完整的页面。
- LTTextBox它包含 LTTextLine 对象的列表。
- LTTextLine包含一个LTChar对象的列表,表现为单行文本字符表现为一行或一列。
- LTChar / LTAnno LTChar对象有真实的分隔符。
- LTAnno 对象是虚拟分隔符,按照两个字符之间的关系,布局分析器插入虚拟分隔符。
- LTFigure代表一个被PDF Form对象使用的区域。
- LTImage代表一个图形对象。
- LTLine代表一根直线。
- LTRect代表一个矩形。
- LTCurve代表一个贝塞尔曲线。
2. 直线对象获取
失败方案:先前在测试时首先想到 对获取到每个内存中的对象筛选出LTLine即可获得内存对象。
失败原因:某些直线并不会被识别成LTLine,就算获得的坐标也并不符合PDF原输入文件的相应位置。
可行方案:对识别出的所有对象,筛选出 LTRect矩形对象 。
原因分析:直线可以被pdfminer识别成LTRect矩形对象,可以将直线看做高度非常小的一种特殊矩形(实际测试数据三线表直线对象高度大约为0.6~0.8左右,可以认为<2)。
3. 直线过滤
利用 直线可以被看做高度小于2的矩形 的特点 设置过滤条件
测试直线
针对测试用的PDF文件,其中三线表的直线的高度大约为0.6~0.8。 不同高度的直线 可以适度调节 过滤时 LTRect对象的 height 的取值。
具体代码
(1) pdfminer相关初始化操作
fp = open(path, 'rb')
# 创建pdf文档对象,并获取所有页面pages
parser = PDFParser(fp)
document = PDFDocument(parser)
pages = PDFPage.create_pages(document)
# 断言文档对象可提取
assert document.is_extractable
# 设置参数并获得pdf解释器
rsrcmgr = PDFResourceManager()
laparams = LAParams()
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
interpreter = PDFPageInterpreter(rsrcmgr, device)
(2) 获取 *** 单页 *** 所有pdfminer扫描得到的内存对象的集合:layout布局对象
for eachPage in pages:
interpreter.process_page(eachPage)
layout = device.get_result()
(3) 对 *** 单页 *** 获得的 layout布局对象 中筛选 LTRect对象 并过滤 LTRect对象 , 同时记录Y轴坐标
coordinateY = []
for each in layout:
# 利用LTRect对象来检测直线
if type(each) == LTRect:
# 将高度 > 2的矩形过滤,(测试数据可推测直线会被扫描成高度接近1的矩形)
if each.height > 2:
continue
# 解决同一直线被分段扫描检测为多段直线的问题(同一个Y坐标,但是宽度不一致,其总和为原始直线)
if each.bbox[1]not in coordinateY:
coordinateY.append(each.bbox[1])
LTRect对象介绍
其某层父类为:LTComponent
其拥有一个bbox绑定盒子对象,其记录了该LTComponent对象的左下角和右上角坐标 (x0, y0, x1, y1)
源码中的体现:
可能存在的问题
在获取所有LTRect对象时,可能会出现如下情况:
原本pdf中三线表的一条直线,可能被分为三段子直线,其Y轴坐标一致,但是每条直线的width(即每条直线的宽度或称之为长度)不一致,但是 三段子直线的总长度和 = 原直线长度
即(x轴方向的总长度): Line = subLine[0] + subLine[1] + subLine[2]
最终效果
获取的该页5张表 共15条直线 不同的Y轴坐标: