使用Flask部署ppocr模型_3

PaddleOCR环境搭建、模型训练、推理、部署全流程(Ubuntu系统)_1_paddle 多进程推理-CSDN博客

PP-Structure 文档分析-CSDN博客

Pycharm的Terminal进入创建好的虚拟环境

有时候Pycharm的terminal中显示的是硬盘中的项目路径,但没有进入创建好的虚拟环境

这时候,在Pycharm>File>Tools>Terminal中切换powershell.exe为cmd.exe

接前两篇继续完成Flask部署

一、使用Flask部署ppocr模型

 GET方法用于从服务器获取资源,即客户端向服务器请求数据。POST方法用于向服务器提交数据,即客户端向服务器发送数据。

  1.  服务器:一般是指    http://127.0.0.1:5000
  2. 客户端:一般是指网页

点击提交按钮,会触发flask的post请求

目录结构

'static/images' 文件夹用来存放上传过来的图片

‘templates’文件夹下的两个html文件定义显示页面

templates这个文件在里面的作用:

在Flask框架中,templates文件夹是一个特定的目录,用于存放Web应用的HTML模板文件。这些模板文件使用Jinja2模板语言编写,允许开发者将动态内容(如从数据库获取的数据、用户输入、计算结果等)与静态HTML结构相结合,生成最终发送给客户端的HTML响应。

作用与特性

  1. 分离视图与逻辑

    • templates文件夹中的模板文件专注于呈现用户界面(UI),即HTML结构和样式。这使得视图层(UI设计)与业务逻辑(Python代码)得以分离,提高了代码的可维护性和复用性。
  2. 动态内容填充

    • 在模板文件中,可以使用Jinja2语法插入变量、控制结构(如条件语句、循环)、过滤器(对数据进行格式化)等。当Flask收到请求并渲染模板时,会将Python代码中传递的上下文数据(字典对象)与模板中的占位符匹配,动态生成包含具体数据的HTML页面。
  3. 继承与宏

    • templates文件夹中的模板可以互相继承,实现布局的复用。一个基础模板(如base.html)可以定义网站的通用结构(如头部、导航栏、页脚等),其他具体的页面模板(如index.htmlprofile.html等)则继承基础模板,并在其内部填充特定的内容区域。此外,Jinja2还支持定义和使用宏(类似于函数),封装重复使用的HTML片段。
  4. 组织结构

    • templates文件夹通常按照应用的结构进行组织,例如创建子目录来存放不同模块或蓝本(Blueprint)对应的模板。这种结构化方式有助于保持项目整洁,便于查找和管理相关模板。

