ai之pdf解析工具 PPStructure 还是PaddleOCR

目录

  • 重点是四 先用 PPStructure 版面分析,分成不同的块儿,再选用 PaddleOCR、或PPStructure
  • 基础路径
  • OCR模型配置
  • OCR模型配置
  • GPU配置
  • 硬件配置
  • 性能配置
      • 一、框架选型对比分析
        • 1. **PaddleOCR核心能力**
        • 2. **PP-Structure核心能力**
        • 3. **选型结论**
      • 二、错误根因分析与修复方案
        • 1. **错误现象**
        • 2. **深层原因**
        • 3. **修复方案
      • 三、性能优化建议
        • 1. **GPU资源利用**
        • 2. **内存管理**
        • 3. **模型裁剪**
      • 四、架构设计升级建议
        • 1. **流程重组**
        • 2. **模块解耦**
      • 五、关键参数调优指南

重点是四 先用 PPStructure 版面分析,分成不同的块儿,再选用 PaddleOCR、或PPStructure

https://chat.deepseek.com/a/chat/s/1dafb23d-d230-48a6-b3a1-72569eb1c7cd

我有解析PDF的程序如下:
1、配置
“”"
OCR处理工具类
功能:统一管理OCR引擎的初始化、处理、资源回收
“”"
import multiprocessing
import os
from pathlib import Path
from typing import Tuple, Optional, Dict, Any

import paddle
from paddleocr import PaddleOCR, PPStructure

from .GPUResource import GPUResourceController
from …utils.logutil import get_local_logger

logger = get_local_logger()

基础路径

BASE_DIR = Path(file).parent.parent
MODEL_DIR = BASE_DIR / “common/models”
logger.info(f" >>>>>> MODEL_DIR路径: {MODEL_DIR}")

OCR模型配置

START_PAGE = 6

OCR模型配置

OCR_CONFIG = {
# 显式指定所有模型路径
# det_model_dir=str(MODEL_DIR /“ch_PP-OCRv4_det_infer”),
“det_model_dir”: str(MODEL_DIR / “ch_PP-OCRv4_det_infer”),
“rec_model_dir”: str(MODEL_DIR / “ch_PP-OCRv4_rec_infer”),
“cls_model_dir”: str(MODEL_DIR / “ch_ppocr_mobile_v2.0_cls_infer”),
“table_model_dir”: str(MODEL_DIR / “en_ppstructure_mobile_v2.0_table_structure_infer”),
“layout_model_dir”: str(MODEL_DIR / “en_ppstructure_mobile_v2.0_layout_infer”),
“lang”: “ch”,
“ocr_version”: “PP-OCRv4”,
“table_version”: “PP-StructureV2”
}

GPU配置

GPU_CONFIG = {
“enable_gpu”: True,
“max_gpus”: 2,
“memory_fraction”: 0.5
}

硬件配置

GPU_MEMORY_LIMIT = 0.8 # 单进程最大显存占比
CPU_THREADS = 4 # CPU模式线程数

性能配置

PRECISION_MODE = “fp16” if paddle.is_compiled_with_cuda() else “fp32”
ENABLE_TENSORRT = True

