YOLOv8 测试 5-2:Linux 中 Dockerfile 部署 YOLOv8 项目一键运行,Python 封装 API 接口测试

一、前言

记录时间 [2024-4-15]

系列文章简摘:
Docker 学习笔记(二):在 Linux 中部署 Docker(Centos7 下安装 docker、环境配置,以及镜像简单使用)
API 接口简单使用(二):Python 中使用 Flask(接口封装整理版,含文件上传接口的详细实现)
YOLOv8 测试 5:Linux 中 Docker 部署 YOLOv8,Python 封装 API 接口,base64 图片处理

更多 YOLOv8 测试相关文章请参考上面专栏哦。

本文在 YOLOv8 测试 5 的基础上开展,在测试 5 中,实现了在 Linux 中 使用 Docker 部署 YOLOv8 模型,并借助 Python 封装 API 接口来调用。还介绍了 base64 格式图片的处理方法,最后通过接口上传图片的 base64 格式编码,得到接口返回识别结果。

本文在测试 5 基础上进行升级,采用 Dockerfile 的方式来构建 Conda 镜像,部署 YOLOv8 项目一键运行。


二、材料准备

材料准备:是在测试 5 基础上哦,这些材料的制作测试 5 都有详细说明。

在这里整理了一下步骤,方便快速操作。更详细的解释请参考,这篇文章

  1. 【测试 5 步骤 4-3】导出备份的 conda 虚拟环境 envs(envs / yolov8 里面安装了 python 和 pytorch);
  2. 【测试 5 步骤 3, 4-2】本地编写完成的 ultralytics-main 项目文件(base64_test.py 编写完成了);
  3. 把这两个材料放在同一个目录下,比如笔者放在了 /home/yuanyuan/build/yolo 目录下;
  4. /home/yuanyuan/build/yolo 是制作 Dockerfile 的工作目录。

1. 导出 conda 虚拟环境

制作虚拟环境

Docker 安装配置什么的这里就不赘述啦

用从 DockerHub 下载的基础镜像 conda/miniconda3 运行容器,制作 conda 虚拟环境 yolov8,并下载 python 和 pytorch。

# 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

导出到 Linux 宿主机

备份 conda 虚拟环境 yolov8 到 Linux 宿主机

# docker cp 容器名:源路径 目标路径
docker cp yolopy03:/usr/local/envs /home/yuanyuan/conda

2. 编写 YOLOv8 项目并上传

自己电脑上,使用 PyCharm 打开从仓库下载的 YOLOv8 项目 ultralytics-main,找到 tests 目录,在该目录下新建 base64_test.py 文件。并在 ultralytics-main/tests/tmp/ 目录下,新建 upload 文件夹,用来存放接口上传的文件;新建 save 文件夹,用来存放项目保存的文件。

导入项目依赖

在 base64_test.py 文件中导入项目运行的所有依赖:

# YOLOv8 所需依赖
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)

# Flask 框架使用所需依赖
from flask import Flask, request, send_file

# base64 处理依赖,文件依赖
import base64
from PIL import Image
from io import BytesIO

编写测试程序

在 base64_test.py 文件中,编写 API 接口,完成 YOLOv8 测试程序编写:

app = Flask(__name__)

@app.post('/baseFile')
def return_image():
# 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)
    
# 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')

# 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)


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

上传本地项目

本地项目 ultralytics-main 已经完成编写,关闭 PyCharm,找到 ultralytics-main 文件夹

通过 FinalShell,把 ultralytics-main 一整个上传到 Linux 服务器 /home/yuanyuan/build/yolo 目录中


3. 上传材料到工作目录

本地项目 ultralytics-main 应该是上一步就上传好了的,接下来把备份的虚拟环境也放进工作目录。

Linux 中拷贝文件夹的命令为:

# cp -r 源路径 目标路径
cp -r /home/yuanyuan/conda/envs /home/yuanyuan/build/yolo

如图所示,把这两个材料放在工作目录。

在这里插入图片描述


三、思路整理

Dockerfile 用于程序开发,就好比,本来我们是在 Linux 中运行官方仓库的基础镜像,然后自己在容器里面一步一步地完成 YOLOv8 模型的部署,自己创建 conda 环境,在命令行里一步一步地配置依赖,最后再通过 python 把我们的项目运行起来。

Dockerfile 要做的事情就是,上面的这些步骤都可以在构建镜像之前完成,然后只要运行这个镜像,项目就可以一键运行。

那么在 Dockerfile 中具体完成了哪些步骤呢?

  • 配置基础镜像 conda/miniconda3
  • 添加 ultralytics-main 项目到工作路径
  • 添加适合 yolov8 运行的 conda 虚拟环境
  • 设置合适的 Bash 脚本 /bin/bash -c
  • 安装项目所需的依赖
  • 配置工作路径 /usr/local/ultralytics-main
  • 暴露项目运行的 5001 端口
  • 设置容器默认的启动运行命令 CMD

四、部署 YOLOv8 项目

1. 编写 Dockerfile

根据上面的思路整理,完成 Dockerfile 的编写。

