java通过ocr实现识别pdf中的文字

news2025/1/12 21:52:31

需求:识别pdf文件中的中文

根据github项目mymonstercat 改造,先将pdf文件转为png文件存于临时文件夹,然后通过RapidOcr转为文字,最后删除临时文件夹

1、引入依赖

		
            <dependency>
                <groupId>org.apache.pdfbox</groupId>
                <artifactId>fontbox</artifactId>
                <version>3.0.3</version>
            </dependency>
            <dependency>
                <groupId>org.apache.pdfbox</groupId>
                <artifactId>pdfbox</artifactId>
                <version>3.0.3</version>
            </dependency>

            <!-- ocr图片识别 -->
            <dependency>
                <groupId>io.github.mymonstercat</groupId>
                <artifactId>rapidocr</artifactId>
                <version>0.0.7</version>
            </dependency>

            <dependency>
                <groupId>io.github.mymonstercat</groupId>
                <artifactId>rapidocr-onnx-platform</artifactId>
                <version>0.0.7</version>
            </dependency>
            
            <!-- 本地测试可不引 , 服务器部署linux x86架构 下引入 ,其他环境部署可搜maven -->
			<dependency>
                <groupId>io.github.mymonstercat</groupId>
                <artifactId>rapidocr-onnx-linux-x86_64</artifactId>
                <version>1.2.2</version>
            </dependency>

2、工具类



import org.springframework.util.StringUtils;
import com.benjaminwan.ocrlibrary.OcrResult;
import com.benjaminwan.ocrlibrary.TextBlock;


import io.github.mymonstercat.Model;
import io.github.mymonstercat.ocr.InferenceEngine;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
@Service
public class PdfOCRConverter {

	//临时输出png文件路径
    private static final String outputDirs = "D:/pdfToImg/temp/";

    public static void main(String[] args) throws IOException {
        List<String> fileNameList = getWords("D:/Download/123.pdf");
        for (String fileName : fileNameList) {
            System.out.println(fileName);
        }
    }


    public static List<String> getWords(String pdfFilePath) throws IOException {
        String outputDir =  outputDirs + UUID.randomUUID().toString().replace("-", "");

        List<String> fileNameList = convertPdfToImage(pdfFilePath, outputDir);

        List<String> wordsList = new ArrayList<>();
        for (String fileName : fileNameList) {
            System.out.println("识别图片:"+fileName);
            if (StringUtils.isEmpty(fileName)){break;}
            List<String> words = runOcr(fileName);
            for (String word : words) {
                System.out.println(word);
                wordsList.add(word);
            }
        }
        deleteDirectory(outputDir);
        return wordsList;
    }