工作流程

  1. 路由定义

    • 在Flask应用中,通过@app.route装饰器定义路由,如@app.route('/')表示处理根URL(http://example.com/)的请求。
  2. 视图函数

    • 对应路由的视图函数(如def index():)负责处理HTTP请求,执行必要的业务逻辑,并准备要传递给模板的数据(通常以字典形式)。
  3. 渲染模板

    • 视图函数调用render_template()函数,传入模板文件名(如'index.html')和上下文数据。Flask自动在templates文件夹中查找指定的模板,并使用Jinja2引擎渲染模板,将动态数据填充到相应的位置。
  4. 响应生成

    • 渲染后的HTML字符串作为HTTP响应的主体,发送回客户端(如浏览器),用户最终看到的就是根据模板动态生成的网页。

总之,templates文件夹在Flask应用中起着至关重要的作用,它承载了Web应用的用户界面设计,并通过Jinja2模板语言与应用的业务逻辑紧密协作,共同构建出丰富的动态Web页面

服务器程序——载入模型,命名app.py 

import numpy as np
from flask import Flask, request, jsonify, render_template
import pickle
 
app = Flask(__name__)
model = pickle.load(open('model.pkl','rb'))
 
@app.route('/')
def home():
    return render_template('page.html')
 
@app.route('/predict', methods=['POST'])
def predict():
    features_list = [float(x) for x in request.form.values()]
    features = np.array(features_list).reshape(1,-1)
    predict_outcome_list = model.predict(features)
    predict_outcome = round(predict_outcome_list[0],2)
 
    return render_template('page.html',prediction_display_area='预测价格为:{}'.format(predict_outcome))
 
if __name__ == "__main__":
    app.run(port=80,debug = True)

部署PaddleOCR(PP-OCR)模型到Flask应用中,通常包括以下几个步骤:

1、环境准备与模型获取

安装依赖:确保已经安装了Flask,以及PaddlePaddle(PaddleOCR的依赖库)

下载模型

(继续前两篇所以模型和环境不在重复)

2、创建Flask应用

        初始化Flask app:编写Python脚本,创建一个新的Flask应用实例。

from flask import Flask, request, jsonify

app = Flask(__name__)

        定义路由与处理函数:创建一个路由(如/predict),并编写对应的处理函数,该函数接收HTTP请求中的图像数据,调用PaddleOCR进行识别,并返回识别结果。

@app.route('/predict', methods=['POST'])
def ocr_predict():
    # 获取请求中的图像数据
    image_data = request.files.get('image')
    # 使用PaddleOCR进行识别
    result = ocr_api(image_data)
    # 返回JSON格式的结果
    return jsonify(result)

3、加载与封装PaddleOCR

        加载模型:在Flask应用中,使用PaddleOCR提供的API加载模型。指定模型路径和所需配置

from paddleocr import PaddleOCR

ocr = PaddleOCR(model_path='path/to/model', config_path='path/to/config.json')

        封装识别接口:创建一个名为ocr_api的函数,接受图像数据作为输入,使用加载的OCR对象进行识别,并处理返回结果。可能需要对图像数据进行预处理(如解码、缩放),然后调用OCR的ocr方法。

def ocr_api(image_data):
    img_bytes = image_data.read()
    img = cv2.imdecode(np.frombuffer(img_bytes, np.uint8), cv2.IMREAD_COLOR)
    results = ocr.ocr(img)
    # 对结果进行整理,例如提取文字和其坐标
    formatted_results = []
    for res in results:
        text, box, _ = res
        formatted_results.append({
            'text': text,
            'bbox': box.tolist()
        })
    return formatted_results

4、处理图像

        根据Flask接收到的HTTP请求类型(如multipart/form-data),解析上传的图像数据。上述示例中,假设图像通过名为image的字段以文件形式上传

5、配置运行参数:

        设置Flask应用的运行参数,如主机地址、端口、调试模式等。例如:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001, debug=True)

6、部署与测试
  • 启动Flask应用。在命令行中运行包含以上代码的Python脚本。
  • 使用HTTP客户端(如Postman)或编写简单的HTML表单,向http://localhost:5001/predict发送POST请求,附带上要识别的图像文件。检查响应是否包含预期的OCR识别结果

代码:

# 环境ppocr/001

import os
import subprocess
import shutil
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)


file = 'D:/GPT_1/ppocr_1/ppstructure/table/predict_table.py'
det_model = 'D:/GPT_1/ppocr_1/ppstructure/inference/ch_PP-OCRv3_det_infer'
rec_model = 'D:/GPT_1/ppocr_1/ppstructure/inference/ch_PP-OCRv3_rec_infer'
table_model = 'D:/GPT_1/ppocr_1/ppstructure/inference/ch_ppstructure_mobile_v2.0_SLANet_infer'
rec_dict = 'D:/GPT_1/ppocr_1/ppocr/utils/ppocr_keys_v1.txt'
table_dict = 'D:/GPT_1/ppocr_1/ppocr/utils/dict/table_structure_dict_ch.txt'
output = 'D:/GPT_1/ppocr_1/ppocrtable_Flask/static/output/table'


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in set(['bmp', 'jpg', 'JPG', 'png', 'PNG'])


@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')


