当前位置:   article > 正文

使用flask将paddleocr车牌检测模型部署到服务器上_ocr车牌识别服务器的搭建

ocr车牌识别服务器的搭建

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近,需要写一个程序把PaddleOcr的车牌检测模型部署到服务器上,写成接口的形式,方便他人调用。经过1个星期的努力,终于实现基本功能。因为是第一次接触,所以踩了很多弯路,当然,网上很多教程做的都非常不错,但是对于零基础的我来说,有一点难理解,所以我采用了自己能理解的方式写了一个简单的demo,然后简单记录一下flask部署paddleocr车牌号检测模型。方便后续我自己学习。
————————————————
版权声明:本文为CSDN博主「raya」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44902604/article/details/130085119


提示:以下是本篇文章正文内容,下面案例可供参考

一、为什么要学习Flask

深度学习模型不仅仅是停留在研究的阶段,最终目的是应用到实际场景中。为了能够在使用过程中方便地调用模型,我们可以将这些模型封装成为一个 Web 服务,允许客户端通过接口发送请求,进行模型推理,并获取返回结果。也就是我们平常所说的将模型部署到服务器上,然后使用 Flask 进行开发和管理。
通过使用 Flask 来部署模型,我们可以轻松地搭建 Web 服务并提供自定义接口,将深度学习模型应用到实际场景中。通过请求处理和响应处理两个步骤,我们可以将模型的输入和输出数据转换为 HTTP 请求和 HTTP 响应,并通过网络进行交互,使得模型能够被其他应用程序和客户端方便地调用和使用。

二、Flask是什么?

Flask 是一个python编写的Web微框架,让我们可以使用Python语言快速实现一个网站或Web服务。(百度搜的答案)
深度学习模型部署为一个 Web 服务,我们可以充分利用 Flask 框架的功能和特性。Flask 提供了一个轻量级的 Web 开发框架,使我们能够快速地构建和管理 Web 应用程序。我们可以将模型封装在 Flask 应用程序中,通过定义路由和视图函数,将模型的推理过程与特定的请求端点关联起来。这样,客户端可以通过发送请求到服务器的特定端点,触发模型的推理过程,并从响应中获取模型的预测结果。
使用 Flask 进行模型部署和调用,具有以下优势:

  • 方便快捷:Flask 提供了简单易用的 API,使得开发和部署模型变得轻松。
  • 可扩展性:通过使用 Flask 的扩展插件和组件,我们可以增加功能,如身份验证、数据格式转换等,灵活地满足各种需求。
  • 跨平台:由于基于 HTTP 协议进行通信,Flask 部署的模型可以被各种客户端(如 Web、移动应用)访问,使得模型的应用范围更广。
  • 可维护性:Flask 的结构清晰,易于理解和维护,使得团队成员可以协作开发和维护模型的部署代码。
    总之,通过将深度学习模型封装为一个基于 Flask 的 Web 服务,我们可以轻松地部署和调用模型,实现模型的落地应用,满足实际需求。

三、使用步骤

将深度学习模型部署为 Web 服务通常需要经过以下两个步骤:

  1. 接收 HTTP 请求
    在这一步中,我们需要使用 Flask 的 flask.request 模块来接收客户端发送的 HTTP 请求,并提取请求参数。这通常涉及到解析 URL、查询字符串和 POST 数据等,以及对数据格式进行验证和转换。通过使用 Flask 的请求处理机制,我们可以将接收到的请求发送给下一个步骤,进行模型预测。
  2. 响应 HTTP 请求
    在这一步中,我们需要使用 Flask 的 flask.Response 模块将预测结果封装成 HTTP 响应,并将其发送回客户端。这通常涉及到定义 HTTP 状态码、响应头和响应体等,以及将响应数据转换为 JSON 或其他数据格式。通过使用 Flask 的响应处理机制,我们可以将模型预测结果返回给客户端,并告知客户端请求状态和错误信息等。

1.安装

首先你可以先判断一下自己有没有flask,可以使用如下命令

pip show flask
  • 1

如果没有安装的,可以使用如下命令

pip install flask
  • 1

2.创建flask应用程序(构建API接口)

  1. 导入 Flask 模块:首先,需要导入 Flask 模块,以便我们可以使用其中提供的功能和方法
 from flask import Flask
  • 1
  1. 创建 Flask 应用对象:使用 Flask 类,创建一个 Flask 应用对象,该对象将用于处理所有的请求和响应。
 app = Flask(__name__)
  • 1
  1. 定义路由和视图函数:在 Flask 应用对象上使用装饰器(@app.route)来定义路由,将指定的 URL 地址和相应的视图函数进行关联。在下述示例中,我们定义了一个 /ocr 的路由,并将其关联到名为 ocr的视图函数上。通俗的解释一下:
