上期我们使用了IText解析PDF,这期我们需要使用OpenCv来识别PDF中的表格,然后用IText抽取单元格中的文本。

本文适用的条件是“标准的表格”,也就是说,没有隐藏任何表格线的表格,当然,更不能是表格的图片,不然IText根本无法抽取文本。如果希望抽取有隐藏表格线的表格,可以试试PDFLux这款软件。

标准的表格:

不适用的表格:

首先,我们需要使用Apache PDFBox将PDF渲染为png图片,注意的是渲染dpi。IText中抽取出的文字的坐标使用的是72dpi。由于72dpi分辨率过低,可能会导致图片识别不准确,推荐使用144dpi进行渲染,即72的2倍,方便后续的坐标转换。

然后,我们使用OpenCv进行处理,按照惯用套路,我们先将图片转为灰度图,然后二值化,最后反色。反色这个步骤对后续至关重要。

网上你们可以搜到使用腐蚀(erode)和膨胀(dilate)来获取横线和竖线的方法,但是大多没有讲原理,也没有讲参数为什么这么设置,这边简要的说一下。首先,腐蚀和膨胀都需要设置一个m*n的模板,然后使用这个模板从图片左上角开始从左往右从上到下迭代计算,腐蚀是将模板覆盖到的最小像素值替换模板中心相似的值,而膨胀是用最大像素值替换模板中心相似的值。

所以,想要获取“横线”,我们就要使用n*1的模板,因为经过“腐蚀”后,由于横线在n*1的区域内全部为白色(最大像素)而得到保留。n越小,能够被保留的横线就越短,当n小到一定程度时,“一”这种文字中的横线也会被保留。我们希望得到一个阈值,能够过滤掉文字中的横线,但是保留表格中的横线。根据实验,n取页面宽度/20是一个比较不错的阈值。同理,我们需要使用1*m的模板来腐蚀图片获得竖线,由于可能存在2行的表格,所以竖线的阈值肯定比横线要小,经过实验发现,页面高度/50是一个比较不错的阈值。

下面是分别用n*1模板和1*m模板腐蚀后的结果。

细心的同学会发现,“腐蚀”后,横线的宽度比原图横线“短”了。这是因为当这些白色点处于横线边缘时,由于模板会覆盖到左侧或右侧的黑点,从而导致该点被置为黑色。针对这个情况,我们需要对图片使用相同的模板进行“膨胀“操作,抵消掉这个副作用。

下面是使用相同模板膨胀后的情况

然后我们对两张图片使用bitwise_or就可以拼出表格线了

有了表格线以后,我们就可以使用findContours获取轮廓信息。findContours功能很强大,既可以获取最表格的外轮廓,也可以获取单元格的轮廓。

public static void findContours(Mat image, List<MatOfPoint> contours, Mat hierarchy, int mode, int method) 

Mat image 是被识别的图片

List<MatOfPoint> contours 是识别出的轮廓信息

Mat hierarchy 是轮廓的层次信息,是一个n*1*4的高维数组,其中n为contours的长度,第三维的4个元素分别是后一个轮廓、前一个轮廓、父轮廓、包含的轮廓在contours中的编号。我们主要关心的是父轮廓。

int mode 是轮廓的检索模式。CV_RETR_EXTERNAL:只检测最外围轮廓。CV_RETR_LIST:检测所有轮廓,但不建立关系。CV_RETR_CCOMP:检测所有轮廓,只建立2层关系。CV_RETR_TREE:检测所有轮廓,建立树形结构关系

int method 是定义轮廓的近似方法。CV_CHAIN_APPROX_NONE:保存轮廓所有点。CV_CHAIN_APPROX_SIMPLE:仅保留轮廓拐点,不保留直线点。

因为我们只需要获取表格外围和单元格轮廓,我们只需要使用mode=CV_RETR_CCOMP,method=CV_CHAIN_APPROX_SIMPLE

获取到轮廓以后,对于每个轮廓,我们使用approxPolyDP和boundingRect获取到轮廓外包矩形。同时,我们过滤掉那些明显不是表格或单元格的轮廓,例如,面积比一个字符都小(10*10),轮廓使用approxPolyDP后,只剩下4个点以下(很有可能就是条横线或者三角形)

然后我们根据hierarchy组织成(表格外轮廓,List 单元格轮廓)的形式。我们虽然知道了这些单元格属于表格,但是我们还需要单元格的排列信息,以及合并单元格的信息。

对于单元格的排列,我们可以先对y坐标排顺序(因为表格横线获取的单元格y坐标都是对齐的),然后对x坐标排顺序。

那么合并单元格的情况怎么办呢?通过观察,我们发现,没有合并的单元格,不会被表格线的延长线“穿过”,被n根横向/纵向的表格线的延长线“穿过”,那么就横向、纵向合并了n+1个单元格。

这样,我们就解决了从PDF识别表格的问题。只需要最后一步,使用IText获取对应坐标范围的文字填充到表格中。

由于IText使用的是72dpi进行渲染的文字的坐标,以及y轴的原点在页面底部,我们需要对OpenCv获取到的坐标进行转换。

x_itext=x_open_cv/2;

y_itext=(height_open_cv-y_open_cv)/2

参考资料:

https://blog.csdn.net/yomo127/article/details/52045146

