Java实现PDF文字内容识别,结合OCR实现PDF图片实现

使用插件:UMI-OCR、PDFBOX

实现思路:通过PDFBOX识别PDF文字,如果是图片,则识别不出来,再调用OCR进行识别返回文字;OCR识别较慢,长图识别不出来,目前HTTP方式只支持图片格式,还需使用PDFBOX要将每一页PDF转换为图片再进行识别拼接。

UMI-OCR下载地址:https://github.com/hiroi-sora/Umi-OCR/releases/latest

git仓库地址:GitHub - hiroi-sora/Umi-OCR: OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。内置多国语言库。

下载后直接在WIN系统安装(目前只支持WIN系统),安装包内含PaddleOCR-json,无需再进行下载;安装启动,设置HTTP请求参数

全局设置 --> 高级 --> 允许HTTP服务:

主机设置为:任何可用地址

端口:自己设置

PDFBOX MAVEN版本配置:

 <!-- PDF文档处理 -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.8</version>
        </dependency>

代码实现文字识别:

String text = "";
        try {
            PDDocument pdDocument = PDDocument.load(image.getInputStream());
            PDFTextStripper pdfTextStripper = new PDFTextStripper();
            //读取pdf中所有的文件
            //前端HTML不识别><,需要进行更换
            text = pdfTextStripper.getText(pdDocument);
            text = text.replace(" ", "")
                    .replace("\r", "")
                    .replace("\t", "")
                    .replace("\n", "");
            if (StrUtil.isNotEmpty(text)){
                text = text.replace("<","&lt;").replace(">","&gt;");
            }else{
                /**
                 * 如果没有识别到文字,
                 * 则转成图片
                 * 进行OCR识别获取文本
                 */
                text = uploadPDF2OcrGetText(accessUrl, image);
            }
        }catch (IOException e){
            log.error(e.getMessage());
        }

如果文档里面含有"<"">",前端HTML不识别,则需要进行转换

uploadPDF2OcrGetText:
    /**
     * 上传图片文件至OCR
     * @param accessUrl 访问地址
     * @param image 图片文件
     * @return
     */
    public static String uploadPDF2OcrGetText(String accessUrl, MultipartFile image) {
        List<ByteArrayOutputStream> list = getStreamList(image);
        StringBuilder sb = new StringBuilder();
        if (list != null && !list.isEmpty()){
            for (ByteArrayOutputStream outputStream : list) {
                String str = getData(accessUrl, outputStream);
                if (StrUtil.isNotEmpty(str)){
                    sb.append(str);
                }
            }
        }
        return sb.toString();
    }

将PDF转为图片流方法getStreamList:

    /**
     * PDFBOX将PDF转成png流
     * @param file 图片文件
     * @return List
     */
    public static List<ByteArrayOutputStream> getStreamList(MultipartFile file) {
        List<ByteArrayOutputStream> list = new ArrayList<>();
        try{
            PDDocument pdf = PDDocument.load(file.getInputStream());
            PDFRenderer renderer = new PDFRenderer(pdf);
            int pageCount = pdf.getNumberOfPages();
            for (int i = 0; i < pageCount; i++){
                BufferedImage image = renderer.renderImageWithDPI(i, 120);//120为DPI根据自己设置
                ByteArrayOutputStream bas = new ByteArrayOutputStream();
                ImageIO.write(image, "png", bas);
                list.add(bas);
            }
        }catch (IOException e){
            log.error(e.getMessage());
        }
        return list;
    }