use_gpu_flag = paddle.device.is_compiled_with_cuda()
print(f"torch.cuda.is_available(){use_gpu_flag}")
print(f"torch.version
{paddle.device.get_cudnn_version()}")

class OCREngineInitError(Exception):
“”“OCR引擎初始化异常”“”
pass

“”"
OCR配置工具类
“”"
class OCRConfig:

def __init__(self, process_idx: int = 0):"""初始化OCR工具:param process_idx: 进程ID(用于多进程GPU分配)"""self.process_idx = process_idxself.gpu_id = -1self.ocr_engine = Noneself.table_engine = Noneself._init_gpu()self._init_ocr_engine()self._init_table_engine()def __enter__(self):self._set_hardware_environment()self._init_engines()return selfdef __exit__(self, exc_type, *_):self._cleanup_resources()self._report_gpu_status(exc_type is None)def _set_hardware_environment(self):os.environ["CUDA_VISIBLE_DEVICES"] = str(self.gpu_id) if self.gpu_id != -1 else ""device = "gpu:0" if self.gpu_id != -1 else "cpu"paddle.set_device(device)if self.gpu_id != -1:paddle.set_flags({'FLAGS_fraction_of_gpu_memory_to_use': GPU_MEMORY_LIMIT,'FLAGS_allocator_strategy': 'auto_growth'})def _init_gpu(self) -> None:"""初始化GPU环境"""if not GPU_CONFIG["enable_gpu"] or not paddle.is_compiled_with_cuda():logger.info(f" paddle.is_compiled_with_cuda: {paddle.device.is_compiled_with_cuda()}, 即将运行在CPU模式")paddle.set_device("cpu")returnnum_gpus = paddle.device.cuda.device_count()if num_gpus == 0:logger.warn(f" num_gpus: {num_gpus}, 没有检测到可用的GUP, 即将运行在CPU模式")return -1  # 标记为CPU模式self.gpu_id = self.process_idx % num_gpusos.environ["CUDA_VISIBLE_DEVICES"] = str(self.gpu_id)paddle.set_device(f"gpu:{self.gpu_id}")logger.info(f"初始化GPU:{self.gpu_id} | 进程:{self.process_idx}")# 设置显存分配比例paddle.set_flags({'FLAGS_fraction_of_gpu_memory_to_use': GPU_CONFIG["memory_fraction"]})def _init_ocr_engine(self) -> None:"""初始化OCR引擎"""try:self.ocr_engine = PaddleOCR(use_angle_cls=True,lang=OCR_CONFIG["lang"],page_num=START_PAGE,use_gpu=self.gpu_id != -1,gpu_id=self.gpu_id,table_model_dir="../common/models/en_ppstructure_mobile_v2.0_table_structure_infer",  # 显式指定表格模型# 显式指定所有模型路径# det_model_dir=str(MODEL_DIR /"ch_PP-OCRv4_det_infer"),det_model_dir=OCR_CONFIG["det_model_dir"],rec_model_dir=OCR_CONFIG["rec_model_dir"],cls_model_dir=OCR_CONFIG["cls_model_dir"],# ocr_version=OCR_CONFIG["ocr_version"],table_version="PP-StructureV2",  # 使用表格识别模型show_log=False,# 性能优化参数enable_mkldnn=True,  # Intel CPU 加速use_tensorrt=False,   # NVIDIA GPU 加速precision="fp16"     # 混合精度推理)print(f" OCR引擎初始化成功 [PID:{os.getpid()}] Assigned to GPU {self.gpu_id} (Process index: {self.process_idx})")except Exception as e:logger.error(f"OCR引擎初始化失败: {str(e)}")raise OCREngineInitError("OCR初始化失败") from edef _init_table_engine(self) -> None:"""初始化表格引擎: 使用RapidTable """# table_input = RapidTableInput(#     model_type="unitable",#     use_cuda=self.gpu_id != -1,#     device=f"cuda:{self.gpu_id}" if self.gpu_id != -1 else "cpu"# )# self.table_engine = RapidTable(table_input)"""初始化表格引擎: 使用PPStructure """try:self.table_engine = PPStructure(table_model_dir=OCR_CONFIG["table_model_dir"],layout_model_dir=OCR_CONFIG["layout_model_dir"],table_version=OCR_CONFIG["table_version"],ocr=False,use_gpu=GPU_CONFIG["enable_gpu"],gpu_id=self.gpu_id,show_log=False)logger.info("表格引擎初始化成功")except Exception as e:logger.error(f"表格引擎初始化失败: {str(e)}")raise OCREngineInitError("表格引擎初始化失败") from edef _cleanup_resources(self):"""资源清理"""if self.gpu_id != -1:paddle.device.cuda.empty_cache()logger.info(f"已释放GPU:{self.gpu_id}资源")
def _report_gpu_status(self, success: bool):if self.gpu_id != -1:GPUResourceController().release_gpu(self.gpu_id, success)

class OCRManager:
“”"
OCR引擎管理器(多进程安全)
“”"
_engines = {}

@classmethod
def get_engine(cls, process_idx: int) -> OCRConfig:"""获取进程专用引擎"""if not process_idx:process_idx = os.getpid()if process_idx not in cls._engines:try:cls._engines[process_idx] = OCRConfig(process_idx)except OCREngineInitError as e:raise RuntimeError(f"无法为进程{process_idx}创建引擎") from ereturn cls._engines[process_idx]
"""
GPU资源管理器(进程安全版本)
核心功能:
- 自动检测可用GPU
- 实现进程级GPU分配
- 避免跨进程污染
"""
_gpu_ring = []
_lock = multiprocessing.Lock()def __init__(self):self._init_gpu_pool()def _init_gpu_pool(self):"""安全初始化GPU资源池"""with self._lock:if not self._gpu_ring:if paddle.is_compiled_with_cuda():num_gpus = paddle.device.cuda.device_count()self._gpu_ring = list(range(num_gpus)) if num_gpus > 0 else []logger.info(f"GPU资源池初始化完成: {self._gpu_ring}")def acquire_gpu(self, process_id: int) -> int:"""进程安全获取GPU ID"""with self._lock:if not self._gpu_ring:return -1return self._gpu_ring[process_id % len(self._gpu_ring)]

2、处理程序:
def _process_ocr_and_table(self, img_path, page_idx:int):
# 假设这是你的 OCR 和表格识别逻辑
try:
“”“使用进程级引擎处理”“”
ocr_config = OCRManager.get_engine(os.getpid())
ocr_engine = ocr_config.ocr_engine
table_engine = ocr_config.table_engine

        # OCR识别ocr_output = ocr_engine.ocr(img_path)if not ocr_output:raise ValueError(" ocr_output OCR未识别到内容")logger.info(f" 第{page_idx}页OCR识别结果,类型:{type(ocr_output)}, \n 内容示例:{ocr_output}")# 解析OCR结果:每个元素的结构为 [box_coords, (text, score)]boxes = [line[0] for line in ocr_output]  # 提取所有框坐标txts = [line[1][0] for line in ocr_output]  # 提取所有文本

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

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

相关文章

Android计算机网络学习总结

TCP vs UDP 核心区别​​ ​题目​:TCP为什么称为可靠传输协议?UDP在哪些场景下比TCP更具优势? ​得分要点​: ​可靠性机制​ 三握四挥建立可靠连接确认应答(ACK) 超时重传滑动窗口流量控制拥塞控制&…

深入解析Java组合模式:构建灵活树形结构的艺术

引言:当对象需要树形组织时 在日常开发中,我们经常需要处理具有层次结构的对象集合。比如: 文件系统中的文件夹与文件GUI界面中的容器与控件企业组织架构中的部门与员工 这类场景中的对象呈现明显的整体-部分层次结构,如何优雅…

mobaxterm通过ssh登录docker无图形界面

1. 流程 下面是使用Mobaxterm通过SSH登录Docker无图形界面的步骤: 步骤 操作 1 在本地安装Mobaxterm 2 配置Mobaxterm连接SSH 3 启动Docker容器 4 在Mobaxterm中通过SSH连接到Docker容器 2. 操作步骤 步骤1:安装Mobaxterm 首先&#xff…

【赵渝强老师】HBase的体系架构

HBase是大表(BigTable)思想的一个具体实现。它是一个列式存储的NoSQL数据库,适合执行数据的分析和处理。简单来说,就是适合执行查询操作。从体系架构的角度看,HBase是一种主从架构,包含:HBase H…

linux 新增驱动宏config.in配置

‌1. 添加配置宏步骤‌ ‌1.1 修改 Kconfig(推荐方式)‌ ‌定位 Kconfig 文件‌ 内核各子目录(如 drivers/char/)通常包含 Kconfig 文件,用于定义模块配置选项7。‌添加宏定义‌ 示例:在 drivers/char/Kc…

关于git的使用

下载git 可以去git的官网下载https://git-scm.com/downloads 也可以去找第三方的资源下载,下载后是一个exe应用程序,直接点开一直下一步就可以安装了 右键任意位置显示这两个就代表成功,第一个是git官方的图形化界面,第二个是用…

WPF【11_8】WPF实战-重构与美化(UI 与视图模型的联动,实现INotifyPropertyChanged)

11-13 【重构】INotifyPropertyChanged 与 ObservableCollection 现在我们来完成新建客户的功能。 当用户点击“客户添加”按钮以后系统会清空当前所选定的客户,客户的详细信息以及客户的预约记录会从 UI 中被清除。然后我们就可以在输入框中输入新的客户信息了&am…

ArkUI:鸿蒙应用响应式与组件化开发指南(一)

文章目录 引言1.ArkUI核心能力概览1.1状态驱动视图1.2组件化:构建可复用UI 2.状态管理:从单一组件到全局共享2.1 状态装饰器2.2 状态传递模式对比 引言 鸿蒙生态正催生应用开发的新范式。作为面向全场景的分布式操作系统,鸿蒙的北向应用开发…

List优雅分组

一、前言 最近小永哥发现,在开发过程中,经常会遇到需要对list进行分组,就是假如有一个RecordTest对象集合,RecordTest对象都有一个type的属性,需要将这个集合按type属性进行分组,转换为一个以type为key&…

AI与.NET技术实操系列(八):使用Catalyst进行自然语言处理

引言 自然语言处理(Natural Language Processing, NLP)是人工智能领域中最具活力和潜力的分支之一。从智能客服到机器翻译,再到语音识别,NLP技术正以其强大的功能改变着我们的生活方式和工作模式。 Catalyst的推出极大降低了NLP…

MySQL 8.0 OCP 1Z0-908 题目解析(13)

题目49 Choose the best answer. t is a non - empty InnoDB table. Examine these statements, which are executed in one session: BEGIN; SELECT * FROM t FOR UPDATE;Which is true? ○ A) mysqlcheck --analyze --all - databases will execute normally on all ta…