https://www.cnblogs.com/ssyfj/p/9276999.html

https://blog.csdn.net/qq_42887760/article/details/85928182

https://www.jianshu.com/p/884261b5ab5a

https://blog.csdn.net/laobai1015/article/details/76400725

IText+OpenCv抽取PDF表格相关推荐

  1. JAVA使用itext来生成PDF表格实例和使用说明

    在对接某第三方XX平台时需要对表格传入PDF文件类型.于是自造了一个. Maven使用版本如下: <dependency><groupId>com.itextpdf</g ...

  2. itextpdf添加表格元素_java使用iText生成pdf表格详解

    首先需要你自己下载itext相关的jar包并添加引用,或者在maven中添加如下引用配置: com.lowagie iText 2.1.5 com.lowagie iText-rtf 2.1.4 co ...

  3. 绘制pdf表格 (二) 通过itext实现在pdf中绘制excel表格样式设置中文字体、水印、logo、页眉、页码

    前言 在<通过itext实现在pdf中绘制excel表格样式并且实现下载>实现了表格的基本渲染,本文将继续进行水印.logo.页眉.页码的设置,本文的部分代码包含<通过itext实现 ...

  4. java itext 里表格_Java使用itext5实现PDF表格文档导出

    最近拿到一个需求,需要导出PDF文档,市面上可以实现的方法有很多,经过测试和调研决定使用itext5来实现,话不多说,说干就干. 1.依赖导入 com.itextpdf itextpdf 5.5.13 ...

  5. [Python工具]pdf表格提取camelot安装教程

    pdf表格提取camelot安装教程 经过测试,macos 与win10 均可以用一下方式安装 Camelot: 一个友好的PDF表格数据抽取工具 一个python命令行工具,使任何人都能很轻松的从P ...

  6. Python新工具:用三行代码提取PDF表格数据

    点击上方"视学算法",星标公众号 重磅干货,第一时间送达 项目作者:vinayak mehta 参与:一鸣 从 PDF 表格中获取数据是一项痛苦的工作.不久前,一位开发者提供了一个 ...

  7. 使用iText库创建PDF文件

    前言 译文连接:http://howtodoinjava.com/apache-commons/create-pdf-files-in-java-itext-tutorial/ 对于excel文件的读 ...

  8. web怎么用代码创造表格_Python新工具:用三行代码提取PDF表格数据

    机器之心报道 项目作者:vinayak mehta参与:一鸣 从 PDF 表格中获取数据是一项痛苦的工作.不久前,一位开发者提供了一个名为 Camelot 的工具,使用三行代码就能从 PDF 文件中提 ...

  9. python读取pdf表格数据代码_Python新工具:用三行代码提取PDF表格数据

    原标题:Python新工具:用三行代码提取PDF表格数据 机器之心报道 项目作者:vinayak mehta,参与:一鸣 从 PDF 表格中获取数据是一项痛苦的工作.不久前,一位开发者提供了一个名为 ...

最新文章

  1. 统计决策理论1 统计问题与统计决策
  2. Scala类中的+方法
  3. python可迭代对象 迭代器生成器_Python可迭代对象、迭代器和生成器
  4. hdu 1800 (map)
  5. 你知道技术委员会吗?嗯,一个既重要却又鸡肋的神秘组织
  6. delphi image 编辑器_照片拼图编辑器app下载-照片拼图编辑器下载 v1.0.0 安卓版
  7. 服务器关于数据流转方式
  8. python中np.reshape与matlab中reshape区别,以及多axis的np.mean分析[探索6]
  9. django允许跨域请求配置
  10. Vue安装 devTool 时报错的解决办法
  11. 地籍图 cad cass 二次开发 过滤器过滤扩展数据组码1000的解决方案
  12. NLPIR/ICTCLAS 2015 分词系统使用
  13. 分享:映像编辑工具Ghostexp
  14. php5.6.40 在 win10下安装全过程 ( 图文教程、附官方下载链接 )
  15. ORACLE SPA and RAT
  16. ts封装,H264和aac 封装成为ts,并生成m3u8
  17. 如何用python实现爬虫_如何用python实现网络爬虫原理?
  18. UI设计书籍推荐,这三本好书你不能错过
  19. 基础计算机教学论文,基础计算机论文,关于民办院校计算机基础课程实践教学体会相关参考文献资料-免费论文范文...
  20. 用EXCEL做九九乘法表

热门文章

  1. html css投影效果,CSS添加阴影效果
  2. php打开wave文件,什么是WAV和WAVE文件(以及如何打开它们)? | MOS86
  3. 数据库enum怎么对应java_java – 如何持久化EnumSet(使用两个数据库表)?
  4. 查看mysql更新日志_mysql 的日志查看
  5. python怎么打印列表长度_打印知道长度和宽度的钻石(Python)
  6. 用计算机打出98k的歌,抖音绝地求生98K之歌叫什么名字 98K之歌歌词分享
  7. 通信电子电路锁相鉴频器课设(Multisim Proteus)
  8. 我的实践:通过蚂蚁、蜜蜂二分类问题了解如何基于Pytorch构建分类模型
  9. 【VC++ MFC】vc 画笔和画刷|OnDraw()和OnPaint()
  10. 华为WATCH 3和GT3运动手表该如何选?哪个更适合自己