提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
最近,需要写一个程序把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 服务通常需要经过以下两个步骤:
- 接收 HTTP 请求
在这一步中,我们需要使用 Flask 的 flask.request 模块来接收客户端发送的 HTTP 请求,并提取请求参数。这通常涉及到解析 URL、查询字符串和 POST 数据等,以及对数据格式进行验证和转换。通过使用 Flask 的请求处理机制,我们可以将接收到的请求发送给下一个步骤,进行模型预测。 - 响应 HTTP 请求
在这一步中,我们需要使用 Flask 的 flask.Response 模块将预测结果封装成 HTTP 响应,并将其发送回客户端。这通常涉及到定义 HTTP 状态码、响应头和响应体等,以及将响应数据转换为 JSON 或其他数据格式。通过使用 Flask 的响应处理机制,我们可以将模型预测结果返回给客户端,并告知客户端请求状态和错误信息等。
1.安装
首先你可以先判断一下自己有没有flask,可以使用如下命令
pip show flask
如果没有安装的,可以使用如下命令
pip install flask
2.创建flask应用程序(构建API接口)
- 导入 Flask 模块:首先,需要导入 Flask 模块,以便我们可以使用其中提供的功能和方法
from flask import Flask
- 创建 Flask 应用对象:使用 Flask 类,创建一个 Flask 应用对象,该对象将用于处理所有的请求和响应。
app = Flask(__name__)
- 定义路由和视图函数:在 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)
- 启动应用程序:最后,需要在代码的末尾添加一个条件判断,确保应用程序在直接运行脚本的情况下才会启动。(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)
- 将自己模型算法集成到上述的四个步骤中,得到如下的一个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)
- 运行这个服务,假设这个文件名为app.py
python app.py
会有如下结果:说明服务已经起来了,下一步,尝试访问这个接口。
3.请求该接口
使用 POSTman 或 curl 都可以测试模型部署的 API 接口,这里主要使用 requests 的 Python 库来编写发送请求的代码。
- 首先,确保已经在 Python 环境中安装了 requests 库。可以使用以下命令进行安装:
pip install requests
- 在代码中导入 requests 库
import requests
- 定义要访问的接口 URL
运行python app.py后控制台上会出现一个网址以及对应的端口号,然后把刚才定义的路由:ocr家加在后面进行访问。
url = 'http://xx.xxx.xxx.xx:5000/ocr'
- 准备要发送的数据
在这个例子中,我们使用了两个特征作为请求的数据,具体根据接口定义来修改。
data = {'param1': 'value1', 'param2': 'value2'}
这里要注意的是,这里data 定义的两个特征,在上面封装接口的 predict 函数中,使用 request.json.get() 方法从请求中提取参数值。要求参数的名称与示例中的data字典中的键名相同。同理,返回来的结果,如果要用其中的数值,雅瑶保持参数名称和返回值字典中的键名相同
param1 = request.json.get('param1')
param2 = request.json.get('param2')
- 使用 requests.post() 方法向 Flask 接口发送 POST 请求,并将数据以 JSON 格式发送
这里使用了 json=data 参数,它将自动将 Python 字典转换为 JSON 格式,并作为请求的内容发送给接口
response = requests.post(url, json=data)
- 检查响应的状态码,若状态码为 200 表示请求成功,可以进一步处理响应
这里使用了 response.json() 方法将响应的 JSON 格式数据转换为 Python 对象,可以根据实际需要进一步处理返回的结果
if response.status_code == 200:
result = response.json()
print(result)
else:
print('请求失败:', response.status_code)
- 下面展示我自己写的访问这个接口的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"]))
- 假设访问接口的文件为test.py
python test.py 就成功啦
总结
呜呼~~终于写完了。发现总结归纳的过程也是另一种再学习的过程。初体验!!还不错
第一次写笔记,肯定会有很多不足,也恳请大家的批评指正,给予宝贵的建议,让我们共同进步。
这里我也参照了部分博客的内容:
https://blog.csdn.net/weixin_42475060/article/details/129709983
https://zhuanlan.zhihu.com/p/569149798
https://zhuanlan.zhihu.com/p/569136459文章来源:https://www.toymoban.com/news/detail-796535.html
下一步计划,增加一下代码的健壮性以及尝试用一下fastapi 改写一下这个代码。先放几个我搜集到的有关于fastapi 写接口的方法:
https://zhuanlan.zhihu.com/p/397029492
https://blog.csdn.net/qq_43019451/article/details/110186752文章来源地址https://www.toymoban.com/news/detail-796535.html
到了这里,关于使用flask将paddleocr车牌检测模型部署到服务器上的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!