PaddleOCR项目实战(1):Python脚本中使⽤PaddleOCR

1 项目介绍

项目架构如下:

  • APP/WEB/⼩程序为OCR识别接⼝调⽤端,调⽤OCR接⼝,实现OCR功能。本项⽬我们只实现Android APP开发。
  • Nginx反向代理和负载均衡功能,通过Nginx实现对外⽹暴露接⼝,对内负载均衡SpringBoot实现的OCR服务。
  • OCR服务通过Springboot实现,主要功能是提供具体的OCR接⼝实现,其流程是调⽤内部PaddleOCR服务,解析和处理返回结果,最终返回结果给接⼝调⽤者。为了稳定性和安全性,添加了熔断限流、Token认证功能。为了⽅便部署,会以Docker形式部署该服务。
  • PaddleOCR是OCR识别的具体实现,会提供⼀个OCR识别接⼝,供内部调⽤。由于不同的部署⽅式(普通部署和paddleocr serving⽅式部署),PaddleOCR在普通部署⽅式下,⽆法利⽤CPU多核(Servering⽅式不存在该问题),因此会在同⼀个服务器部署多个实例,解决CPU利⽤率差以提升性能。为了⽅便PaddleOCR部署,会以Docker形式部署。后边会讲解普通⽅式部署和Servering⽅式部署,如何构建docker镜像及部署流程。

2 python开发PaddleOCR内部接口

2.1 安装 Flask

pip install flask==3.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

2.2 编写简单Flask接口进行测试

新建python文件,编写接口如下:

@app.route("/learn/hello")
def hello_world():return "Hello,World!"

结果如下:

接口代码如下:

@app.route("/learn/path/<string:name>")
def learn_path(name):return name

结果如下:

接口代码如下:

@app.route("/learn/m-get", methods=["GET"])
def learn_get_method():age = request.args.get("age")name = request.args.get("name")logging.info("learn m-get age 是:%s, name是:%s", age, name)return "SUCCESS", 200

结果如下:

接口代码如下:

# 通过POST方式获取参数,参数时jsOn符中
@app.route("/learn/m-post", methods=["POST"])
def learn_post_method():data = request.datalogging.info("learn post-m data :%s", data)data = json.loads(data)age = data["age"]name = data["name"]logging.info("learn post-m age:%s name:%s", age, name)return jsonify(data), 200

结果如下:

上面都成功说明Flask没问题。

完整代码如下:

import json
import logging
from flask import Flask, request, jsonifydef init_log():# 设置打印到控制台的格式和等级logging.basicConfig(format='%(asctime)s %(filename)s %(levelname)s %(message)s', datefmt='%a %d %b %Y %H:%M:%S',level=logging.INFO)# 设置输出到的文件和编码file_handler = logging.FileHandler("ocr.log", encoding="utf-8")# 设置输出等级file_handler.setLevel(logging.INFO)# 设置输出到文件的日志格式file_handler.setFormatter(logging.Formatter('%(asctime)s %(filename)s %(levelname)s %(message)s'))logger = logging.getLogger()logger.handlers.append(file_handler)init_log()# name是python中的特殊变量,如果文件作为主程序执行(例如直接技行),那么..name.的值就是_main_-,如果是被其它模块引入,那么__name-就是模块名称
app = Flask(__name__)@app.route("/learn/hello")
def hello_world():return "Hello,World!"@app.route("/learn/path/<string:name>")
def learn_path(name):return name@app.route("/learn/m-get", methods=["GET"])
def learn_get_method():age = request.args.get("age")name = request.args.get("name")logging.info("learn m-get age 是:%s, name是:%s", age, name)return "SUCCESS", 200# 通过POST方式获取参数,参数时jsOn符中
@app.route("/learn/m-post", methods=["POST"])
def learn_post_method():data = request.datalogging.info("learn post-m data :%s", data)data = json.loads(data)age = data["age"]name = data["name"]logging.info("learn post-m age:%s name:%s", age, name)return jsonify(data), 200if __name__ == '__main__':# 接收所有的IP请求,debug=True表示代列修改web容器公业启app.run(host='0.0.0.0', debug=True, port=8888)

2.3 Flask集成PaddleOCR

检测+⽅向分类器+识别全流程,只需要下⾯三⾏代码

