当前位置: 首页 > news >正文

fastdeploy部署多线程/进程paddle ocr(python flask框架 )

部署参考:https://github.com/PaddlePaddle/FastDeploy/blob/develop/tutorials/multi_thread/python/pipeline/README_CN.md

安装
cpu: pip install fastdeploy-python

gpu :pip install fastdeploy-gpu-python

#下载部署示例代码
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd  FastDeploy/tutorials/multi_thread/python/pipeline# 下载模型,图片和字典文件
wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar
tar xvf ch_PP-OCRv3_det_infer.tarwget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar
tar -xvf ch_ppocr_mobile_v2.0_cls_infer.tarwget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar
tar xvf ch_PP-OCRv3_rec_infer.tarwget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/doc/imgs/12.jpgwget https://gitee.com/paddlepaddle/PaddleOCR/raw/release/2.6/ppocr/utils/ppocr_keys_v1.txt

命令:
多线程

python multi_thread_process_ocr.py --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image_path xxx/xxx --device gpu --thread_num 3

多进程

python multi_thread_process_ocr.py --det_model ch_PP-OCRv3_det_infer --cls_model ch_ppocr_mobile_v2.0_cls_infer --rec_model ch_PP-OCRv3_rec_infer --rec_label_file ppocr_keys_v1.txt --image_path xxx/xxx --device gpu --use_multi_process True --process_num 3

问题

多进程图片分配有bug

文件:multi_thread_process_ocr.py
原始代码:270行
在这里插入图片描述

修改为如下,去掉1
在这里插入图片描述

ModuleNotFoundError: No module named ‘example’

因为安装包不对,fastdeploy与fastdeploy-python不是同一个包

