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)

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

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

相关文章

ElementUI Table 翻页缓存数据

Element UI Table 翻页保存之前的数据,网上找了一些,大部分都是用**:row-key** 和 reserve-selection,但是我觉得有bug,我明明翻页了…但是全选的的个框还是勾着的(可能是使用方法不对,要是有好使的…请cute我一下…感谢) 所以自己写了一个… 思路: 手动勾选的时候,将数据保存…

UbuntuDDE 23.04发布,体验DeepinV23的一个新选择

UbuntuDDE 23.04发布,体验DeepinV23的一个新选择 昨晚网上搜索了一圈,无意看到邮箱一条新闻,UbuntuDDE 23.04发布了 因为前几天刚用虚拟机安装过,所以麻溜的从网站下载了ISO文件,安装上看看。本来没多想,…

QT connect使用简单介绍

如图,首先 connect是线程安全的。其次它有很多重载,当然最重要的还是QT4连接和QT5连接的区别,这个函数重载表示connect函数也是支持lambda函数的。 connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)connec…

在树莓派上搭建WordPress博客网站,并内网穿透发布到公网

目录 概述 安装 PHP 安装MySQL数据库 安装 WordPress 设置您的 WordPress 数据库 设置 MySQL/MariaDB 创建 WordPress 数据库 WordPress configuration 将WordPress站点发布到公网 安装相对URL插件 修改config.php配置 支持好友链接样式 定制主题 🎈个…

Python功能制作之简单的音乐播放器

需要导入的库: pip install PyQt5 源码: import os from PyQt5.QtCore import Qt, QUrl from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent from PyQt5.QtWidgets import QApplication, QMainWind…

【C++】unordered_map和unordered_set的使用 及 OJ练习

文章目录 前言1. unordered系列关联式容器2. map、set系列容器和unordered_map、unordered_set系列容器的区别3. unordered_map和unordered_set的使用4. set与unordered_set性能对比5. OJ练习5.1 在长度 2N 的数组中找出重复 N 次的元素思路分析AC代码 5.2 两个数组的交集思路分…

Linux 压缩解压(归档管理):tar命令

计算机中的数据经常需要备份,tar是Unix/Linux中最常用的备份工具,此命令可以把一系列文件归档到一个大文件中,也可以把档案文件解开以恢复数据。 tar使用格式 tar [参数] 打包文件名 文件 tar命令很特殊,其参数前面可以使用“-”&…

linux下系统问题排查基本套路

文章目录 总结常用命令原文GC相关网络TIME_WAITCLOSE_WAIT 总结常用命令 top 查找cpu占用高的进程ps 找到对应进程的pidtop -H -p pid 查找cpu利用率较高的线程printf ‘%x\n’ pid 将线程pid转换为16进制得到 nidjstack pid |grep ‘nid’ -C5 –color 在jstack中找到对应堆栈…

3D WEB轻量化引擎HOOPS产品助力NAPA打造船舶设计软件平台

NAPA(Naval Architectural PAckage,船舶建筑包),来自芬兰的船舶设计软件供应商,致力于提供世界领先的船舶设计、安全及运营的解决方案和数据分析服务。NAPA拥有超过30年的船舶设计经验,年营业额超过2560万欧…

镭速传输助力广电行业大数据高效分发,提升智慧融媒水平

随着互联网技术如大数据、人工智能、云计算等和移动通信技术如5G等的快速进步和实际应用,媒体行业发展正式进入智慧时代,智慧融媒成为媒体融合发展的新阶段,全面应用在超高清、云服务、融媒演播、VR等新兴技术为代表的各个方面。 以上技术的…

优思学院|公司质量的重要性与六西格玛的应用

在现代商业环境中,公司的成功与否往往取决于其产品或服务的质量水准。质量不仅是公司的一个重要组成部分,还直接影响着公司的声誉和消费者认可度。保持高质量的商品和服务有助于建立客户信任,维护品牌形象,并确保长期的业务增长。…

JavaWeb+JSP+SQL server学生学籍管理系统设计与实现(源代码+论文+开题报告+外文翻译+答辩PPT)

需求分析 本系统主要是针对各个高校的学生学籍进行管理,系统满足以下几点要求: 系统安全性。由于此系统中的操作都是由用户操作的,所以对于用户的权限设置比较严格。对于数据库,设置了不同用户的权限,不同权限进入不…

封装公共el-form表单(记录)

1.公共表单组件 //commonForm.vue <script> import {TEXT,SELECT,PASSWORD,TEXTAREA,RADIO,DATE_PICKER } from /conf/uiTypes import { deepClone } from /utils export default {name: GFormCreator,props: {config: { // title/itemstype: Object,required: true}}…

UE4/5Niagara粒子特效之Niagara_Particles官方案例:1.1->1.4

目录 1.1-Simple Sprite Emitter ​编辑 发射器更新 粒子生成 粒子更新 1.2-Simple Sprite Emitter 发射器更新 粒子生成 粒子更新 渲染 1.3-Simple GPU Emitter 属性 发射器更新 粒子生成 粒子更新 1.4-Sprite Facing 发射器更新 粒子生成 粒子更新 通过对官方…

wazuh初探系列二 :Wazuh功能初步探知

目录 介绍 主动响应&#xff1a; 监控日志 "bin"目录用途&#xff1a; 告警信息&#xff1a; etc 目录中包含了以下主要的配置文件&#xff1a; ruleset&#xff1a;自带规则库&#xff0c;建议不改 rules目录: 解码器&#xff1a; 登录日志格式&#xff1a…

财务数据分析模板有哪些,能满足决策吗?

虽然企业的业务经营各有不同&#xff0c;但在财务数据分析上却有着相似的需求与流程&#xff0c;因此财务数据分析是可以形成一套标准化模板的。奥威BI数据可视化工具从多年丰富的BI项目中总结经验&#xff0c;形成一套标准化、系统化的财务数据分析模板&#xff0c;内含资产负…

CentOS中Oracle11g进程有哪些

最近遇到Oracle数据库运行过程实例进程由于某种原因导致中止的问题&#xff0c;专门看了下正常Oracle数据库启动后的进程有哪些&#xff0c;查阅资料了解了下各进程的作用&#xff0c;记录如下。 oracle 3032 1 0 07:36 ? 00:00:00 ora_pmon_orcl oracle …

最优的家电设备交互方式是什么?详解家电设备交互的演进之旅

家电&#xff0c;在人们的日常生活中扮演着不可或缺的角色&#xff0c;也是提升人们幸福感的重要组成部分&#xff0c;那你了解家电的发展史吗&#xff1f; 70年代 结婚流行“四大件”&#xff1a;手表、自行车、缝纫机&#xff0c;收音机&#xff0c;合成“三转一响”。 80年…

git 回滚相关问题

原本用as自带的git执行回滚任务&#xff0c; 但是提交之后发现并没有成功&#xff0c; 后面通过命令行的方式重新回滚并且提交上去&#xff0c;就可以了 说明as的git还是有点小瑕疵&#xff0c;还是命令行最稳妥 相关博文&#xff1a; git代码回滚操作_imkaifan的博客-CSDN博…

网络安全(大厂)面试题

以下为网络安全各个方向涉及的面试题&#xff0c;星数越多代表问题出现的几率越大&#xff0c;祝各位都能找到满意的工作。 注&#xff1a;本套面试题&#xff0c;已整理成pdf文档&#xff0c;但内容还在持续更新中&#xff0c;因为无论如何都不可能覆盖所有的面试问题&#xf…