#导⼊依赖
from paddleocr import PaddleOCR
#创建PaddleOCR对象,只需要在初始化时执⾏⼀次该语句
ocr = PaddleOCR(use_angle_cls=True, det=False, use_gpu=False)
#识别图⽚返回结果,cls=True 表示识别旋转180度的⽂字,如果没有⽂字旋转180度,那么
#可以cls=False,这样会提升性能,旋转90度和270度也能够识别
result = ocr.ocr(imgPath, cls=True)

完整的PaddleOCR内部接口开发如下:

下⾯这段python代码主要是实现:通过flask创建web容器,并通过/ocr 接⼝调⽤ paddleocr进⾏图⽚识别,并通过json格式返回识别结果。

import json
import logging
from flask import Flask, request, jsonify
from paddleocr import PaddleOCRdef init_log():# 设置打印到控制台的格式和等级logging.basicConfig(format='%(asctime)s %(filename)s %(levelname)s %(message)s', datefmt='%a %d %b %Y %H:%M:%S',level=logging.INFO)# 设置输出到的文件和编码file_handler = logging.FileHandler("ocr.log", encoding="utf-8")# 设置输出等级file_handler.setLevel(logging.INFO)# 设置输出到文件的日志格式file_handler.setFormatter(logging.Formatter('%(asctime)s %(filename)s %(levelname)s %(message)s'))logger = logging.getLogger()logger.handlers.append(file_handler)init_log()# name 是python中的特殊变量,如果文件作为主程序执行(例如直接执行),那么__name__的值就是__main__,如果是被其它模块引入,那么__name__就是模块名称
app = Flask(__name__)# 创建一个PaddleOCR对象,使用方向识别器,不使用gpu进行技术,通过cpu进行计算。PaddleOCR我们只需要初始化一次,会将模型加载到内存,会将相关模型下载如果是第一次使用
ocr = PaddleOCR(usr_angle_cls=True, use_gpu=False)# 通过POST方法识别图片,传入参数为图片的路径
@app.route("/ocr", methods=["POST"])
def learn_post_method():try:data = json.loads(request.data)img_path = data["imgPath"]logging.info("ocr imgPath : %s", img_path)ocr_result = ocr.ocr(img_path)return jsonify({"code": 0, "msg": "ok", "data": ocr_result}), 200except Exception as e:logging.error("ocr error: %s", str(e))ocr_result = {"code": -1, "msg": str(e)}return jsonify(ocr_result), 200if __name__ == '__main__':# 可以返回中文字符app.config['JSON_AS_ASCII'] = False# 接收所有的IP请求,debug=True表示代码修改web容器会重启app.run(host='0.0.0.0', debug=True, port=8888)
  • import 表示导⼊整个module(模块),⼀个.py⽂件就是⼀个module
  • from A import B 表示导⼊A模块中的B(可以为⽅法、类)
  • flask是python实现的web框架,类似Tomcat

  1. 如果是json格式的请求数据,则是采⽤request.data来获取请求体的字符串。
  2. 如果是form表单的请求体,那么则可以使⽤request.form来获取参数。
  3. 如果是url参数,例如:url?param1=xx¶m2=xx,那么则可以使⽤request.args来获取参数。
  4. 如果需要区分GET\POST请求⽅法,则可以使⽤request.method来进⾏判断区分
  5. 参考:https://cloud.tencent.com/developer/article/1539199,解释的很清楚
  6. @app.route 声明⼀个接⼝,指定请求⽅法和U请求路径
  • 作为 Python 的内置变量,__name__它是每个 Python 模块必备的属性,但它的值取决于你是如何执⾏这段代码。通过__name__变量,可以判断出这时代码是被直接运⾏,还是被导⼊到其他程序中去了。当直接执⾏⼀段脚本的时候,这段脚本的 __name__变量等于 '__main__',当这段脚本被导⼊其他程序的时候,__name__ 变量等于脚本本身的名字。

接口测试,如下:

结果如下:

{"code": 0,"data": [[[[[1.0,12.0],[222.0,12.0],[222.0,35.0],[1.0,35.0]],["2.安装tesseract-ocr",0.9961034059524536]],[[[4.0,55.0],[384.0,54.0],[384.0,72.0],[4.0,73.0]],["OCR(OpticalCharacterRecognition,光学字符识别)软件",0.9673566222190857]],[[[1.0,88.0],[382.0,87.0],[382.0,103.0],[1.0,104.0]],["安装包含两个部分:ORC引擎本身以及对应语言的训练数据",0.9957185387611389]],[[[0.0,155.0],[389.0,153.0],[389.0,172.0],[0.0,174.0]],["githubttt址:https://github.com/tesseract-ocr/tesseract",0.9804431200027466]],[[[0.0,186.0],[576.0,187.0],[576.0,207.0],[0.0,206.0]],["You can either Install Tesseract via pre-built binary package or build it from source.",0.9568857550621033]],[[[1.0,221.0],[86.0,224.0],[85.0,241.0],[1.0,239.0]],["windows:",0.9869498014450073]],[[[1.0,256.0],[915.0,258.0],[915.0,278.0],[1.0,276.0]],["The latest installer can be downloaded here: tesseract-ocr-setup-3.05.01.exe and tesseract-ocr-setup-4.00.00dev.exe (experimental).",0.9753488898277283]]]],"msg": "ok"
}

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

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

相关文章

Reranker + BM25 + FAISS 构建高效的多阶段知识库检索系统一

一、什么是知识库检索&#xff1f; 在构建基于大语言模型的问答系统&#xff08;如 RAG&#xff09;中&#xff0c;知识库检索&#xff08;Retrieval&#xff09; 是第一步&#xff0c;也是影响最终回答质量的关键环节。它负责从大规模文档中快速定位与用户问题最相关的 top-k…

Walle-Web:打造轻量级高效的DevOps自动化部署平台

在当今快速迭代的开发环境中,高效的代码部署工具已成为团队不可或缺的基础设施。Walle-Web作为一款免费开源的DevOps平台,专注解决"部署难、管理乱"的痛点问题,为开发团队提供了简洁而强大的自动化部署解决方案。 1. 什么是Walle-Web? Walle-Web是一款专注于代码…

力扣LeetBook数组和字符串--二维数组

1.旋转矩阵 题目链接 想了那么久的各种旋转&#xff0c;对角线&#xff0c;其实把问题搞复杂了。 旋转90度的本质无非就是转置镜像对称 转置是什么&#xff1f;&#xff1a;将矩阵的行和列互换。 镜像对称&#xff1a;把矩阵从中间对折&#xff0c;互换位置 矩阵 A A [ 1 3 0…

图论水题2

div2 361 D. Tree Requests 题意 对于一颗 n n n节点的树&#xff0c;每个节点有一个字母&#xff0c;有 m m m次询问&#xff0c;每次询问求对于顶点 v v v的子树中深度为 h h h的结点能否组成一个回文串$ (1 \leq n \leq m \leq 5 \cdot 10^5) $ 思路 关于 v v v的子树结…

Redis 过期了解

Redis 版本&#xff1a;5.0 &#xff1a; 一&#xff1a;过期监听&#xff1a; Spring Data Redis 封装了 Redis 的 Pub/Sub 功能&#xff0c;提供了对 key 过期事件的监听支持。 1. 核心类&#xff1a;KeyExpirationEventMessageListener 这个抽象类是 Spring 提供的&#x…

OA工程自动化办公系统 – 免费Java源码

概述 功能完备的OA工程自动化办公系统Java源码&#xff0c;采用主流技术栈开发&#xff0c;无论是学习SpringBoot框架还是开发企业级应用&#xff0c;都是不可多得的优质资源。 主要内容 技术架构 ​​后端技术栈​​&#xff1a; 核心框架&#xff1a;SpringBoot 2.xORM框…

嵌入式SDK技术EasyRTC音视频实时通话助力即时通信社交/教育等多场景创新应用

一、引言​ 在数字化时代&#xff0c;即时通信已成为人们生活和工作中不可或缺的部分。音视频功能作为即时通信的核心&#xff0c;能实现更加直观、高效的信息传递。EasyRTC作为一款强大的实时通信框架&#xff0c;具备诸多优势&#xff0c;为即时通信的音视频应用提供了优质解…

BEV和OCC学习-5:数据预处理流程

参考&#xff1a;自定义数据预处理流程 — MMDetection3D 1.4.0 文档 数据预处理流程的设计 预处理流程中的各项操作主要分为数据加载、预处理、格式化、测试时的数据增强。 接下来将展示一个用于 PointPillars 模型的数据集预处理流程的例子。 train_pipeline [dict(type…

OGG 23ai for DAA 部署与补丁升级

