一、前言
记录时间 [2024-4-14]
系列文章简摘:
Docker 学习笔记(二):在 Linux 中部署 Docker(Centos7 下安装 docker、环境配置,以及镜像简单使用)
API 接口简单使用(二):Python 中使用 Flask(接口封装整理版,含文件上传接口的详细实现)
YOLOv8 测试 3:在 Python 中将 YOLOv8 模型封装成 API 接口使用(上传测试图片并返回识别结果,附测试代码)
YOLOv8 测试 4:在 Linux 中使用 Docker 部署 YOLOv8 模型,并使用简单的命令行脚本测试模型
更多 YOLOv8 测试相关文章请参考上面专栏哦。
本文在 YOLOv8 测试 3 和 4 的基础上开展,在测试 3 中,介绍 Windows 中使用 Python 将 YOLOv8 模型封装成 API 接口来调用;在测试 4 中,介绍 Linux 中使用 Docker 部署 YOLOv8 模型。
综合测试 3 和 4,本文主要实现在 Linux 中 使用 Docker 部署 YOLOv8 模型,并借助 Python 封装 API 接口来调用。在此基础上,再介绍 base64 格式图片的处理方法,最后通过接口上传图片的 base64 格式编码,得到接口返回识别结果。
二、思路整理
- 在本地 PyCharm 中完成项目开发
- 使用 Flask 框架编写 API 接口
- base64 格式图片处理
- YOLOv8 模型的 predict 使用
- 在 Linux 中部署 Docker,操作系统为 CentOS 7
- 准备 Linux 云服务器 / 虚拟机
- 安装并配置 Docker
- 熟悉 Docker 的镜像容器操作
- 在 Conda 容器中部署 YOLOv8 项目
- 通过 FinalShell 把本地项目上传到 Linux 服务器中
- 部署一个 conda 镜像
- 配置端口暴露,数据卷挂载
- 通过数据卷挂载 YOLOv8 项目到容器中
- 使用 Postman 测试 API 接口
- 上传图片的 base64 格式编码文件
- 得到接口返回的图片识别结果
三、YOLOv8 项目开发
在本地 PyCharm 中完成项目开发,更详细的步骤请参考这篇文章
1. 依赖配置
使用 PyCharm 打开我们之前使用过的,从仓库下载的 YOLOv8 项目 ultralytics-main,找到 tests 目录,在该目录下新建 base64_test.py 文件。
并在 ultralytics-main/tests/tmp/
目录下,新建 upload
文件夹,用来存放接口上传的文件;新建 save
文件夹,用来存放项目保存的文件;
在 base64_test.py 文件中导入 YOLOv8 项目运行所需的依赖和配置:
# Ultralytics YOLO 🚀, AGPL-3.0 license
import contextlib
from copy import copy
from pathlib import Path
import cv2
import numpy as np
import pytest
import torch
import yaml
from PIL import Image
from torchvision.transforms import ToTensor
from ultralytics import RTDETR, YOLO
from ultralytics.cfg import TASK2DATA
from ultralytics.data.build import load_inference_source
from ultralytics.utils import (
ASSETS,
DEFAULT_CFG,
DEFAULT_CFG_PATH,
LINUX,
MACOS,
ONLINE,
ROOT,
WEIGHTS_DIR,
WINDOWS,
Retry,
checks,
is_dir_writeable,
)
from ultralytics.utils.downloads import download
from ultralytics.utils.torch_utils import TORCH_1_9, TORCH_1_13
MODEL = WEIGHTS_DIR / "path with spaces" / "yolov8n.pt" # test spaces in path
CFG = "yolov8n.yaml"
SOURCE = ASSETS / "bus.jpg"
TMP = (ROOT / "../tests/tmp").resolve() # temp directory for test files
IS_TMP_WRITEABLE = is_dir_writeable(TMP)
2. 编写 API 接口
如果对 Flask 构建 API 接口有疑问的,参考这篇文章
在这个接口中,实现以下要求:
- 接收接口请求的图片的 base64 格式编码文件
- 将 base64 格式编码文件还原成图片并保存
- YOLOv8 模型对该图片进行目标识别
- 返回目标图片的识别结果
编写文件上传接口
在 base64_test.py 文件中,导入 Flask 框架使用所需依赖:
from flask import Flask, request, send_file
编写一个简单的 API 接口,后面我们在return_image()
函数中编写内容。
app = Flask(__name__)
@app.post('/baseFile')
def return_image():
return "Succeed"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001)
编写好后运行(右键 run ‘base64_test.py’),使用 Postman 测试下这个接口可不可用。
POST 请求不能直接在浏览器测试,浏览器默认 GET 请求。
处理上传的文件
在return_image()
函数中编写内容:获取接口上传的文件,并保存到 upload 目录。
# 1. 获取上传的文件
# 文件作为参数传递,其 id为 file
# 如果没有接收到这个请求,返回 No file part
if 'file' not in request.files:
return "No file part"
# 获取文件
file = request.files['file']
# 获取文件名
if file.filename == '':
return "No selected file"
filename = file.filename
# 2. 保存到指定位置 upload 文件夹
file.save(TMP / 'upload' / filename)
处理 base64 格式编码文件
base64 格式编码是指:把二进制数据转换成 64 个可以打印的字符。
如何获取图片的 base64 格式编码呢?使用在线图片转换工具,上传图片获得 base64 格式编码,将编码保存为 txt 文件。
在 base64_test.py 文件中,导入依赖:
import base64
from PIL import Image
from io import BytesIO
接着在return_image()
函数中编写内容:读取编码文件内容,将 base64 格式编码文件还原成图片并保存。
# 3. 获取编码文件并解码
base_file = TMP / 'upload' / filename
# 打开编码文件,读取文件中的内容
with open(base_file, 'r') as file:
content = file.read()
# 将 base64_str 以 “,” 分割为两部分,context 部分是需要解码的部分
base64_str = str(content)
head, context = base64_str.split(",")
# 解码时只要内容部分
img_data = base64.b64decode(context)
# 4. 通过解码内容得到图片,保存图片
image = Image.open(BytesIO(img_data))
image.save(TMP / 'save' / 'test_image.jpg')
# 看图片
# image.show()
3. YOLOv8 识别图片
接下来,下载并使用 YOLOv8 模型,对获得的图片进行目标识别。
接着在return_image()
函数中编写内容:对图片进行目标识别,并返回识别结果。
# 5. 使用 YOLOv8 模型对该图片进行目标识别
model = YOLO(MODEL)
# 得到的图片路径
source = TMP / 'save' / 'test_image.jpg'
# 保存 目标识别的结果
results = model.predict(source, save=True, imgsz=320, conf=0.5)
# 6. 获取 识别结果 的保存路径
save_path = Path(results[0].save_dir)
image_path = save_path / 'test_image.jpg'
# 7. 以图片形式 返回结果
return send_file(image_path)
编写好后运行(右键 run ‘base64_test.py’),使用 Postman 测试下,选 form-data
类型,上传 base64 格式编码文件,测试下识别结果是否返回成功。
四、在 Linux 中的准备工作
1. Linux 中部署 Docker
宿主机 Linux,操作系统为 CentOS 7,Linux 虚拟机安装,参考这篇文章
在 Linux 中部署 Docker,参考这篇文章
2. 上传本地项目
本地项目 ultralytics-main 已经完成编写,关闭 PyCharm,找到 ultralytics-main 文件夹
通过 FinalShell,把 ultralytics-main 一整个上传到 Linux 服务器 /home/YOLO 目录中(目录随便)
3. 运行 conda 容器
在之前的文章中,参考这篇文章,我们已经在 Docker 中部署了 Conda 环境,可以直接把这个部署好的 conda 虚拟环境拿来用。
如果之前的容器丢失了,那我们快速地部署一下吧。
# 1. 创建 conda 容器并运行
docker run -it --name yolopy03 conda/miniconda3 /bin/bash
# 2. 配置 yolov8 运行环境
conda create -n yolov8 python=3.9
# Proceed ([y]/n)? y
# 3. 检查虚拟环境配置
conda env list
# 4. 进入 base 环境
source activate
# 5. 激活 Conda 环境,创建 yolov8 运行
conda activate yolov8
# 6. 配置清华源镜像
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 7. 安装 pytorch
pip install torch==1.13.1+cpu torchvision==0.14.1+cpu torchaudio==0.13.1 \
--extra-index-url https://download.pytorch.org/whl/cpu
# 8. 检查 python 环境
python --version
# 9. 退出容器 exit,退出虚拟环境用 conda deactivate,退不出就 kill,没事的
exit
五、部署 YOLOv8 项目
接下来,在 Docker 中部署 YOLOv8 项目,配置数据卷挂载,更详细的步骤请参考这篇文章
1. 导出 yolov8 虚拟环境
把上面那个配置好的 yolopy03 容器 conda 环境拿过来,导出 envs 下面的 yolov8 虚拟环境。
虚拟环境位于容器的 /usr/local/envs
,把它导出到宿主机的 /home/YOLO
目录下:
# 导出 yolov8 虚拟环境
docker cp yolopy03:/usr/local/envs /home/YOLO
2. 运行新的容器
在运行前,配置下端口暴露,以及数据卷挂载。
端口暴露是为 API 接口访问做准备,数据卷挂载是为了将宿主机上的 ultralytics-main 项目和 yolov8 虚拟环境同步到新容器中。
这样可以省去新容器重复配置的步骤,一些创建的、安装好的东西不用重复安装了。
但是参数 / 变量的配置是不会生效的,比如清华源镜像。
-it
:交互式运行;--name
:容器命名;-p 3352:5001
:把容器的 5001 端口映射到宿主机的 3352 端口;-v 宿主机路径:容器内路径
:把容器内路径挂载到宿主机路径,可以挂载很多个路径。
docker run -it --name yolopy06 -p 3352:5001 \
-v /home/YOLO/ultralytics-main:/usr/local/ultralytics-main \
-v /home/YOLO/envs:/usr/local/envs conda/miniconda3
进入容器后,检查下虚拟环境配置,然后激活 yolov8 运行环境。
# 检查虚拟环境配置
conda env list
# 进入 base 环境
source activate
# 激活 yolov8 运行环境
conda activate yolov8
配置清华源镜像,否则下载东西非常慢
# 检查 python 环境
python --version
# 配置清华源镜像
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
3. 安装 YOLOv8 项目依赖
进入 ultralytics-main 目录,为什么容器内会有 ultralytics-main 文件呢?答对了,因为数据卷挂载。
cd /usr/local/ultralytics-main
在该目录下,安装 / 更新 YOLOv8 项目运行所需的依赖:
# 安装 YOLOv8 项目依赖
pip install -e .
# 更新 opencv-python
pip uninstall opencv-python -y
pip install opencv-python-headless -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pytest
pip install flask
六、项目测试运行
1. 运行项目
先确定容器工作目录:/usr/local/ultralytics-main
python 方式运行 base64_test.py(熟悉吗?我们刚刚写的)
python tests/base64_test.py
2. 接口测试
测试方式,使用 Postman 测试。
http://ip:3352/baseFile
如图所示,项目启动成功后,输入宿主机 ip / 宿主机端口,POST 请求,添加 base64 格式编码文件,Send 测试!
返回了识别结果,测试成功!
再来看一下服务端的情况吧:
- 处理了 base64 编码文件,保存了图片;
- 下载了 yolov8n.pt 模型,对图片进行目标识别;
- 将结果保存,并通过接口返回给客户端。
七、总结
本文主要实现在 Linux 中 使用 Docker 部署 YOLOv8 模型,并借助 Python 封装 API 接口来调用。还介绍了 base64 格式图片的处理方法,最后通过接口上传图片的 base64 格式编码,得到接口返回识别结果。复习了数据卷的命令挂载方法。
一些参考资料
Docker 官方文档:https://docs.docker.com/engine/install/centos/
Docker 远程仓库:https://hub.docker.com/
FinalShell 下载:http://www.hostbuf.com/t/988.html
YOLOv8 官方文档:https://docs.ultralytics.com/zh/
YOLOv8 模型仓库地址:https://github.com/ultralytics/ultralytics
PyCharm官网:https://www.jetbrains.com/pycharm/download/?section=windows
Postman 官网:https://www.postman.com/
阿里云官网:https://www.aliyun.com/