调用OCR识别文字方法getData:

 /**
     * 上传图片文件至OCR
     * @param accessUrl 访问地址
     * @param outputStream 图片流
     * @return
     */
    public static String getData(String accessUrl, ByteArrayOutputStream outputStream){
        //转换为Base64
        String base64Image = new String(Base64.encodeBase64(outputStream.toByteArray()));
        //如果文件属于图片则进行文件转换
        JSONObject jb = new JSONObject();
        jb.set("base64", base64Image);
        JSONObject jb1 = new JSONObject();
        jb1.set("tbpu.parser", "multi_para");
        jb1.set("data.format", "text");
        jb.set("options", jb1);
        String result2 = HttpRequest.post(accessUrl)
                .body(jb.toString())//表单内容
                .timeout(300000)//数据可能较大,超时时间调的较长
                .execute().body();
        JSONObject jsonObject = JSONUtil.parseObj(result2);
        String text = null;
        if ("100".equals(jsonObject.getStr("code"))){
            text = jsonObject.getStr("data");
        }
        return text;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/457935.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年【流动式起重机司机】考试题及流动式起重机司机模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 流动式起重机司机考试题参考答案及流动式起重机司机考试试题解析是安全生产模拟考试一点通题库老师及流动式起重机司机操作证已考过的学员汇总&#xff0c;相对有效帮助流动式起重机司机模拟考试题学员顺利通过考试。…

008:安装Docker

安装Docker 如果不太熟悉Linux命令&#xff0c;不想学习Linux命令&#xff0c;可以直接看文末NAS面板章节&#xff0c;通过面板&#xff0c;像使用Window一样操作NAS。 一、安装 Docker 1.安装 Docker wget -qO- https://get.docker.com/ | sh2.启动 Docker 服务 sudo sys…

Ubuntu系统的安装及基础操作

目录 一、VMware虚拟机安装Ubuntu20.04过程 1、安装前的准备工作 2、VMware虚拟机创建Ubuntu操作系统 步骤一&#xff1a;以管理员的身份运行VMware虚拟机 步骤二&#xff1a;新建虚拟机 步骤三&#xff1a;选择类型配置 步骤四&#xff1a;选择安装客户机操作系统 步骤…

100W-150W电阻器-TO-247模压厚膜电阻(1)

EAK封装的TO-247功率电阻器为设计工程师提供稳定的晶体管式封装的大功率电阻器件&#xff0c;功率为100W-150W。这些电阻器专为需要精度和稳定性的应用而设计。该电阻器采用氧化铝陶瓷层设计&#xff0c;可将电阻元件和安装片分开。 EAK模压TO-247厚膜功率电阻器 这种结构提供了…

蓝桥杯刷题|02入门真题

[蓝桥杯 2022 省 B] 刷题统计 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a 道题目&#xff0c;周六和周日每天做 b 道题目。请你帮小明计算&#xff0c;按照计划他将在第几天实现做题数大于等于 n 题? 输入格式 输入一行包含三个整数…

react04- mvc 、 mvvm

MVC与MVVM stackoverflow论坛网站 react前端框架 使用框架前&#xff1a; 操作dom > js获取dom元素&#xff0c;事件侦听&#xff0c;修改数据&#xff0c;设置样式。。。 操作dom问题: 直接操作dom&#xff0c;会造成大量的回流、重绘&#xff0c;消耗大量性能操作起来也…

物联网终端telegraf采集设备信息

背景 低功耗设备上资源有限&#xff0c;但又比较重要。对其的管理难度很大&#xff0c;有些时候又必须时刻了解其运行状况。我们自然想到的是能否有办法监控它呢&#xff1f;当时是有的&#xff01;而且很成熟的解决方案。TICK技术栈&#xff0c;那TICK是什么呢&#xff1f; TI…

云仓酒庄2024年培训专业化:强化销售与品酒技能,酒业新动态

云仓酒庄2024年培训专业化&#xff1a;强化销售与品酒技能&#xff0c;共筑酒业新动态 在风云变幻的市场竞争中&#xff0c;云仓酒庄始终秉持着创新、进取的理念&#xff0c;不断探索与实践&#xff0c;以推动酒业行业的持续健康发展。2024年&#xff0c;云仓酒庄在培训专业化…

SpringBoot(自定义转换器+处理Json+内容协商)

文章目录 1.自定义转换器1.代码实例1.save.html2.编写两个bean1.Car.java2.Monster.java 3.WebConfig.java 配置类来自定义转换器4.测试 2.注意事项和细节1.debug查看转换器总数1.打断点2.执行到断点后&#xff0c;选左边的1923.可以看出&#xff0c;加上自定义的转换器一共125…

Day63:WEB攻防-JS应用算法逆向三重断点调试调用堆栈BP插件发包安全结合

目录 前置知识 JS调试分析 JS分析调试结合Burp JS分析调试知识点&#xff1a; 1、JavaScript-作用域&调用堆栈 2、JavaScript-断点调试&全局搜索 3、JavaScript-Burp算法模块使用 前置知识 JS加密数据走向 浏览器调试 1、作用域&#xff1a;&#xff08;本地&全…

论文阅读——RingMo

RingMo: A Remote Sensing Foundation Model With Masked Image Modeling 与自然场景相比&#xff0c;RS图像存在以下困难。 1&#xff09;分辨率和方位范围大&#xff1a;受遥感传感器的影响&#xff0c;图像具有多种空间分辨率。此外&#xff0c;与自然图像的实例通常由于重…

《1w实盘and大盘基金预测 day3》

上贴指数预测拉满&#xff0c;上证最低位置和最高位置预测的八九不离十&#xff0c;个人预测最高3062实际3060&#xff0c;最低3017实际3020 昨天的预测 3017-3031-3062 低开反抽&#xff0c;回落下杀 明天看是否能阳包阴&#xff0c;得看蓝筹、证券发力。&#xff08;AI板块…

对OceanBase进行 sysbench 压测前,如何用 obdiag巡检

有一些用户想对 OceanBase 进行 sysbench 压测&#xff0c;并向我询问是否需要对数据库的各种参数进行调整。我想起有一个工具 obdiag &#xff0c;具备对集群进行巡检的功能。因此&#xff0c;我正好借此机会试用一下这个工具。 obdiag 功能的比较丰富&#xff0c;详细情况可参…

【机器学习300问】37、什么是迁移学习?

一、什么是迁移学习&#xff1f; &#xff08;1&#xff09;它的出现是为了解决什么问题&#xff1f; 迁移学习是为了解决深度学习中由于数据不足导致的学习效果受限以及跨领域知识的有效利用等问题而发展起来的一种重要技术手段。 ① 缺少训练数据 在许多实际应用中&#xf…

手动创建线程池各个参数的意义?

今天我们学习线程池各个参数的含义&#xff0c;并重点掌握线程池中线程是在什么时机被创建和销毁的。 线程池的参数 首先&#xff0c;我们来看下线程池中各个参数的含义&#xff0c;如表所示线程池主要有 6 个参数&#xff0c;其中第 3 个参数由 keepAliveTime 时间单位组成。…

DM数据库安装(Linux)

Linux安装 操作系统CPU数据库CentOS7x86_64 架构dm8_20230418_x86_rh6_64 先把压缩包扔过去 新建 dmdba 用户 创建用户所在的组&#xff0c;命令如下&#xff1a; groupadd dinstall 创建用户&#xff0c;命令如下&#xff1a; useradd -g dinstall -m -d /home/dmdba -s /…

MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的通信协议&#xff0c;在物联网和消息传递系统中广泛应用。MQTT 提供了三个不同的 QoS&#xff08;Quality of Service&#xff09;等级&#xff0c;用于确保消息的可靠性和传输效率。本文将详细…

java数据结构与算法刷题-----LeetCode47. 全排列 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 暴力回溯2. 分区法回溯 此题为46题的衍生题&#xff0c;在46题…

Android14之报错:error:add its name to the whitelist(一百九十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Vscode 修改C++版本

1. 首先要检查GCC版本&#xff0c;有的gcc版本过低会导致C版本升级不成功 可以用cmd&#xff0c;用gcc --version命令查看gcc版本 我这里就是gcc版本较低&#xff0c;不支持c17 需要先升级gcc版本 gcc与c对应的版本&#xff0c;大家可以在这位大佬的博客中看&#xff0c;写…