@app.route('/Upload', methods=['POST', 'GET'])  # 添加路由
def classification():
    if request.method == 'POST':
        f = request.files['images']
        if not (f and allowed_file(f.filename)):
            return jsonify({"error": 1001, "msg": "only support image formats: .bmp .png .PNG .jpg .JPG"})

        basepath = os.path.dirname(__file__)  # 当前文件所在路径

        if os.path.exists('static/images/test.jpg'):
            os.remove('static/images/test.jpg')
            pass
        else:
            pass

        if os.path.exists('static/output/table'):
            shutil.rmtree('static/output/table')
            pass
        else:
            pass

        upload_path = os.path.join(basepath, 'static/images/test.jpg')  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径
        f.save(upload_path)
        f_name = f.filename

        # image = cv2.imread(upload_path)
        # image = image.astype(np.float32)
        # image_array = np.array(image)
        # input_data = np.expand_dims(image_array, axis=-0)

        cmd = ['python',
               '{}'.format(file),
               '--det_model_dir={}'.format(det_model),
               '--rec_model_dir={}'.format(rec_model),
               '--table_model_dir={}'.format(table_model),
               '--rec_char_dict_path={}'.format(rec_dict),
               '--table_char_dict_path={}'.format(table_dict),
               '--image_dir={}'.format(upload_path),
               '--output={}'.format(output)]

        # 使用Popen创建进程,并与进程进行复杂的交互
        proc = subprocess.Popen(
            cmd,  # cmd特定的查询空间的命令
            stdin=None,  # 标准输入 键盘
            stdout=subprocess.PIPE,  # -1 标准输出(演示器、终端) 保存到管道中以便进行操作
            stderr=subprocess.PIPE,  # 标准错误,保存到管道# #
        )
        outinfo, errinfo = proc.communicate()  # 获取输出和错误信息
        print('----------')
        print(outinfo)
        print(errinfo)
        print('-------')

        return render_template('return.html', info=outinfo.decode('utf-8'), img_name=f_name,
                               file_loc=os.getcwd() + '\static\output\\table\show.html')

    return render_template('index.html')


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

代码详解:

# 环境ppocr/001

import os
import subprocess
import shutil
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

# 除了output外其它写成绝对路径
# inference里的是自己训练好或官方的推理模型
file = '/home/sxj/GPT_1/ppocr_1/ppstructure/table/predict_table.py'
det_model = '/home/sxj/GPT_1/ppocr_1/ppstructure/inference/ch_PP-OCRv3_det_infer'
rec_model = '/home/sxj/GPT_1/ppocr_1/ppstructure/inference/ch_PP-OCRv3_rec_infer'
table_model = '/home/sxj/GPT_1/ppocr_1/ppstructure/inference/ch_ppstructure_mobile_v2.0_SLANet_infer'
rec_dict = '/home/sxj/GPT_1/ppocr_1/ppocr/utils/ppocr_keys_v1.txt'
table_dict = '/home/sxj/GPT_1/ppocr_1/ppocr/utils/dict/table_structure_dict_ch.txt'
output = '/home/sxj/GPT_1/ppocr_1/ppocrtable_Flask/static/output/table'

# file: PaddleOCR表格预测脚本的路径。
# det_model, rec_model, table_model: 用于文本检测、文本识别和表格结构识别的模型文件路径。
# rec_dict, table_dict: 文本识别和表格结构识别所需的字符字典文件路径。
# output: 应用运行时生成的输出文件(如表格识别结果)的保存目录

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in set(['bmp', 'jpg', 'JPG', 'png', 'PNG'])


@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

# 定义Flask路由,当访问应用根URL(http://localhost:5000/)时,调用index函数。该函数返回渲染后的index.html模板作为HTTP响应