# methods: 指定请求方式,get 也行
 @app.route('/ocr', methods=['POST')
 def predict():
    # 处理请求和返回响应的逻辑
    # 请求方式为post时,可以使用 request.get_json()接收到JSON数据
    data = request.get_json()  # 获取 POST 请求中的 JSON 数据
    # 如果得到的data是字符串格式,则需要用json.loads来变换成python格式
     # data = json.loads(data)
    
    # 处理数据
    # 调用do_something_with_data函数来处理接收到的数据。
    processed_data = do_something_with_data(data)

    # 请求方得到处理后的数据
    return jsonify(processed_data)
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  1. 启动应用程序:最后,需要在代码的末尾添加一个条件判断,确保应用程序在直接运行脚本的情况下才会启动。(app.run()里有很多参数)
    app.run() 方法会启动 Flask 应用程序,监听指定的 IP 地址和端口号,并开始接收客户端的请求。
    host: 服务器监听的主机名或 IP 地址,默认为 127.0.0.1,即本地回环地址。
    port: 服务器监听的端口号,默认为 5000。
    debug: 是否启用调试模式,默认为 False。调试模式下,Flask 会自动重载代码、打印详细的错误信息等,方便开发和调试。
    threaded: 是否开启多线程模式,开启后可以提高服务器的并发处理能力,默认为 True。
    options: 其它选项,如 SSL/TLS 配置等。
    processes: 指定启动的进程数,用于多进程模式,默认为 1。
    ssl_context: 用于配置 SSL/TLS 加密连接的上下文,用于启用 HTTPS,默认为 None。
 if __name__ == '__main__':
     app.run(host='0.0.0.0', port=5000)
  • 1
  • 2
  1. 将自己模型算法集成到上述的四个步骤中,得到如下的一个flask应用程序(创建我自己模型的API)
    PS:paddleocr 的推理命令为:python tools/infer/predict_system.py 我就直接从predict_system.py文件中拿的方法直接用的。
import json
from flask import Flask, request, jsonify
import re
import infer.utility as utility
from infer.predict_system import TextSystem
import numpy as np
from infer.utility import draw_ocr_box_txt
import cv2
import os
import base64
import io
from PIL import Image
app = Flask(__name__)
args = utility.parse_args()
text_sys = TextSystem(args) # TextSystem这个是PaddleOcr中预测车牌号的模型
draw_img_save_dir = args.draw_img_save_dir

@app.route('/test', methods=['GET'])  #这个是用来做测试,demo的,看看定义视图和路由函数的
def test_api():
    return "success"

#这里是我的主要功能,因为请求的时候,给我传的是图像的数据流,所以前几行代码需要做一些预处理。后面request 会有详细的描写
@app.route('/ocr', methods=['POST'])  #这里是我的主要功能,因为请求的时候,给我传的是图像的数据流,所以前几行代码需要做一些预处理。
def ocr_api():
     # 解析 JSON 数据
    params = json.loads(request.data)
    # 收集所有图像的结果
    images_results = []
     # 遍历所有的图像数据流
    for base64_image_data in params['images_data']:
        # base64解码
        image_data = base64.b64decode(base64_image_data)
        # 使用 NumPy 创建一个数组
        image_np_array = np.frombuffer(image_data, np.uint8)
        # 使用 OpenCV 的 imdecode 函数将其转换成图像格式
        image = cv2.imdecode(image_np_array, cv2.IMREAD_COLOR,)  # flags可以指定加载图像的颜色空间,IMREAD_COLOR 表示加载一个彩色图像,默认读取格式为BGR
        # 将BGR转换为RGB
        image_RGB = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
        dt_boxes, rec_res, _ = text_sys(image)
        plates = []
        for text, _ in rec_res:
            text = text.replace('·','')#去除·
            plate_regex = r'[\u4e00-\u9fa5][A-Z].*'
            plates.append(re.findall(plate_regex,text))
            # plates = re.findall(plate_regex,text)
        txts = [rec_res[i][0] for i in range(len(rec_res))]
        scores = [rec_res[i][1] for i in range(len(rec_res))]
        # 绘制框
        draw_img = draw_ocr_box_txt(
            image_RGB,
            dt_boxes,
            txts,
            scores,
            drop_score=0.5,
            font_path="./doc/fonts/simfang.ttf")
        # 如果 draw_img 为PIL图像,将其转换为NumPy数组,颜色通道为RGB
        draw_img_cv2 = cv2.cvtColor(np.array(draw_img), cv2.COLOR_RGB2BGR)

        # 转换为base64数据流
        _, buffer = cv2.imencode('.jpg', draw_img_cv2)
        base64_image = base64.b64encode(buffer).decode('utf-8')
        # 现在 base64_image 包含处理后图像的base64编码数据流
        # 将处理结果添加到 images_results
        images_results.append({
         "results_rec": plates,
         "show_image": base64_image,
        })
    return jsonify({
     "images_results": images_results,
    "status": "success"
        }), 200    
        
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5003)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  1. 运行这个服务,假设这个文件名为app.py
python app.py
  • 1