创建ogg 用户 /usr/sbin/groupadd -g 1002 dba /usr/sbin/groupadd -g 1001 oinstall /usr/sbin/groupadd -g 1003 oper useradd -u 1001 -g oinstall -G dba,oper oracle echo "oracle" |passwd oracle --stdin创建ogg安装目录 mkdir -p /u01/app/ogg/soft mkdir …

【LangchainAgent】Agent基本构建与使用

目录 一、功能简述 代码功能概括 &#x1f3af; 核心能力 二、运作流程 三、核心代码 四、运行结果 五、代码功能拆解 ✅ 1. 环境准备与依赖导入 ✅ 2. 加载网页文档并处理为向量 ✅ 3. 创建检索工具与搜索工具 ✅ 4. 初始化语言模型与 Agent ✅ 5. 封装支持多轮记…

【云安全】以Aliyun为例聊云厂商服务常见利用手段

目录 OSS-bucket_policy_readable OSS-object_public_access OSS-bucket_object_traversal OSS-Special Bucket Policy OSS-unrestricted_file_upload OSS-object_acl_writable ECS-SSRF 云攻防场景下对云厂商服务的利用大同小异&#xff0c;下面以阿里云为例 其他如腾…

完成一个可交互的k8s管理平台的页面开发

使用deepseek完成设计一个k8s管理平台&#xff0c;关键词如下&#xff1a; 完成一个可交互的k8s管理平台的页面开发Kubernetes 管理平台页面设计 下面是一个基于现代Web技术的可交互Kubernetes管理平台的页面设计方案&#xff0c;使用React作为前端框架&#xff0c;配合Ant De…

TDengine 支持的平台汇总

TDengine 服务端支持的平台列表 注&#xff1a;1) ● 表示经过官方测试验证&#xff0c; ○ 表示非官方测试验证&#xff0c;E 表示仅企业版支持。 2) 社区版仅支持主流操作系统的较新版本&#xff0c;包括 Ubuntu 18/CentOS 7/CentOS Stream/RedHat/Debian/CoreOS/FreeBSD/Op…

使用 HTML + JavaScript 实现文章逐句高亮朗读功能

在这个信息爆炸的时代&#xff0c;我们每天都要面对大量的文字阅读。无论是学习、工作还是个人成长&#xff0c;阅读都扮演着至关重要的角色。然而&#xff0c;在快节奏的生活中&#xff0c;我们往往难以找到足够的安静时间专注于阅读。本文用 HTML JavaScript 实现了一个基于…

理解非结构化文档:将 Reducto 解析与 Elasticsearch 结合使用

作者&#xff1a;来自 Elastic Adel Wu 演示如何将 Reducto 的文档处理与 Elasticsearch 集成以实现语义搜索。 Elasticsearch 与业界领先的生成式 AI 工具和提供商有原生集成。欢迎观看我们的网络研讨会&#xff0c;了解如何超越 RAG 基础&#xff0c;或使用 Elastic 向量数据…

从Copilot到Agent,AI Coding是如何进化的?

编程原本是一项具有一定门槛的技能&#xff0c;但借助 AI Coding 产品&#xff0c;新手也能写出可运行的代码&#xff0c;非专业人员如业务分析师、产品经理&#xff0c;也能在 AI 帮助下直接生成简单应用。 这一演变对软件产业产生了深远影响。当 AI 逐步参与代码生成、调试乃…

UGUI Text/TextMeshPro字体组件

UGUI Text组件的不当使用及其性能瓶颈与优化 在Unity UGUI系统中&#xff0c;Text 组件&#xff08;或其升级版 TextMeshPro&#xff09;是显示文本信息的核心元素。然而&#xff0c;如果不当使用&#xff0c;它极易成为UI性能瓶颈的罪魁祸首&#xff0c;尤其是在预制体、属性…

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…

【个人笔记】数据库原理(西电)

写在前面&#xff1a;文中提到的页面指向&#xff08;如“p45”&#xff09;&#xff0c;除特别说明&#xff0c;都是指对应ppt上的页面&#xff0c;非同款ppt的友友可忽略 第一章 ER图和关系分解见课本p69 ER图是常用的 概念模型 方形&#xff1a;实体圆形&#xff1a;属性…

SDC命令详解:使用set_propagated_clock命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定端口列表/集合 简单使用 注意事项 传播时钟是在进行了时钟树综合后&#xff0c;使用set_propagated_clock命令可以将一个理想时钟转换为传播时钟&#x…