    public static List<String> runOcr(String path) {
        List<String> results = new ArrayList<>();
        InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V3);
        OcrResult ocrResult = engine.runOcr(path);
        for (TextBlock textBlock : ocrResult.getTextBlocks()) {
            results.add(textBlock.getText());
        }
        return results;
    }


    public static List<String> convertPdfToImage(String pdfFilePath, String outputDir) {

        // 设置DPI(越高图片越清晰,但文件也会更大)
        int dpi = 300;
        List<String> fileNameList = new ArrayList<>();
        File file = new File(pdfFilePath);
        try (PDDocument document = Loader.loadPDF(file)) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            String pdfFileName = file.getName().replace(".pdf", "");
            String name = pdfFileName;
            for (int page = 0; page < document.getNumberOfPages(); page++) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(page, dpi);
                String folder = createFolder(outputDir + "/" + name);
                String fileName = folder + "/" + pdfFileName + "_page_" + (page + 1) + ".png";
                ImageIO.write(bim, "png", new File(fileName));
                fileNameList.add(fileName);
                System.out.println("生成图片:"+fileName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileNameList;
    }


    public static void deleteDirectory(String path) throws IOException {
        // 如果路径不指向一个目录,则抛出异常
        Path directory = Paths.get(path);
        if (!Files.isDirectory(directory)) {
            throw new IOException("The provided path is not a directory.");
        }

        // 遍历目录中的所有文件和子目录
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                // 删除文件
                Files.delete(file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                // 所有内容被删除后删除目录本身
                Files.delete(dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                // 如果访问文件失败,则抛出异常
                throw exc;
            }
        });
    }

    public static String createFolder(String folderPath) {
        String txt = folderPath;
        try {
            File myFilePath = new File(txt);
            txt = folderPath;
            if (!myFilePath.exists()) {
                myFilePath.mkdirs();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return txt;
    }


    public static List<String> getWordsByBase64(String base64) throws IOException {
        List<String> words = new ArrayList<>();

        if (StringUtils.isEmpty(base64)) {
            return null;
        }
        String outputDir = outputDirs + UUID.randomUUID().toString().replace("-", "");

        
        // 解码Base64字符串
        byte[] decodedBytes = Base64.getDecoder().decode(base64);
        createFolder(outputDir);
        // 输出的PDF文件名
        String outputFilePath = outputDir+"/output.pdf";
        try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
            // 将解码后的字节数组写入文件
            fos.write(decodedBytes);
            System.out.println("PDF文件已成功生成: " + outputFilePath);

            words = getWords(outputFilePath);
        } catch (Exception e) {
            e.printStackTrace();
        }

        deleteDirectory(outputDir);
        return words;
    }
    
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用网页版Jupyter Notebook和VScode打开.ipynb文件

目录 正文 1、网页版Jupyter Notebook查看 2、VScode查看 因为总是忘记查看文件的网址&#xff0c;收藏了但分类众多每次都找不到……当个记录吧&#xff08;/捂脸哭&#xff09;&#xff01; 正文 此处以gitub中的某个仓库为例&#xff1a; https://github.com/INM-6/mu…

景联文科技提供高质量多模态数据处理服务,驱动AI新时代

在当今快速发展的AI时代&#xff0c;多模态数据标注成为推动人工智能技术进步的关键环节。景联文科技作为行业领先的AI数据服务提供商&#xff0c;专注于为客户提供高质量、高精度的多模态数据标注服务&#xff0c;涵盖图像、语音、文本、视频及3D点云等多种类型的数据。通过专…

Python在Excel工作表中创建数据透视表

在数据处理和分析工作中&#xff0c;Excel作为一个广泛使用的工具&#xff0c;提供了强大的功能来管理和解析数据。当面对大量复杂的数据集时&#xff0c;为了更高效地总结、分析和展示数据&#xff0c;创建数据透视表成为一种不可或缺的方法。通过使用Python这样的编程语言与E…

django基于Python的电影推荐系统

Django 基于 Python 的电影推荐系统 一、系统概述 Django 基于 Python 的电影推荐系统是一款利用 Django 框架开发的智能化应用程序&#xff0c;旨在为电影爱好者提供个性化的电影推荐服务。该系统通过收集和分析用户的观影历史、评分数据、电影的属性信息&#xff08;如类型…

GPT-SoVITS学习01

1.什么是TTS TTS&#xff08;Text-To-Speech&#xff09;这是一种文字转语音的语音合成。类似的还有SVC&#xff08;歌声转换&#xff09;、SVS&#xff08;歌声合成&#xff09;等。 2.配置要求 GPT-SoVITS对电脑配置有较高的要求。 训练&#xff1a;对于Windows电脑&#…

计算机网络 (36)TCP可靠传输的实现

前言 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP通过多种机制实现可靠传输&#xff0c;这些机制主要包括连接管理、序列号和确认应答机制、重传机制、流量控制、拥塞控制等。 一、连接管理 TCP使用三次握手&#xff0…

视频编辑最新SOTA!港中文Adobe等发布统一视频生成传播框架——GenProp

文章链接&#xff1a;https://arxiv.org/pdf/2412.19761 项目链接&#xff1a;https://genprop.github.io 亮点直击 定义了一个新的生成视频传播问题&#xff0c;目标是利用 I2V 模型的生成能力&#xff0c;将视频第一帧的各种变化传播到整个视频中。 精心设计了模型 GenProp&…

make工程管理器与Makefile

目录 一、介绍 1、make工程管理器 2、Makefile 二、Makefile语法规则 1、Makefile语法格式 2、Makefile中特殊处理与伪目标 3、变量、规则与函数 (1)自定义变量使用示例 (2)自动变量使用示例 一、介绍 1、make工程管理器 定义&#xff1a; make是一个命令工具&…

【git】-2 分支管理

目录 一、分支的概念 二、查看、创建、切换分支 1、查看分支-git branch 2、创建分支- git branch 分支名 3、切换分支- git checkout 分支名 三、git指针 -实现分支和版本间的切换 四、普通合并分支 git merge 文件名 五、冲突分支合并 ​​​​​​【git】-初始gi…

3DGabor滤波器实现人脸特征提取

import cv2 import numpy as np# 定义 Gabor 滤波器的参数 kSize 31 # 滤波器核的大小 g_sigma 3.0 # 高斯包络的标准差 g_theta np.pi / 4 # Gabor 函数的方向 g_lambda 10.0 # 正弦波的波长 g_gamma 0.5 # 空间纵横比 g_psi np.pi / 2 # 相位偏移# 生成 Gabor 滤…

接口项目架构流程图-thinkphp6-rabbitmq

一、整个系统流程 第一步&#xff1a;平台在创建好后开启消息队列&#xff1b; 第二步&#xff1a;平台为需要服务的客户开好账号并传输对应的公私钥文件&#xff1b; 第三步&#xff1a;客户通过平台分享的接口连接地址采用开户时的手机号查看&#xff1b; 第四步&#xff1a;…

Vue3初学之组件通信

一起进行学习&#xff1a; 在 Vue 3 中&#xff0c;组件通信是一个非常重要的概念&#xff0c;它决定了如何在父子组件之间、兄弟组件之间以及跨层级组件之间传递数据和事件。以下是 Vue 3 中常见的组件通信方式&#xff1a; 父子组件通信 1.1 父组件向子组件传递数据&#x…

2025年第三届“华数杯”国际大学生数学建模竞赛【A题】Problem A: Can He Swim Faster

问题1&#xff1a;运动员的出色比赛表现通常得益于艰苦且持续的专业训练&#xff0c;这不仅提升了游泳技能&#xff0c;也增强了生理储备。比赛中&#xff0c;科学控制游泳速度是关键&#xff0c;包括保持个人节奏、寻求最佳身体状态节奏和合理分配体力。针对自由泳项目&#x…

【计算机网络】lab4 Ipv4(IPV4的研究)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;计算机网络_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2.…

ELFK日志采集实战

一、日志分析概述 日志分析是运维工程师解决系统故障&#xff0c;发现问题的主要手段 日志主要包括系统日志、应用程序日志和安全日志 系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因 经常分析日志可以了解服务器的负荷&#x…

辅助--Inspector

辅助–Inspector 1.Introduction This manual explains how to use the Inspector. 1.1.Overview Inspector is a Qt-based library that provides functionality to interactively inspect low-level content of the OCAF data model, OCCT viewer and Modeling Data. Thi…

如何播放视频文件

文章目录 1. 概念介绍2. 使用方法2.1 实现步骤2.2 具体细节3. 示例代码4. 内容总结我们在上一章回中介绍了"如何获取文件类型"相关的内容,本章回中将介绍如何播放视频.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 播放视频是我们常用的功能,不过Flutter官方…

R数据分析:多分类问题预测模型的ROC做法及解释

有同学做了个多分类的预测模型,结局有三个类别,做的模型包括多分类逻辑回归、随机森林和决策树,多分类逻辑回归是用ROC曲线并报告AUC作为模型评估的,后面两种模型报告了混淆矩阵,审稿人就提出要统一模型评估指标。那么肯定是统一成ROC了,刚好借这个机会给大家讲讲ROC在多…

【数据库】四、数据库管理与维护

文章目录 四、数据库管理与维护1 安全性管理2 事务概述3 并发控制4 备份与恢复管理 四、数据库管理与维护 1 安全性管理 安全性管理是指保护数据库&#xff0c;以避免非法用户进行窃取数据、篡改数据、删除数据和破坏数据库结构等操作 三个级别认证&#xff1a; 服务器级别…

C语言gdb调试

目录 1.gdb介绍 2.设置断点 2.1.测试代码 2.2.设置函数断点 2.3.设置文件行号断点 2.4.设置条件断点 2.5.多线程调试 3.删除断点 3.1.删除指定断点 3.2.删除全部断点 4.查看变量信息 4.1.p命令 4.2.display命令 4.3.watch命令 5.coredump日志 6.总结 1.gdb介绍…