Docker 一键部署倒计时页面:Easy Countdown全设备通用

Easy Countdown 介绍 Easy countdown是一个易于设置的倒计时页面。可以设置为倒计时或计时器。可用于个人生活、工作管理、教育、活动策划等多个领域。 🚢 项目地址 Github:https://github.com/Yooooomi/easy-countdown 🚀Easy Countdown …

Python训练打卡Day35

模型可视化与推理 知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 模型结构可视化 理解一个深度学习网络最重要的2点…

四、生活常识

一、效应定律 效应 1、沉没成本效应 投入的越多,退出的难度就越大,因为不甘心自己之前的所有付出都付之东流。 2、破窗效应 干净的环境下,没有人会第一个丢垃圾,但是当环境变得糟糕,人们就开始无所妒忌的丢垃圾。…

机器学习圣经PRML作者Bishop20年后新作中文版出版!

机器学习圣经PRML作者Bishop20年后新书《深度学习:基础与概念》出版。作者克里斯托弗M. 毕晓普(Christopher M. Bishop)微软公司技术研究员、微软研究 院 科学智 能 中 心(Microsoft Research AI4Science)负责人。剑桥…

Python应用嵌套猜数字小游戏

大家好!今天向大家分享的是有关“嵌套”的猜数字小游戏。希望能够帮助大家理解嵌套。 代码呈现: # 1. 构建一个随机的数字变量 import random num random.randint(1, 10)guess_num int(input("输入你要猜测的数字: "))# 2. 通过if判断语句进行数字的猜…