会有如下结果:说明服务已经起来了,下一步,尝试访问这个接口。
在这里插入图片描述

3.请求该接口

使用 POSTman 或 curl 都可以测试模型部署的 API 接口,这里主要使用 requests 的 Python 库来编写发送请求的代码。

  1. 首先,确保已经在 Python 环境中安装了 requests 库。可以使用以下命令进行安装:
pip install requests
  • 1
  1. 在代码中导入 requests 库
import requests
  • 1
  1. 定义要访问的接口 URL
    运行python app.py后控制台上会出现一个网址以及对应的端口号,然后把刚才定义的路由:ocr家加在后面进行访问。
url = 'http://xx.xxx.xxx.xx:5000/ocr'
  • 1
  1. 准备要发送的数据

在这个例子中,我们使用了两个特征作为请求的数据,具体根据接口定义来修改。

data = {'param1': 'value1', 'param2': 'value2'}
  • 1

这里要注意的是,这里data 定义的两个特征,在上面封装接口的 predict 函数中,使用 request.json.get() 方法从请求中提取参数值。要求参数的名称与示例中的data字典中的键名相同。同理,返回来的结果,如果要用其中的数值,雅瑶保持参数名称和返回值字典中的键名相同

 param1 = request.json.get('param1')
  param2 = request.json.get('param2')
  • 1
  • 2
  1. 使用 requests.post() 方法向 Flask 接口发送 POST 请求,并将数据以 JSON 格式发送

这里使用了 json=data 参数,它将自动将 Python 字典转换为 JSON 格式,并作为请求的内容发送给接口

response = requests.post(url, json=data)
  • 1
  1. 检查响应的状态码,若状态码为 200 表示请求成功,可以进一步处理响应

这里使用了 response.json() 方法将响应的 JSON 格式数据转换为 Python 对象,可以根据实际需要进一步处理返回的结果

if response.status_code == 200:
    result = response.json()
    print(result)
else:
    print('请求失败:', response.status_code)
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 下面展示我自己写的访问这个接口的demo

因为传的参数是图片的数据流,所以无论是在请求还是接口写的时候都会有一些预处理,如果大家传的直接是图片,可以不需要这些预处理。

import base64
import os
import requests
import cv2
import json
from base64 import b64encode,  b64decode

# 指定文件夹路径
folder_path = "./test"
# 读取文件夹下所有的 jpg 和 png 图片
image_files = [file for file in os.listdir(folder_path) if file.endswith(('.jpg', '.png'))]
# 存储转换后的 base64 编码的图片数据
images_data = []
# 遍历并编码图片文件
for image_file in image_files:
    with open(os.path.join(folder_path, image_file), 'rb') as stream:
        # 注意,这里存储的时候不需要再次编码为 JSON 字符串,直接保存 base64 字符串即可。
        image_base64 = b64encode(stream.read()).decode()
        images_data.append(image_base64)
# 构建发送到服务器的数据,包含所有图片的 base64 编码
data = json.dumps({"images_data": images_data})
# 设置 OCR API 的 URL
url = "http://xx.xxx.xxx.xx:5003/ocr"

# 向 OCR API 发送请求
res = requests.post(url, data=data)

# 解析返回的 JSON 数据
ret = json.loads(res.content)

# 目标文件夹
output_folder = "./results"

# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)

# 遍历返回的结果,并保存包含 OCR 文本框的图片
for idx, result in enumerate(ret["images_results"]):
    image_filename = f"result_{idx}.jpg"

    # 保存处理后的图片到指定的文件夹
    with open(os.path.join(output_folder, image_filename), 'wb') as outStream:
        outStream.write(base64.b64decode(result["show_image"]))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  1. 假设访问接口的文件为test.py
python test.py 就成功啦
  • 1

总结

呜呼~~终于写完了。发现总结归纳的过程也是另一种再学习的过程。初体验!!还不错
第一次写笔记,肯定会有很多不足,也恳请大家的批评指正,给予宝贵的建议,让我们共同进步。
这里我也参照了部分博客的内容:
https://blog.csdn.net/weixin_42475060/article/details/129709983
https://zhuanlan.zhihu.com/p/569149798
https://zhuanlan.zhihu.com/p/569136459

下一步计划,增加一下代码的健壮性以及尝试用一下fastapi 改写一下这个代码。先放几个我搜集到的有关于fastapi 写接口的方法:
https://zhuanlan.zhihu.com/p/397029492
https://blog.csdn.net/qq_43019451/article/details/110186752

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/364260
推荐阅读
相关标签
  

闽ICP备14008679号