确定工作目录 /home/yuanyuan/build/yolo,确保工作目录下面两份材料导入成功。

[root@localhost yolo]# pwd
/home/yuanyuan/build/yolo
[root@localhost yolo]# ls
envs  ultralytics-main

在工作目录,创建 Dockerfile 文件:注意默认命名 Dockerfile 不要写错。

vim Dockerfile

编写 Dockerfile,注意顺序,构建的时候是从上到下执行的。

FROM conda/miniconda3
MAINTAINER yuanyuan<1234567@qq.com>

ADD ultralytics-main /usr/local/ultralytics-main
ADD envs /usr/local/envs

SHELL ["/bin/bash", "-c"]

RUN source activate && \
    conda activate yolov8 && \
    pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
    cd /usr/local/ultralytics-main && \
    pip install -e . && \
    pip uninstall opencv-python -y && \
    pip install opencv-python-headless -i https://pypi.tuna.tsinghua.edu.cn/simple && \
    pip install pytest && \
    pip install flask
        

ENV MYPATH /usr/local/ultralytics-main
WORKDIR $MYPATH

EXPOSE 5001

CMD source activate && conda activate yolov8 && python tests/base64_test.py

2. 构建 + 运行 + 测试

构建镜像

在工作目录,使用 Dockerfile 构建 diy-yolov8 镜像

docker build -t diy-yolov8 .

一键运行

diy-yolov8 镜像构建完成后,把容器端口映射给宿主机,一键运行。

docker run -p 3354:5001 diy-yolov8

接口测试

测试方式,使用 Postman 测试。

在 Postman 中,输入宿主机 ip / 宿主机端口,POST 请求,添加 base64 格式编码 txt 文件,Send 测试!

http://ip:3354/baseFile

五、常见问题整理

1. sh 无法运行 source 命令

Docker 使用 conda 时,如果遇到以下错误:

ERROR: failed to solve: process "/bin/sh -c source ..." did not complete successfully: exit code: 127

错误原因:Docker 构建镜像时,默认使用 sh 方式,而 sh 下没有 source 命令。

解决方式:把 sh 修改为 bash 方式。

# 此命令写在 source 命令之前
SHELL ["/bin/bash", "-c"]

2. ADD 添加文件注意点

对比 cp 和 ADD 中的文件路径:

# 在 yolo 目录下放入 整个 envs
# 最终文件位置 yolo/envs
cp -r /home/yuanyuan/conda/envs /home/yuanyuan/build/yolo

# 把 envs 目录下的内容放入 local/envs 目录下
# 最终文件位置 local/envs
ADD envs /usr/local/envs

六、总结

本文在测试 5 基础上进行升级,采用 Dockerfile 的方式来构建 Conda 镜像,部署 YOLOv8 项目一键运行。整理了 Dockerfile 制作 YOLOv8 镜像过程中的常见问题。


一些参考资料

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/

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

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

相关文章

海外媒体发稿:新加坡 Asia One VS新加坡sg雅虎

海外媒体发稿&#xff1a;新加坡 Asia One VS新加坡sg雅虎 新加坡&#xff1a;雅虎 官网&#xff1a;sy.yahoo.com 官网&#xff1a;asiaone.com/lite 亚洲第一站。是 新加坡的新闻和生活方式网站和新闻聚合器。它是 新加坡第一个纯数字 内容平台&#xff0c;主要为新加坡、…

【攻防世界】bug

垂直越权IP绕过文件上传 文件上传绕过&#xff1a; 1. mime检测 2. 大小写绕过 3. 等价替换&#xff08;php5&#xff0c;php3&#xff09; 4. 利用JavaScript执行php代码&#xff08;正常的php代码会被检测到&#xff0c;所以就用JavaScript来执行&#xff09; <script lan…

docker特殊问题处理3——docker-compose安装配置nacos

最近几年随着大数据和人工智能持续大热&#xff0c;容器化安装部署运维已经走进了各个中小公司&#xff0c;也得已让众多开发者能上手实际操作&#xff0c;不过说真心话&#xff0c;“万物皆可容器化”的理念越来越深入人心。 而如何使用docker-compose安装&#xff0c;配置&a…

dremio作业概括

1. Summary 属性 描述 Status 表示一个或多个作业状态。作业和状态 Total Memory 提供有关查询操作的实际成本&#xff08;以内存为单位&#xff09;的统计信息。 CPU Used 提供有关查询操作的实际成本&#xff08;CPU 处理&#xff09;的统计信息。 Query Type 表示五…

IDEA设置文件编码

全局编码&#xff1a;UTF-8 项目编码&#xff1a;UTF-8 属性文件的默认编码&#xff1a;UTF-8 自动转换成Ascii但现实原生的内容&#xff1a;勾上

An Investigation of Geographic Mapping Techniques for Internet Hosts(2001年)第一部分

下载地址:An investigation of geographic mapping techniques for internet hosts | Proceedings of the 2001 conference on Applications, technologies, architectures, and protocols for computer communications 被引次数:766 Padmanabhan V N, Subramanian L. An in…

【C++软件调试技术】C++软件开发维护过程中典型调试问题的解答与总结