黑马k8s(十四)

1.Service-概述 service:用于四层路由的负载,Ingress七层路由的负载;,先学习service 开启ipvs 2.Service-资源清单文件介绍 修改每个显示的内容 ClusterIP类型的Service Endpoints:建立service与pod关联 亲和性测试…

Kotlin 中 Lambda 表达式的语法结构及简化推导

在 Kotlin 编程中,Lambda 表达式是一项非常实用且强大的功能。今天,我们就来深入探讨一下 Lambda 表达式的语法结构,以及它那些令人 “又爱又恨” 的简化写法。 一、Lambda 表达式完整语法结构 Lambda 表达式最完整的语法结构定义为{参数名…

Kafka Streams 和 Apache Flink 的无状态流处理与有状态流处理

Kafka Streams 和 Apache Flink 与数据库和数据湖相比的无状态和有状态流处理的概念和优势。 在数据驱动的应用中,流处理的兴起改变了我们处理和操作数据的方式。虽然传统数据库、数据湖和数据仓库对于许多基于批处理的用例来说非常有效,但在要求低延迟…

【后端高阶面经:缓存篇】34、高并发下缓存穿透、击穿、雪崩怎么解决

一、缓存三大核心问题:穿透、击穿、雪崩的本质区别 (一)概念对比表 问题类型核心特征典型场景危害等级缓存穿透数据在缓存和数据库中均不存在,请求直接穿透到数据库恶意攻击(伪造不存在的ID)、业务逻辑漏洞★★★★★缓存击穿热点数据在缓存中过期,大量并发请求同时击穿…