CUDA error(3), initialization error.

  ----------------------Error Message Summary:----------------------ExternalError: CUDA error(3), initialization error. [Hint: Please search for the error code(3) on website (https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__TYPES.html#group__CUDART__TYPES_1g3f51e3575c2178246db0a94a430e0038) to get Nvidia's official solution and advice about CUDA Error.] (at /home/fastdeploy/develop/paddle_build/v0.0.0/Paddle/paddle/phi/backends/gpu/cuda/cuda_info.cc:251)

参考:
PaddlePaddle——问题解决:使用Python multiprocessing时报错:CUDA error(3), initialization error.
https://github.com/PaddlePaddle/PaddleDetection/issues/2241
paddle 相关模块只在方法里面引用,要在多进程外有 import 这些模块

flask部署

发送列表类型的图片base64编码,返回列表类型的字符串

注意server端文件放在FastDeploy/tutorials/multi_thread/python/pipeline目录下
创建server端

from threading import Threadimport cv2
import os
from multiprocessing import Pool
import sysimport fastdeploy as fd
import numpy as np
import base64
from PIL import Image
from io import BytesIO
from sqlalchemy import create_engine, textfrom flask import Flask, request, jsonify
import argparse
import ast# watch -n 0.1 nvidia-smidef parse_arguments():parser = argparse.ArgumentParser()parser.add_argument("--det_model",# required=True,type=str,default='ch_PP-OCRv3_det_infer',help="Path of Detection model of PPOCR.")parser.add_argument("--cls_model",# required=True,type=str,default='ch_ppocr_mobile_v2.0_cls_infer',help="Path of Classification model of PPOCR.")parser.add_argument("--rec_model",# required=True,type=str,default='ch_PP-OCRv3_rec_infer',help="Path of Recognization model of PPOCR.")parser.add_argument("--rec_label_file",# required=True,type=str,default='ppocr_keys_v1.txt',help="Path of Recognization model of PPOCR.")# parser.add_argument(#     "--image_path",#     type=str,#     required=True,#     help="The directory or path or file list of the images to be predicted."# )parser.add_argument("--device",type=str,default='gpu', # cpuhelp="Type of inference device, support 'cpu', 'kunlunxin' or 'gpu'.")parser.add_argument("--backend",type=str,default="default",help="Type of inference backend, support ort/trt/paddle/openvino, default 'openvino' for cpu, 'tensorrt' for gpu")parser.add_argument("--device_id",type=int,default=0,help="Define which GPU card used to run model.")parser.add_argument("--cpu_thread_num",type=int,default=9,help="Number of threads while inference on CPU.")parser.add_argument("--cls_bs",type=int,default=1,help="Classification model inference batch size.")parser.add_argument("--rec_bs",type=int,default=6,help="Recognition model inference batch size")parser.add_argument("--thread_num", type=int, default=1, help="thread num")parser.add_argument("--use_multi_process",type=ast.literal_eval,default=True,help="Wether to use multi process.")parser.add_argument("--process_num", type=int, default=5, help="process num")return parser.parse_args()def get_image_list(image_path):image_list = []if os.path.isfile(image_path):image_list.append(image_path)# load image in a directoryelif os.path.isdir(image_path):for root, dirs, files in os.walk(image_path):for f in files:image_list.append(os.path.join(root, f))else:raise FileNotFoundError('{} is not found. it should be a path of image, or a directory including images.'.format(image_path))if len(image_list) == 0:raise RuntimeError('There are not image file in `--image_path`={}'.format(image_path))return image_listdef build_option(args):option = fd.RuntimeOption()if args.device.lower() == "gpu":option.use_gpu(args.device_id)option.set_cpu_thread_num(args.cpu_thread_num)if args.device.lower() == "kunlunxin":option.use_kunlunxin()return optionif args.backend.lower() == "trt":assert args.device.lower() == "gpu", "TensorRT backend require inference on device GPU."option.use_trt_backend()elif args.backend.lower() == "pptrt":assert args.device.lower() == "gpu", "Paddle-TensorRT backend require inference on device GPU."option.use_trt_backend()option.enable_paddle_trt_collect_shape()option.enable_paddle_to_trt()elif args.backend.lower() == "ort":option.use_ort_backend()elif args.backend.lower() == "paddle":option.use_paddle_infer_backend()elif args.backend.lower() == "openvino":assert args.device.lower() == "cpu", "OpenVINO backend require inference on device CPU."option.use_openvino_backend()return optiondef load_model(args, runtime_option):# Detection模型, 检测文字框det_model_file = os.path.join(args.det_model, "inference.pdmodel")det_params_file = os.path.join(args.det_model, "inference.pdiparams")# Classification模型,方向分类,可选cls_model_file = os.path.join(args.cls_model, "inference.pdmodel")cls_params_file = os.path.join(args.cls_model, "inference.pdiparams")# Recognition模型,文字识别模型rec_model_file = os.path.join(args.rec_model, "inference.pdmodel")rec_params_file = os.path.join(args.rec_model, "inference.pdiparams")rec_label_file = args.rec_label_file# PPOCR的cls和rec模型现在已经支持推理一个Batch的数据# 定义下面两个变量后, 可用于设置trt输入shape, 并在PPOCR模型初始化后, 完成Batch推理设置cls_batch_size = 1rec_batch_size = 6# 当使用TRT时,分别给三个模型的runtime设置动态shape,并完成模型的创建.# 注意: 需要在检测模型创建完成后,再设置分类模型的动态输入并创建分类模型, 识别模型同理.# 如果用户想要自己改动检测模型的输入shape, 我们建议用户把检测模型的长和高设置为32的倍数.det_option = runtime_optiondet_option.set_trt_input_shape("x", [1, 3, 64, 64], [1, 3, 640, 640],[1, 3, 960, 960])# 用户可以把TRT引擎文件保存至本地#det_option.set_trt_cache_file(args.det_model  + "/det_trt_cache.trt")global det_modeldet_model = fd.vision.ocr.DBDetector(det_model_file, det_params_file, runtime_option=det_option)cls_option = runtime_optioncls_option.set_trt_input_shape("x", [1, 3, 48, 10],[cls_batch_size, 3, 48, 320],[cls_batch_size, 3, 48, 1024])# 用户可以把TRT引擎文件保存至本地# cls_option.set_trt_cache_file(args.cls_model  + "/cls_trt_cache.trt")global cls_modelcls_model = fd.vision.ocr.Classifier(cls_model_file, cls_params_file, runtime_option=cls_option)rec_option = runtime_optionrec_option.set_trt_input_shape("x", [1, 3, 48, 10],[rec_batch_size, 3, 48, 320],[rec_batch_size, 3, 48, 2304])# 用户可以把TRT引擎文件保存至本地#rec_option.set_trt_cache_file(args.rec_model  + "/rec_trt_cache.trt")global rec_modelrec_model = fd.vision.ocr.Recognizer(rec_model_file,rec_params_file,rec_label_file,runtime_option=rec_option)# 创建PP-OCR,串联3个模型,其中cls_model可选,如无需求,可设置为Noneglobal ppocr_v3ppocr_v3 = fd.vision.ocr.PPOCRv3(det_model=det_model, cls_model=cls_model, rec_model=rec_model)# 给cls和rec模型设置推理时的batch size# 此值能为-1, 和1到正无穷# 当此值为-1时, cls和rec模型的batch size将默认和det模型检测出的框的数量相同ppocr_v3.cls_batch_size = cls_batch_sizeppocr_v3.rec_batch_size = rec_batch_sizedef predict(model, img_list):result_list = []# predict ppocr resultfor image in img_list:im = cv2.imread(image)result = model.predict(im)result_list.append(result)return result_listdef process_predict(image):# predict ppocr resultim = cv2.imread(image)result = ppocr_v3.predict(im)print(result)def process_predict_text(base64_str):image = base64_to_bgr(base64_str)result = ppocr_v3.predict(image)# print(result)return ''.join(result.text) #不能直接返回OCR对象序列化会失败def cv_show(img):'''展示图片@param img:@param name:@return:'''cv2.namedWindow('name', cv2.WINDOW_KEEPRATIO)  # cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIOcv2.imshow('name', img)cv2.waitKey(0)cv2.destroyAllWindows()def base64_to_bgr(base64_str):base64_hex = base64.b64decode(base64_str)image = BytesIO(base64_hex)img = Image.open(image)if img.mode=='RGBA':width = img.widthheight = img.heightimg2 = Image.new('RGB', size=(width, height), color=(255, 255, 255))img2.paste(img, (0, 0), mask=img)image_array = np.array(img2)else:image_array = np.array(img)image = cv2.cvtColor(image_array, cv2.COLOR_RGB2BGR)return imageclass WrapperThread(Thread):def __init__(self, func, args):super(WrapperThread, self).__init__()self.func = funcself.args = args# self.result = self.func(*self.args)def run(self):self.result = self.func(*self.args)def get_result(self):return self.resultdef ocr_image_list(imgs_list):args = parse_arguments()# 对于三个模型,均采用同样的部署配置# 用户也可根据自行需求分别配置runtime_option = build_option(args)if args.use_multi_process:process_num = args.process_numwith Pool(process_num,initializer=load_model,initargs=(args, runtime_option)) as pool:#results = pool.map(process_predict_text, imgs_list)# pool.map(process_predict, imgs_list)# 进一步处理结果for i, result in enumerate(results):print(i, result)else:load_model(args, runtime_option)threads = []thread_num = args.thread_numimage_num_each_thread = int(len(imgs_list) / thread_num)# unless you want independent model in each thread, actually model.clone()# is the same as model when creating thead because of the existence of# GIL(Global Interpreter Lock) in python. In addition, model.clone() will consume# additional memory to store independent member variablesfor i in range(thread_num):if i == thread_num - 1:t = WrapperThread(predict,args=(ppocr_v3.clone(),imgs_list[i * image_num_each_thread:]))else:t = WrapperThread(predict,args=(ppocr_v3.clone(),imgs_list[i * image_num_each_thread:(i + 1) *image_num_each_thread]))  # - 1threads.append(t)t.start()for i in range(thread_num):threads[i].join()for i in range(thread_num):for result in threads[i].get_result():print('thread:', i, ', result: ', result)@app.route('/ocr/submit', methods=['POST'])
def ocr():args = parse_arguments()process_num = 1#args.process_numruntime_option = build_option(args)data = request.get_json()# 获取 Base64 数据base64_str = data['img_base64']with Pool(process_num, initializer=load_model, initargs=(args, runtime_option)) as pool:results = pool.map(process_predict_text, base64_str)# 返回响应response = {'message': 'Data received', 'result': results}return jsonify(response)import json
import pandas as pd
import timeif __name__ == '__main__':app.run(host='192.168.xxx.xxx', port=5000)

client 端

import base64
import sysimport requests
import json
# 读取图像文件
with open('./pic/img.png', 'rb') as image_file:# 将图像文件内容读取为字节流image_data = image_file.read()# 将图像字节流进行 Base64 编码
img_base64 = base64.b64encode(image_data)data = {'img_base64': [img_base64.decode('utf-8')] }headers = {'Content-Type': 'application/json'
}response = requests.post("http://192.168.xxx.xxx:5000/ocr/submit",  data=json.dumps(data),headers = headers)if response.status_code == 200:result = response.json()print(result['result'])
else:print('Error:', response.status_code)

相关文章:

fastdeploy部署多线程/进程paddle ocr(python flask框架 )

部署参考:https://github.com/PaddlePaddle/FastDeploy/blob/develop/tutorials/multi_thread/python/pipeline/README_CN.md 安装 cpu: pip install fastdeploy-python gpu :pip install fastdeploy-gpu-python #下载部署示例代码 git cl…...

【图论】拓扑排序

一.定义 拓扑排序是一种对有向无环图(DAG)进行排序的算法,使得图中的每个顶点在排序中都位于其依赖的顶点之后。它通常用于表示一些任务之间的依赖关系,例如在一个项目中,某些任务必须在其他任务之前完成。 拓扑排序的…...

自动化备份方案

背景说明 网上有很多教程,写的都是从零搭建一个什么什么,基本上都是从无到有的教程,但是,很少有文章提及搭建好之后如何备份,这次通过请教GitHub Copilot Chat,生成几个备份脚本,以备后用。 注…...

win11出现安全中心空白和IT管理员已限制对此应用的某些区域的访问

问题 windows安全中心服务被禁用 winr 输入services.msc 找到windows安全中心服务查看是否被禁用,改为启动,不可以改动看第三条 打开设置,找到应用—windows安全中心–终止–修复–重置 重启如果还是不行看第四条 家庭版系统需要打开gped…...

github实用指令(实验室打工人入门必备)

​​​​​​​​博主进入实验室啦,作为一只手残党决定在这里分享一些常用的github使用情景和操作指南来解救其他手残党。 内容随着情景增加实时更新。如果只有没几个内容说明场景不多(相信对手残党而言是再好不过的消息) 情景一&#xff1a…...

6. 激活层

6.1 非线性激活 ① inplace为原地替换,若为True,则变量的值被替换。若为False,则会创建一个新变量,将函数处理后的值赋值给新变量,原始变量的值没有修改。 import torch from torch import nn from torch.nn import …...

AIGC ChatGPT 制作地图可视化分析

地图可视化分析是一种将数据通过地图的形式进行展示的方法,可以让人们更加直观、快速、准确的理解和分析数据。以下是地图可视化分析的一些主要好处: 加强数据理解:地图可视化可以将抽象的数字转化为直观的图形,帮助我们更好地理解复杂的数据集。 揭示地理模式:地理位置是…...

2023-08-24 LeetCode每日一题(统计参与通信的服务器)

2023-08-24每日一题 一、题目编号 1267. 统计参与通信的服务器二、题目链接 点击跳转到题目位置 三、题目描述 这里有一幅服务器分布图,服务器的位置标识在 m * n 的整数矩阵网格 grid 中,1 表示单元格上有服务器,0 表示没有。 如果两台…...

前端实习day35

今天是下早班的一天,下完班直接赶车回广州了,吐槽一下深圳站管理得真得差,候车厅小,人巨多,而且进站口的标识也很少,绕了好久才找到!下次再也不去了。 今天是改bug的一天,但是有半天…...

Linux安装jupyter notebook

1. Linux安装jupyter notebook 1.1 生成配置文件 这里在conda环境中安装。 jupyter notebook --generate-config --allow-root上面命令是生成配置文件,并且允许使用root用户运行。配置文件默认生成到~/.jupyter/jupyter_notebook_config.py。 具体解释如下&…...

【猿灰灰赠书活动 - 03期】- 【RHCSA/RHCE 红帽Linux认证学习指南(第7版) EX200 EX300】

说明:博文为大家争取福利,与清华大学出版社合作进行送书活动 图书:《RHCSA/RHCE 红帽Linux认证学习指南(第7版) EX200 & EX300》 一、好书推荐 图书介绍 《RHCSA/RHCE 红帽Linux认证学习指南(第7版) EX200 & E…...

当 Tubi 遇到 Ruby

有人说 Tubi 作为 RubyConf China 金牌赞助商,明明用极具吸引力的 Elixir 后端工程师岗位和高品质的 Elixir Meetup,“拐走了”一批又一批 Rubyist 投身于 Elixir 开发中,却依然让人想在 Tubi 展台前多停留一会儿。 为什么工程师、校友甚至 …...

【C++从0到王者】第二十四站:多态的底层原理

文章目录 前言一、虚函数表二、一道经典的例题三、深度剖析多态的条件之一:为什么必须是父类的指针或引用四、深度剖析多态的条件之二:为什么是虚函数的重写/覆盖?五、虚函数表的一些总结六、关于Func3的验证七、动态绑定与静态绑定八、总结 …...

Java从入门到精通24==》数据库、SQL基本语句、DDL语句

Java从入门到精通24》数据库、SQL基本语句、DDL语句 2023.8.27 文章目录 <center>Java从入门到精通24》数据库、SQL基本语句、DDL语句一、什么是数据库二、数据库的优缺点1、使用数据库的优点&#xff1a;2、使用数据库的缺点&#xff1a; 三、MySQL基本语句四、DDL语句 …...

学习ts(十)装饰器

定义 装饰器是一种特殊类型的声明&#xff0c;它能够被附加到类声明&#xff0c;方法&#xff0c;访问符&#xff0c;属性或参数上&#xff0c;是一种在不改变原类和使用继承的情况下&#xff0c;动态的扩展对象功能。 装饰器使用expression形式&#xff0c;其中expression必须…...

如何在 Opera 中启用DNS over HTTPS

DNS over HTTPS&#xff08;基于HTTPS的DNS&#xff09;是一种更安全的浏览方式&#xff0c;但大多数 Web 浏览器默认情况下不启用它。了解如何在 Opera 浏览器中启用该功能。 您可能不知道这一点&#xff0c;但您的网络浏览器并不像您希望的那样私密或安全。您会看到&#xff…...

STM32 F103C8T6学习笔记13:IIC通信—AHT10温湿度传感器模块

今日学习一下这款AHT10 温湿度传感器模块&#xff0c;给我的OLED手环添加上测温湿度的功能。 文章提供源码、测试工程下载、测试效果图。 目录 AHT10温湿度传感器&#xff1a; 特性&#xff1a; 连接方式&#xff1a; 适用场所范围&#xff1a; 程序设计&#xff1a; 设…...

QT基础使用:组件和代码关联(信号和槽)

自动关联 ui文件在设计环境下&#xff0c;能看到的组件可以使用鼠标右键选择“转到槽”就是开始组件和动作关联。 在自动关联这个过程中软件自动动作的部分 需要对前面头文件进行保存&#xff0c;才能使得声明的函数能够使用。为了方便&#xff0c;自动关联时先对所有文件…...

TCP最大连接数问题总结

最大TCP连接数量限制有&#xff1a;可用端口号数量、文件描述符数量、线程、内存、CPU等。每个TCP连接都需要以下资源&#xff0c;如图所示&#xff1a; 1、可用端口号限制 Q&#xff1a;一台主机可以有多少端口号&#xff1f;端口号与TCP连接&#xff1f;是否能修改&#x…...

【Docker】云原生利用Docker确保环境安全、部署的安全性、安全问题的主要表现和新兴技术产生

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 云原生利用Docker确保环境安全、部署的…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...