java通过ocr实现识别pdf中的文字
需求:识别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>() {@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {// 删除文件Files.delete(file);return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {// 所有内容被删除后删除目录本身Files.delete(dir);return FileVisitResult.CONTINUE;}@Overridepublic 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;}}
相关文章:
java通过ocr实现识别pdf中的文字
需求:识别pdf文件中的中文 根据github项目mymonstercat 改造,先将pdf文件转为png文件存于临时文件夹,然后通过RapidOcr转为文字,最后删除临时文件夹 1、引入依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId&g…...
Git 命令代码管理详解
一、Git 初相识:版本控制的神器 在当今的软件开发领域,版本控制如同基石般重要,而 Git 无疑是其中最耀眼的明珠。它由 Linus Torvalds 在 2005 年创造,最初是为了更好地管理 Linux 内核源代码。随着时间的推移,Git 凭借…...
Docker的安装和使用
容器技术 容器与虚拟机的区别 虚拟机 (VM) VM包含完整的操作系统,并在虚拟化层之上运行多个操作系统实例。 VM需要更多的系统资源(CPU、内存、存储)来管理这些操作系统实例。 容器 (Container) 容器共享主机操作系统的内核,具…...
Flink系统知识讲解之:Flink内存管理详解
Flink系统知识讲解之:Flink内存管理详解 在现阶段,大部分开源的大数据计算引擎都是用Java或者是基于JVM的编程语言实现的,如Apache Hadoop、Apache Spark、Apache Drill、Apache Flink等。Java语言的好处是不用考虑底层,降低了程…...
使用JMeter模拟多IP发送请求!
你是否曾遇到过这样的场景:使用 JMeter 进行压力测试时,单一 IP 被服务器限流或者屏蔽?这时,如何让 JMeter 模拟多个 IP 发送请求,成功突破测试限制,成为测试工程师必须攻克的难题。今天,我们就…...
【Ubuntu与Linux操作系统:六、软件包管理】
第6章 软件包管理 6.1 Linux软件安装基础 Linux的软件包是以二进制或源码形式发布的程序集合,包含程序文件和元数据。软件包管理器是Linux系统的重要工具,用于安装、更新和卸载软件。 1. 常见的软件包管理器: DEB 系统(如Ubunt…...
【数据结构-堆】力扣1834. 单线程 CPU
给你一个二维数组 tasks ,用于表示 n 项从 0 到 n - 1 编号的任务。其中 tasks[i] [enqueueTimei, processingTimei] 意味着第 i 项任务将会于 enqueueTimei 时进入任务队列,需要 processingTimei 的时长完成执行。 现…...
【前端动效】原生js实现拖拽排课效果
目录 1. 效果展示 2. 效果分析 2.1 关键点 2.2 实现方法 3. 代码实现 3.1 html部分 3.2 css部分 3.3 js部分 3.4 完整代码 4. 总结 1. 效果展示 如图所示,页面左侧有一个包含不同课程(如语文、数学等)的列表,页面右侧…...
C#使用OpenTK绘制3D可拖动旋转图形三棱锥
接上篇,绘制着色矩形 C#使用OpenTK绘制一个着色矩形-CSDN博客 上一篇安装OpenTK.GLControl后,这里可以直接拖动控件GLControl 我们会发现GLControl继承于UserControl //// 摘要:// OpenGL-aware WinForms control. The WinForms designer will always call the default//…...
排序的本质、数据类型及算法选择
排序的本质、数据类型及算法选择 一、排序的本质二、排序的数据类型三、排序算法的选择依据 前两天老金写了篇 “十大排序简介”,有点意犹未尽,这一回老金想把排序连根拔起,从排序的本质说道说道。 一、排序的本质 从字面上理解,…...
Python的列表基础知识点(超详细流程)
目录 一、环境搭建 二、列表 2.1 详情 2.2 列表定义 2.3 列表长度 2.4 列表索引 2.5 切片索引 2.6 添加 2.7 插入 2.8 剔除 2.8.1 pop方法 2.8.2 del方法 2.9 任何数据类型 2.10 拼接 2.10.1 “” 2.10.2 “*” 2.11 逆序 编辑 2.12 计算出现次数 2.13 排序…...
HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现
HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现 最近在学习鸿蒙开发过程中,阅读了官方文档,在之前做flutter时候,经常使用overlay,使用OverlayEntry加入到overlayState来做添加悬浮按钮、提示弹窗、加载中指示器、加载失败的t…...
【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】
第1章 Ubuntu安装与基本使用 1.1 Linux与Ubuntu Linux是一种开源、类Unix操作系统内核,拥有高稳定性和强大的网络功能。由于其开源性和灵活性,Linux被广泛应用于服务器、嵌入式设备以及桌面环境中。 Ubuntu是基于Debian的一个流行Linux发行版…...
React 元素渲染
React 元素渲染 React 是一个用于构建用户界面的 JavaScript 库,它允许开发人员创建大型应用程序,这些应用程序可以随着时间的推移而高效地更新和渲染。React 的核心概念之一是元素渲染,它描述了如何将 JavaScript 对象转换为 DOM࿰…...
【2024年华为OD机试】 (C卷,100分)- 括号匹配(Java JS PythonC/C++)
一、问题描述 题目描述 给定一个字符串,里边可能包含“()”、“[]”、“{}”三种括号,请编写程序检查该字符串中的括号是否成对出现,且嵌套关系正确。 若括号成对出现且嵌套关系正确,或该字符串中无括号字符,输出&am…...
解锁企业数字化转型新力量:OpenCoze(开源扣子)
在当今数字化浪潮席卷之下,企业对于高效管理和协同运作的需求愈发迫切,而开源技术正逐渐成为众多企业破局的关键利器。今天,想给大家介绍一款极具潜力的开源项目 ——OpenCoze,中文名称 “开源扣子”。 一、OpenCoze 是什么&…...
【网络云SRE运维开发】2025第2周-每日【2025/01/12】小测-【第12章 rip路由协议】理论和实操考试题解析
文章目录 选择题答案及解析理论题答案及解析实操题答案及解析下一步进阶 选择题答案及解析 RIP路由协议是基于哪种算法的动态路由协议? 答案:B. 距离矢量算法解析:链路状态算法用于OSPF等协议;最小生成树算法主要用于生成树协议&…...
【微服务】8、分布式事务 ( XA 和 AT )
文章目录 利用Seata解决分布式事务问题(XA模式)AT模式1. AT模式原理引入2. AT模式执行流程与XA模式对比3. AT模式性能优势及潜在问题4. AT模式数据一致性解决方案5. AT模式一阶段操作总结6. AT模式二阶段操作分析7. AT模式整体特点8. AT模式与XA模式对比…...
CVE-2025-22777 (CVSS 9.8):WordPress | GiveWP 插件的严重漏洞
漏洞描述 GiveWP 插件中发现了一个严重漏洞,该插件是 WordPress 最广泛使用的在线捐赠和筹款工具之一。该漏洞的编号为 CVE-2025-22777,CVSS 评分为 9.8,表明其严重性。 GiveWP 插件拥有超过 100,000 个活跃安装,为全球无数捐赠平…...
TypeScript Jest 单元测试 搭建
NPM TypeScript 项目搭建 创建目录 mkdir mockprojectcd mockproject初始化NPM项目 npm init -y安装TypeScript npm i -D typescript使用VSCode 打开项目 创建TS配置文件tsconfig.json {"compilerOptions": {"target": "es5","module&…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