@app.route('/Upload', methods=['POST', 'GET'])  # 添加路由
def classification():
    if request.method == 'POST':
        # 定义另一个Flask路由,当访问 / Upload
        # URL且请求方法为POST或GET时,调用classification函数。函数内部首先判断请求方法是否为POST,如果是,则执行上传图片和表格识别的逻辑;
        # 否则(即请求方法为GET时),返回渲染后的index.html模板。
        # 接下来是classification函数内部的POST请求处理逻辑:
        f = request.files['images']
        if not (f and allowed_file(f.filename)):
            return jsonify({"error": 1001, "msg": "only support image formats: .bmp .png .PNG .jpg .JPG"})

        # 从请求对象中获取上传的文件(假设表单字段名为images),并使用allowed_file函数检查文件格式。如果不满足条件,返回包含错误码和消息的JSON响应


        basepath = os.path.dirname(__file__)  # 当前文件所在路径

        if os.path.exists('static/images/test.jpg'):
            os.remove('static/images/test.jpg')
            pass
        else:
            pass

        if os.path.exists('static/output/table'):
            shutil.rmtree('static/output/table')
            pass
        else:
            pass
        # 获取当前文件(app.py)所在的路径,并在此基础上删除旧的测试图片和清理输出目录(如果存在)

        upload_path = os.path.join(basepath, 'static/images/test.jpg')  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径
        f.save(upload_path)
        f_name = f.filename
        # 将上传的图片保存到指定路径,并记录文件名

        # image = cv2.imread(upload_path)
        # image = image.astype(np.float32)
        # image_array = np.array(image)
        # input_data = np.expand_dims(image_array, axis=-0)

        cmd = ['python',
               '{}'.format(file),
               '--det_model_dir={}'.format(det_model),
               '--rec_model_dir={}'.format(rec_model),
               '--table_model_dir={}'.format(table_model),
               '--rec_char_dict_path={}'.format(rec_dict),
               '--table_char_dict_path={}'.format(table_dict),
               '--image_dir={}'.format(upload_path),
               '--output={}'.format(output)]
        # --det_model_dir = {}: 同样使用format()方法插入变量值。这里插入的是det_model变量
        # 这是一个命令行选项,告诉表格预测脚本使用指定的检测模型。
        # 格式化后为 - -output = / home / sxj / GPT_1 / ppocr_1 / ppocrtable_Flask / static / output / table,告诉脚本将识别结果保存到此目录。
        # 构造用于执行表格预测脚本的命令行参数列表

        # 使用Popen创建进程,并与进程进行复杂的交互
        proc = subprocess.Popen(
            cmd,  # cmd特定的查询空间的命令
            stdin=None,  # 标准输入 键盘
            stdout=subprocess.PIPE,  # -1 标准输出(演示器、终端) 保存到管道中以便进行操作
            stderr=subprocess.PIPE,  # 标准错误,保存到管道# #
        )
        outinfo, errinfo = proc.communicate()  # 获取输出和错误信息
        print('----------')
        print(outinfo)
        print(errinfo)
        print('-------')
        # 使用subprocess.Popen创建子进程,执行表格预测脚本,并通过管道获取子进程的输出和错误信息。打印这些信息以辅助调试

        return render_template('return.html', info=outinfo.decode('utf-8'), img_name=f_name,
                               file_loc=os.getcwd() + '\static\output\\table\show.html')
    # 在子进程执行成功后,返回渲染后的return.html模板作为HTTP响应,其中包含表格识别结果(info)、上传图片的文件名(img_name)以及输出文件(show.html)的相对路径

    return render_template('index.html')


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)
# 如果当前脚本作为主程序运行(而不是作为模块导入),则启动Flask应用。设置监听所有网络接口(host="0.0.0.0")、监听端口为5000(port=5000),并开启调试模式(debug=True)

接下来做内网穿透部署

内网穿透部署的主要作用是使得内网中的服务能够被外部用户访问,从而扩大了服务的覆盖范围。具体来说,它有以下几方面的应用:

  1. 远程办公与灵活性提升:通过内网穿透,员工可以在任何地方安全地访问公司的内部资源,如文件共享、内部网站、数据库等,从而提高了工作的灵活性和效率。
  2. 远程开发与调试:对于开发人员而言,内网穿透可以使其将本地开发环境暴露给外部网络,方便团队成员或客户远程访问和测试应用程序,从而加快开发周期和提高协作效率。
  3. 设备远程管理与控制:通过内网穿透,用户可以远程访问和管理路由器、摄像头、网络存储等设备,实现远程管理和控制。
  4. 数据远程同步与安全性保障:一些企业由于安全考虑,不愿将数据库放到云服务器上。内网穿透可以将数据库放在办公室本地,然后通过特定的传输通道实现数据的远程同步和访问,既保证了安全又保证了公网的正常访问。
  5. 搭建局域网服务器服务:内网穿透使得用户可以搭建FTP服务器、Web服务器等,并提供外网访问功能。
  6. 其他应用:内网穿透还可以用于远程监控设备的运行状况、实现远程联机游戏、文件远程共享等。