目录 1、引发C软件异常的常见原因有哪些&#xff1f; 2、排查C软件异常的常用方法有哪些&#xff1f; 3、为什么要熟悉常见的异常内存地址&#xff1f; 4、调试时遇到调用IsBadReadPtr或者IsBadWritePtr引发的异常&#xff0c;该如何处理&#xff1f; 5、如何排查GDI对象泄…

极大似然估计、最大后验估计、贝叶斯估计

机器学习笔记 第一章 机器学习简介 第二章 感知机 第三章 支持向量机 第四章 朴素贝叶斯分类器 第五章 Logistic回归 第六章 线性回归和岭回归 第七章 多层感知机与反向传播【Python实例】 第八章 主成分分析【PCA降维】 第九章 隐马尔可夫模型 第十章 奇异值分解 第十一章 熵…

Flask框架——安装与第一个应用

安装 Flask是一个轻量级的Python Web框架。它是一个微型框架&#xff0c;具有灵活性和可扩展性。Flask使用Python语言编写&#xff0c;它是一个开源框架&#xff0c;使得它可以自由地使用和修改。Flask框架可以用于构建任何类型的Web应用程序&#xff0c;包括单页面应用程序、…

C#硬件接口开发------一文了解WMI

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C# 硬件接口开发 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足…

C++11 设计模式0. 设计模式的基本概念,设计模式的准则,如何学习设计模式,24种设计模式的分为3大类

一 设计模式的基本概念&#xff1a; 模式&#xff1a;指事物的标准样式 或者 理解成 针对特定问题的可重用解决方案。 设计模式&#xff0c;是在特定问题发生时的可重用解决方案。 设计模式一般用于大型项目中。 大型项目中&#xff0c;设计模式保证所设计的模块之间代码的灵…

【Web】设置默认浏览器

专栏文章索引&#xff1a;Web 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 一、步骤 一、步骤 打开 “控制面板” 查看方式选择 “大/小图标” 点击 “默认程序” 点击想要设置的 默认浏览器 点击 “设置默认值” 设置 “默认文件类型”

FreGS:具有渐进频率正则化的3D高斯溅射

FreGS: 3D Gaussian Splatting with Progressive Frequency Regularization FreGS&#xff1a;具有渐进频率正则化的3D高斯溅射 Jiahui Zhang1  Fangneng Zhan2  Muyu Xu1  Shijian Lu1  Eric Xing3, 4 张家慧 1 詹方能 2 许慕玉 1 卢世坚 1 邢志伟 3, 4 1Nanyang Technolo…

调度:setTimeout 和 setInterval

有时我们并不想立即执行一个函数&#xff0c;而是等待特定一段时间之后再执行。这就是所谓的“计划调用&#xff08;scheduling a call&#xff09;”。 目前有两种方式可以实现&#xff1a; setTimeout 允许我们将函数推迟到一段时间间隔之后再执行。 setInterval 允许我们重…

Jmeter-跨线程传参(正则提取多个参数、jsonpath提取器)

目的&#xff1a; 当前接口请求的参数依赖于其他请求&#xff0c;且两个请求不是在同一个线程组时就会用到该方法进行跨线程组传参。 实际使用场景&#xff1a; 多个线程组的请求都依赖登录接口&#xff0c;但是登录接口仅执行一次。 实现方法&#xff1a; 以下举例的有正…

25. 【Android教程】列表控件 ListView

在学习了 ScrollView 及 Adapter 两节内容之后&#xff0c;大家应该对 ListView 有了一些基本的了解&#xff0c;它是一个列表样式的 ViewGroup&#xff0c;将若干 item 按行排列。ListView 是一个很基本的控件也是 Android 中最重要的控件之一。它可以帮助我们完成多个 View 的…

bugku-web-需要管理员

页面源码 <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>404 Not Found</title> </head> <body> <div idmain><i> <h2>Something error:</h2…

指针的深入理解(七)

指针的深入理解&#xff08;七&#xff09; 个人主页&#xff1a;大白的编程日记 个人专栏&#xff1a;C语言学习之路 感谢遇见&#xff0c;我们一起学习进步&#xff01; 文章目录 指针的深入理解&#xff08;七&#xff09;前言一.常量字符串指针1.1常量字符串的理解1.2常量…

[蓝桥杯 2019 国 B] 解谜游戏

[蓝桥杯 2019 国 B] 解谜游戏 题目背景 题目描述 小明正在玩一款解谜游戏。谜题由 24 24 24 根塑料棒组成&#xff0c;其中黄色塑料棒 4 4 4 根&#xff0c;红色 8 8 8 根&#xff0c;绿色 12 12 12 根 (后面用 Y 表示黄色、R 表示红色、G 表示绿色)。初始时这些塑料棒排…

LangChain初学者指南

自从ChatGPT发布以来&#xff0c;大语言模型(LLM)得到极大普及。虽然大多数人没有足够资金和计算资源从头开始训练LLM&#xff0c;但仍然可以基于预训练的LLM来构建一些很酷的东西&#xff0c;例如: 可以根据个人数据与外界互动的个人助理为特定目的定制的聊天机器人对文档或代…