Gradio 部署 YOLOv8:浏览器目标检测与分割演示系统实战

📅 发布时间:2026/10/1 4:56:01
Gradio 部署 YOLOv8:浏览器目标检测与分割演示系统实战
简介基于Gradio的YOLOv8通用目标检测与图像分割演示系统将前沿检测算法与低代码交互界面结合适合计算机视觉学习者、算法工程师以及需要快速搭建演示Demo的开发者。压缩包共32个文件包含网络结构yaml配置、Python启动脚本、示例jpg图片、类别映射csv以及Docker部署文件等包体仅2.59MB轻量简洁。已有1361人学习下载受到一定关注。借助该资源可一键运行本地演示上传图片即可获得目标边界框与分割掩码结果同时提供多语言类别配置、FastAPI服务端脚本、字体与PDF优化工具兼顾界面演示与实际项目集成便于二次开发与教学分享。1. 把 YOLOv8 拖进浏览器这个 Gradio 演示系统解决的不只是「跑通」你手上有一个训练好的 YOLOv8 权重模型在终端里跑得飞快但到了给导师、给甲方演示的时候现场永远是一堆命令行和 TensorBoard 截图效果打折。这个gradio-yolov8-det-master压缩包就是干这个的用 Gradio 把 YOLOv8 的目标检测和图像分割包成一个网页应用浏览器打开拖一张图进去检测框和分割掩码直接画出来还能切换语言、切换模型、走 Docker 或 FastAPI 对外提供接口。对搞毕设、打比赛、做内部交付演示的从业者来说它省掉了从前端到后端的一整套重复劳动。本文按「包内有什么、本地怎么跑、容器和 API 怎么上、坑在哪、怎么改成自己的模型」这条线拆完你拿到压缩包后应该能在半小时内把它跑起来。2. 拆包看货项目文件结构与主程序核心逻辑2.1 文件清单先搞清楚每个文件是干什么的我在拿到这个压缩包后做的第一件事不是急着装依赖而是把文件按「主程序 / 模型配置 / 类别名 / 部署 / 工具 / 示例图」分了个类。这样后面出了问题能直接定位到对应的文件去改而不是全程黑匣子式排查。分类文件作用主程序gradio_yolov8_det.py核心演示应用Gradio 界面 YOLOv8 推理主程序变体gradio_yolov8_det_v03.py另一个版本的主程序功能与主程序略有差异可对比使用Docker 版本gradio_yolov8_det_docker.py容器内启动入口代码逻辑与主程序基本一致FastAPI 后端gyd_fastapi_server.py把检测/分割能力封装成 HTTP 接口供外部调用模型配置model_config/model_name_all.csv、model_name_all.yaml、model_name_custom.yaml管理可选模型清单custom.yaml是留给用户自定义模型的入口类别名配置cls_name目录下cls_name.yaml及_zh/_en/_ru/_ar/_ko/_es等把 COCO 80 类类别名翻译成多语言界面语言切换时用部署配置Dockerfile、.dockerignore、requirements.txt、.gitignore、setup.cfg、.pre-commit-config.yaml构建镜像、Python 依赖、代码规范工具模块util/pdf_opt.py、util/fonts_opt.pyPDF 导出优化、字体加载处理样例图片img_examples/下 6 张 jpgCOCO 官方样本bus、zidane、giraffe 等用于功能验证图标icon/logo.icoGradio 页面左上角 logo要注意的一点是gradio_yolov8_det.py和gradio_yolov8_det_v03.py并不是简单的新旧替换关系。我对比过两个文件v03在界面布局和部分参数上做了调整但主程序和 Docker 入口都引用核心逻辑。如果你是自己学习先跑主程序如果你是奔着部署去直接看gradio_yolov8_det_docker.py走容器路线更省事。2.2 主程序推理链路从图片上传到检测框画出中间发生了什么整个系统说白了就是三件事加载模型、接收图片、把结果画回前端。以一个典型的 YOLOv8 Gradio 实现为例核心代码结构是这样组织的import gradio as gr from ultralytics import YOLO # 模型加载权重可以是官方预训练也可以是你自己训练的 model YOLO(yolov8n.pt) def detect_and_segment(image, conf_thres, iou_thres, task_mode): 统一推理入口检测和分割共用同一个模型实例 # 根据 UI 选择切换任务类型 if task_mode 检测: results model.predict(sourceimage, confconf_thres, iouiou_thres) else: results model.predict(sourceimage, confconf_thres, iouiou_thres, tasksegment) # YOLOv8 的 results[0] 自带 plot() 方法直接生成标注后的图像 annotated results[0].plot() return annotated # Gradio 界面输入图片、两个滑杆、一个单选按钮输出标注图 demo gr.Interface( fndetect_and_segment, inputs[gr.Image(typepil), gr.Slider(0.1, 1.0, value0.25), gr.Slider(0.1, 1.0, value0.45), gr.Radio([检测, 分割])], outputsgr.Image(typepil), titleYOLOv8 目标检测与分割演示, ) if __name__ __main__: demo.launch(server_name0.0.0.0, server_port7860)这段代码背后的逻辑值得细说。model.predict()返回的是一个Results对象列表每个对象对应一张输入图plot()方法内部做了两件事把检测框、类别标签、置信度画上去对于分割任务还会把掩码叠加成半透明色块。这就是为什么你不需要自己写任何 OpenCV 绘制代码几行就能出一个能看的 demo。参数方面conf是置信度阈值默认 0.25 意味着模型只显示置信度高于 25% 的目标iou是 NMS 的 IoU 阈值默认 0.45。实际调的时候如果你发现画面里框太多、重叠严重就把iou调高如果发现该检出的目标被滤掉了就把conf调低。这个系统里把两个参数做成了滑杆实操中非常方便因为每张图的场景复杂度不一样固定阈值经常会翻车。2.3 模型配置与多语言类别名为什么这不能写死在代码里model_config目录下有三个文件我强烈建议你在跑之前先看一眼model_name_all.csvyolov8n.pt, COCO 80类, 检测分割 yolov8s.pt, COCO 80类, 检测分割 yolov8m.pt, COCO 80类, 检测分割 yolov8l.pt, COCO 80类, 检测分割 yolov8x.pt, COCO 80类, 检测分割这个 CSV 的作用是给 Gradio 下拉框提供候选模型列表。实际加载时程序会拼接权重路径、读取对应 YAML 里的任务类型再决定调用YOLO(weights)时是否要额外指定tasksegment。这样设计的好处很明显你要加一个新模型只需要在 CSV 里加一行不用改主程序代码。cls_name目录里的多语言 YAML 是这套系统的一个亮点。COCO 数据集默认类别名是英文person、car、dog...但演示给国内客户看的时候全是英文标签体验很违和。这里的做法是把类别名从model.names取出来之后根据界面语言设置去替换 YAML 里对应语言的映射表。你如果要把这套系统改成自己的业务场景最该动的就是这个目录把类别名换成你实际要识别的物体界面展示上立刻就是一套「自己的系统」而不是一眼假的官方 demo。3. 本地跑起来环境配置、模型切换与检测/分割双模式3.1 环境准备Ubuntu 20.04 CPU 机器也能跑但有前提很多人一看到 YOLOv8 就默认必须要有 NVIDIA GPU实际上这个系统在 CPU 上完全能跑只是速度不同。我就在一台没有独显的 Ubuntu 20.04 机器上跑通过一张 640x640 的图yolov8n.pt在 CPU 上推理大约需要 200-400ms做演示完全够用实时视频流才需要认真考虑 GPU。先看requirements.txt里面最关键的是ultralytics、gradio、torch、opencv-python、PyYAML、pillow这几个。踩过坑的人都知道ultralytics和torch的版本匹配极其敏感常见做法是直接用 PyTorch 官方推荐的组合# 创建干净环境Python 3.10 比较稳妥 conda create -n gyd python3.10 -y conda activate gyd # CPU 版 torch 这样装GPU 版按 PyTorch 官网对应 CUDA 版本命令装 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 一键安装项目全部依赖 pip install -r requirements.txt参数说明--index-url只对 torch 和 torchvision 生效后面的requirements.txt里的其他包仍然从默认 PyPI 源拉取。我一般会把ultralytics、gradio这类包固定一个主版本号避免隔了半年后拉到一个 API 大变样的新版本。CPU 环境注意别装torch的 CUDA 版本装完才发现多占了几个 GB 磁盘不说部分机器还会在导入时报错。环境装好后我建议先手动验证一下依赖有没有装全而不是直接起 Gradio。最省事的验证方式是python -c from ultralytics import YOLO; import gradio as gr; print(deps ok)这个命令没有任何输出异常就说明基础环境没问题后面再报错就是代码层或配置层的问题了。3.2 启动主程序第一次跑通 Gradio 界面环境就绪后直接启动主程序是一个比较直接的做法python gradio_yolov8_det.py正常情况你会看到终端出现Running on local URL: http://127.0.0.1:7860。用浏览器打开这个地址就能看到上传区域和参数面板。界面大概是这样的结构左侧是图片上传、置信度滑杆、IoU 滑杆、任务模式切换右侧是结果输出。首次运行时ultralytics会自动下载你选择的权重文件到~/.cache/ultralytics目录。如果网络状况不太好、下载长时间卡住建议手动把权重文件下载好放到项目目录下的weights文件夹中然后改model_name_all.yaml里对应的路径。我自己习惯先把yolov8n.pt和yolov8s.pt都备好避免演示现场等下载。跑通之后有几个 UI 细节值得注意。gradio从 4.x 开始支持allow_flaggingnever这个参数用来关闭输出结果上的 Flag 按钮如果你要把这个系统交付给别人用建议加上。另外demo.launch(auth(admin, 123456))可以给整个界面加一道用户名密码验证——这就是热搜里说的 gradio 身份验证在公网演示或者内网多人访问时非常实用否则谁拿到你的 IP 端口都能白嫖算力。3.3 检测与分割双模式一个按钮背后的模型调度逻辑系统里界面上有「检测 / 分割」两个模式但底层其实只是给同一个predict()传了不同的参数。YOLOv8 的yolov8n.pt权重本身是同时包含检测头和分割头的所以不需要加载两个模型文件。分割模式走的参数是这样的# tasksegment 时返回的 Results 包含掩码数据 results model.predict( sourceimage, conf0.25, iou0.45, tasksegment, # 关键参数告诉模型走分割分支 retina_masksTrue, # 返回高分辨率掩码 ) mask results[0].masks.data # 形状为 [N, H, W] 的 Tensor这里有个很容易误会的点tasksegment是让模型使用分割头但如果你加载的是一个纯检测权重比如某些只训练了检测任务的自定义模型传这个参数会报错或者没效果。相反官方预训练权重是没问题的。分割结果的掩码是一个[N, H, W]的布尔张量N是检测到的目标数每个目标对应一张二值掩码图。如果你要拿掩码去做后续处理比如统计像素面积直接从results[0].masks.data取值就行。实际操作中分割模式的速度会比检测模式慢不少同样的图yolov8n检测大约 50ms分割大约 120ms。如果你的显卡显存比较小分割模式下两张 1080p 图同时推理就有 OOM 风险这我在第 5 章会细说。3.4 模型怎么切CSV、YAML 和启动参数三者的关系model_config下三个文件分工不同。model_name_all.csv更像是给前端下拉框用的候选清单model_name_all.yaml是实际运行时的配置映射model_name_custom.yaml则是为你准备的自定义模型入口。我拆开看过 YAML 里的关键字段models: - name: yolov8n.pt task: detect labels: cls_name/cls_name_en.yaml - name: yolov8n-seg.pt task: segment labels: cls_name/cls_name_en.yaml这里task字段决定了下拉框里选择这个模型时系统默认用什么样的推理模式labels字段指定了类别名文件位置。你换成自己训练的模型时要保证这三处对应关系没错权重文件真实存在、task与训练时一致、labels的类别数和权重里的类别数一致。否则会出现「模型加载成功但界面显示类别全是乱码」这类尴尬问题。4. 容器化和 API 化Docker 部署与 FastAPI 后端调用4.1 Dockerfile 解析从源码到可分发镜像如果你只是本地自己玩直接python gradio_yolov8_det.py完全够用。但像我这种经常要把系统交付给别人的场景Docker 镜像几乎是必须的——不然对方环境千奇百怪光装依赖就能耗掉半天。项目里自带的 Dockerfile 思路很清晰用 Python 3.10 slim 作为基础镜像装系统级依赖再装 Python 包最后复制代码进去。FROM python:3.10-slim # 系统级依赖opencv 需要 libgl1 和 libglib2.0少一个都会在 import cv2 时报错 RUN apt-get update apt-get install -y --no-install-recommends \ libgl1 libglib2.0-0 libsm6 libxext6 libxrender-dev \ rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 先复制主程序和配置再复制权重权重单独复制方便利用 Docker 缓存 COPY gradio_yolov8_det_docker.py . COPY model_config ./model_config COPY cls_name ./cls_name COPY util ./util COPY img_examples ./img_examples EXPOSE 7860 CMD [python, gradio_yolov8_det_docker.py]构建和启动命令# 构建镜像注意 context 是项目根目录 docker build -t gyd-demo:latest . # 启动容器宿主机 7860 映射到容器 7860 docker run -d -p 7860:7860 --name gyd \ -v /path/to/weights:/app/weights \ gyd-demo:latest-v挂载的意思是让容器读取宿主机上的权重目录这样你更新模型时不用重新构建镜像。这是实际项目里少走弯路的关键习惯把权重和代码分开不然每次换权重都要docker build一次镜像体积还会因为多份权重迅速膨胀。构建时如果网络不好pip install那一步会非常痛苦建议提前把requirements.txt里的包下载到本地或者给 Docker daemon 配置国内镜像源。4.2 FastAPI 后端把检测能力暴露成标准 HTTP 接口Gradio 界面适合人看但机器和机器之间的对接不合适。项目里带了gyd_fastapi_server.py这个文件的定位就是把 YOLOv8 的检测、分割能力封装成 HTTP 接口让其他业务系统可以上传图片、拿到 JSON 格式的结果。一个标准实现大概长这样from fastapi import FastAPI, UploadFile, File from ultralytics import YOLO import numpy as np from PIL import Image import io app FastAPI() model YOLO(yolov8n.pt) app.post(/detect) async def detect(file: UploadFile File(...), conf: float 0.25): # 读入上传图片并转为 RGB 数组 image Image.open(io.BytesIO(await file.read())).convert(RGB) results model.predict(sourcenp.array(image), confconf) # 序列化返回把框、类别、置信度整理成 JSON boxes results[0].boxes output [] for box in boxes: output.append({ class: model.names[int(box.cls)], conf: round(float(box.conf), 4), xyxy: [round(float(v), 2) for v in box.xyxy[0].tolist()], }) return {detections: output} # 启动方式uvicorn gyd_fastapi_server:app --host 0.0.0.0 --port 8000这个接口的设计有几个点值得注意。首先FastAPI 的UploadFile直接接收文件流我不建议你把它转成 base64 字符串再传那样会白白增加 30% 左右的传输体积。其次框的坐标是保留两位小数后返回前端或者调用方可以直接用这个值去画框不用关心模型内部的整数坐标还是浮点坐标。最后置信度阈值conf通过 query 参数传入这样调用方可以根据业务场景实时调整而不是固定死一个值。启动 FastAPI 服务后用curl测一下接口curl -X POST http://127.0.0.1:8000/detect?conf0.3 \ -F fileimg_examples/bus.jpg返回的 JSON 里应该有 bus、person、traffic light 之类的检测结果。如果返回 500 错误最常见的两个原因一是图片格式问题二是model.names的索引越界——后者多在类别数不匹配的情况下发生。这个接口也可以跟 Gradio 界面同时跑在同一个环境里互不干扰因为端口不同。GPU 资源紧张时要注意两个进程都会加载模型显存占用翻倍建议分开部署或者共用同一个后端服务。4.3 边缘设备部署的注意点RK3588 等 ARM 平台的差异关于 RK3588 这类边缘设备部署 YOLOv8 的场景我多说一句这个项目的代码在 ARM 板上可以跑但你要把torch换成 ARM 版且大概率要用onnxruntime或 RKNN 做推理加速。Gradio 和 FastAPI 部分逻辑不用改模型加载那段要换成对应的推理引擎。如果你现在用 x86 机器已经把整个流程跑通换到 ARM 时别急着在板子上装 PyTorch先用 ONNX 导出再转 RKNN会少走很多弯路。这个项目的目录结构里虽然没有直接的 RKNN 转换脚本但util目录下的工具是通用的可以先在电脑上把模型导出好再传到板子上。5. 避坑排查五个高频翻车点与对应解法5.1 翻车一Gradio 界面正常打开上传图片后无结果现象浏览器能访问界面拖入图片后点了 Submit但输出区域一直转圈终端没有任何报错最后超时。原因最常见的是ultralytics在加载模型时默认去下载权重文件你的机器能访问 Gradio 的本地服务但网络访问不了外网下载卡在连接阶段整个推理线程被阻塞了。解决先手动下载好对应的.pt权重放到项目目录然后改代码里模型加载的路径从相对路径读取不要用默认的yolov8n.pt这个名字因为这个名字会触发自动下载逻辑。具体做法是把YOLO(yolov8n.pt)改成YOLO(./weights/yolov8n.pt)确保不走网络。5.2 翻车二torch 与 ultralytics 版本不匹配推理时报参数错误现象环境装好后导入ultralytics不报错但一调用model.predict()就报一个很长的 TypeError类似got an unexpected keyword argument task。原因ultralytics是一个更新很频繁的库不同版本对predict()的参数支持不一样。老版本可能不支持task参数新版本改了默认行为。解决进到环境里执行pip list | grep ultralytics看版本如果是 8.0.x 的早期版本直接升到 8.1.0 以上。我一般是在requirements.txt里直接写死ultralytics8.1.0这样重新装的时候不会拉回旧版。这个问题在 CPU 机器上尤其隐蔽因为 CPU 不报 CUDA 错误你很容易归因到别的地方。5.3 翻车三容器启动后报libGL.so.1: cannot open shared object file现象Docker 镜像构建成功但docker run之后容器秒退查看日志发现import cv2时抛出libGL.so.1找不到。原因opencv-python的 wheel 包依赖系统的libGL库而python:3.10-slim这个基础镜像里没有装这个系统库。这是 slim 镜像的经典问题几乎所有用 OpenCV 的 Python 项目都会遇到。解决在 Dockerfile 里加一行apt-get install -y libgl1 libglib2.0-0。如果你用的是非 slim 镜像或者ubuntu基础镜像大概率不会踩这个坑但镜像体积会大上不少。这个问题的典型特征就是日志里只有这一行错误很容易搜索定位但没遇到过的人会以为是 cv2 没装好白折腾半天重装。5.4 翻车四中文类别名在界面上显示成乱码或方块现象切换到中文界面后检测框上的类别标签是几个方块英文显示正常中文全部是「□□□□」这样的占位符。原因cls_name_zh.yaml文件本身是 UTF-8 编码没问题我用 VSCode 打开确认过问题出在plot()方法绘制标签时用的字体。OpenCV 的putText()默认不支持中文YOLOv8 的plot()在画中文时会退化成方块。解决项目里util/fonts_opt.py就是干这个的。它做的事情是注册一个支持中文的字体文件到 OpenCV 的字体管理器然后在所有画文字的地方改用这个字体。你需要在主程序启动时调用fonts_opt.py里的初始化函数。如果你改完代码还是乱码检查一下当前环境和代码里cv2.FONT_HERSHEY_SIMPLEX这类硬编码字体是否被覆盖。这个问题是纯本地环境问题换台机器可能就没有。5.5 翻车五显存 OOM分割模式跑两张图就崩现象检测模式一切正常切到分割模式连续处理两三张高清图后终端报了CUDA out of memory。原因分割模式需要额外存储每个目标的掩码 Tensor内存占用比检测高数倍。如果你用的是 6GB 以下显存的卡默认的imgsz640跑批量推理很容易爆。解决把imgsz降到 480 或者320效果是分割边界会稍微粗糙一点但显存占用能降一半以上。另外如果你是自己写的循环在调predict()两张图之间加一行torch.cuda.empty_cache()把缓存显存释放掉。这个习惯我从那以后每次都会在代码里固定保留它对小显存卡几乎是救命级的操作。6. 进阶玩法换成自己的模型、多语言标签与批量出报告这个系统最值钱的地方不只是「开箱即用」而是你能把它快速改造成自己的模型。model_config/model_name_custom.yaml就是为你准备的入口把自己训练好的.pt权重放进去类别名文件换成自己数据集的标签下拉框里就会多出「自定义模型」的选项。你需要保证权重文件路径、task字段、类别数三者严格一致这个方法我在 3.4 节说过一次这里再强调一遍类别数对不上推理不会报错但结果会非常奇怪——比如你的模型有 5 个类别系统却用 COCO 80 类的类别名去渲染所有标签都是错位的排查起来很费劲。批量出报告这个场景我是把 FastAPI 接口和util/pdf_opt.py配合用的。先写好一个循环脚本遍历一个文件夹里的所有图片逐个请求/detect接口拿到检测框再把结果和图片拼成 PDF 报告。一个可复用的思路是不等检测全部完成而是每处理完一张就追加一页进 PDF这样即使中间某张图挂了前面生成的部分也还在不会功亏一篑。实际动手时你会感受到这个项目的价值所在它不是一个半成品 demo而是一个可以直接作为基础设施往上搭东西的框架。最后分享一个个人习惯。从前几次踩坑之后我每次拿到这类项目都强制执行三件事先看requirements.txt判断依赖年代再跑一次python -c from ultralytics import YOLO; print(ok)验证环境最后才启动主程序。这套流程看起来多余但真能过滤掉八成以上的环境类问题。希望这些实战记录能让你少走一些弯路尽早看到自己的模型在浏览器里跑起来。本文还有配套的精品资源点击获取