总的来说,内网穿透部署通过技术手段将内网中的服务暴露给外部网络,不仅扩大了服务的覆盖范围,还提高了工作效率和便利性,为远程办公、家庭安防、开发测试等提供了方便的解决方案

参考:内网穿透(详细且免费)部署(现已推出新的源码 搭建网站和云盘)_内网穿透服务器搭建-CSDN博客

参考:flask部署深度学习pytorch模型_flsak部署pytorch深度学习模型-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 开发实现登陆和注册模块

Python 开发实现登陆和注册模块 一、案例介绍 本例设计一个用户登录和注册模块,使用Tkinter框架构建界面,主要用到画布、文本框、按钮等组件。涉及知识点:Python Tkinter界面编程、pickle数据存储。本例实现了基本的用户登录和注册互动界面…

ic基础|时序篇:握手协议valid和ready的时序优化

大家好,我是数字小熊饼干,一个练习时长两年半的ic打工人。我在两年前通过自学跨行社招加入了IC行业。现在我打算将这两年的工作经验和当初面试时最常问的一些问题进行总结,并通过汇总成文章的形式进行输出,相信无论你是在职的还是…

网络安全的守护者:防火墙的五个主要功能解析

防火墙是一种网络安全设备,用于保护计算机网络免受未经授权的访问、攻击和恶意软件的侵害。它通过监控、过滤和控制网络流量,实施安全策略,防止不安全的数据包进入或离开受保护的网络。 防火墙的五个主要功能: 1. 访问控制&#…

Web入门-Tomecat

黑马程序员JavaWeb开发教程 文章目录 一、简介1、Web服务器2、Tomcat 二、基本使用三、入门程序解析 一、简介 1、Web服务器 对HTTP协议操作进行封装,简化web程序开发部署Web项目,对外提供网上信息浏览服务 2、Tomcat 概念:Tomcat是Apach…

(回溯)记忆化搜索和dp

动态规划的核心就是 状态的定义和状态的转移 灵神 的 回溯改递归思路 首先很多动态规划问题都可以采用 回溯 的思想 回溯主要思想就是把 一个大问题分解成小问题 比如 采用子集类回溯问题中的核心思想-> 选或不选 或者 选哪个 记忆化搜索之后 我们可以发现 每个新节点依…

深度图转点云

一、理论分析 二、其他分析 1、相机内参 相机内参主要是四个参数fx,fy,u0,v0。要明白相机内参就是相机内部参数,是参考像素坐标系而言,有了这个前提,这四个参数也就很好理解了。 (1)首先,。其中F是相机的…

sora related

官方https://openai.com/research/video-generation-models-as-world-simulators 概述: sora可以生成变长的、不同分辨率的最长可到1分钟的视频;整体流程是 v i d e o c o m p r e s s i o n n e r w o r k ( v i d e o → l a t e n t ) p a t c h i…

HarmonyOS ArkUI实战开发-NAPI数据类型

在前两篇文章里笔者简单介绍了 NAPI 工程结构以及生成的 cpp 源码部分,其中 JS 应用层传递过来的数据被封装在了 napi_value 中,使用前先要转换成对应的 C/C 数据类型,C/C 端的数据也要转换成 napi_value 数据类型传递给 JS 应用层&#xff0…

大模型改变了NLP的游戏规则了吗

NLP已经死了吗? 自从 ChatGPT 横空出世以来,自然语言处理(Natural Language Processing,NLP) 研究领域就出现了一种消极的声音,认为大模型技术导致 NLP “死了”。在某乎上就有一条热门问答,大…

mac上VMware fusion net模式无法正常使用的问题

更新时间:2024年04月22日21:39:04 1. 问题 环境: intel芯片的macbook pro VMware fusion 13.5.1 无法将“Ethernet0”连接到虚拟网络“/dev/vmnet8”。在这里显示这个之后,应该是vmnet8的网段发生了冲突,所以导致无法正常使用…

一篇文章带您了解操作系统的体系结构

操作系统的体系结构有哪些? 我们可以利用时钟中断实现计时功能。 原语是一种特殊的程序,具有原子性。也就是说,这段程序的运行必须一气呵成,不能中断。 内核是操作系统最基本,最核心的部分。 实现操作系统内核功能的…

Opencv Python图像处理笔记一:图像、窗口基本操作

文章目录 前言一、输入输出1.1 图片读取显示保存1.2 视频读取保存1.3 文件读取保存 二、GUI2.1 窗口2.2 轨迹条2.3 画图2.4 鼠标回调 三、图像入门操作3.1 颜色空间转化3.2 通道分离合并3.3 添加边框3.4 算数操作 四、二值化4.1 普通4.2 自适应4.3 Otsu 参考 前言 随着人工智能…

PS入门|蒙版到底是个什么样的功能?看完就明白了

前言 前段时间一直说蒙版蒙版什么的,很多小伙伴估计都听得一头雾水。 抠个图要加蒙版,调个色要加蒙版。 小白感觉这个蒙版就像调味剂一样,啥都需要加一个蒙版。 动不动就加个蒙版,究竟是干啥用的? 今天咱们就深入来…

【深度学习-第5篇】使用Python快速实现CNN分类(模式识别)任务,含一维、二维、三维数据演示案例(使用pytorch框架)

在之前的文章中介绍了CNN的图解入门,CNN的MATLAB分类实现,CNN的MATLAB回归实现。 卷积神经网络(Convolutional Neural Networ,简称CNN)是一种广泛应用于图像识别领域的深度学习算法。它通过模拟人类视觉系统的层次结构,可以自动提…

【linux】软件工具安装 + vim 和 gcc 使用(上)

目录 1. linux 安装软件途径 2. rzsz 命令 3. vim 和 gcc 使用 a. vim的基本概念 b. 命令模式下的指令 c. 底行模式下的指令 1. linux 安装软件途径 源代码安装rpm安装 -- linux安装包yum安装(最好,可以解决安装源,安装版本&#xff0…

实战 | 无视杀软使用远控工具进行横向移动Tips

实战 | 无视杀软使用远控工具进行横向移动Tips。 在有杀软拦截,CS无法上线的情况下,经常用到todesk和向日葵这两个远控工具进行横向移动。不过这两个工具现在好像不怎么好用了。不过无所谓,用其他的就是了,听说最近GotoHTTP很火&…

手拉手安装Kafka2.13发送和消费消息

Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。 Kafka启动方式有Zookeeper和Kraft,两种方式只能选择其中一种启动,不能同时使用。 Kafka下载https://downloads.apache.org/kafka/3.7.0/kafka_2.…

四川易点慧电子商务抖音小店:安全正规,购物新选择

在当今互联网高速发展的时代,电子商务已经成为人们日常购物的重要组成部分。四川易点慧电子商务抖音小店作为新兴的电商平台,凭借其安全正规的经营理念和便捷高效的购物体验,正逐渐赢得消费者的信赖和喜爱。 一、平台背景实力雄厚 四川易点慧…

【Linux系统化学习】线程控制

目录 前言 POSIX线程库 线程控制 创建线程 线程终止 pthread_exit()函数 pthread_cancel()函数(会在下面线程等待部分详解) 线程等待 pthread_join()函数 获取线程退出码 分离线程 线程取消(pthread_cancel()函数) 线程ID及进程…

Scikit-Learn支持向量机分类

Scikit-Learn 支持向量机分类 1、支持向量机(SVM)1.1、SVM概述1.2、SVM原理1.3、SVM的损失函数1.4、支持向量机分类的优缺点 2、Scikit-Learn支持向量机分类2.1、Scikit-Learn支持向量机分类API2.2、支持向量机分类初体验(手写数字识别&#…