将YOLO模型集成到Label Studio中作为其MODEL服务,实现自动标注功能,
第一步 本地环境跑通服务
一、整体部署流程
Label Studio的MODEL服务本质是一个遵循其规范的REST API服务,YOLO模型通过该API接收Label Studio的图片标注请求,推理后返回标注结果。整体流程如下:
步骤1:环境准备
安装必要的依赖包(建议在虚拟环境中操作):
bash
# 安装Label Studio(用于标注平台)
pip install label-studio
# 安装YOLO(以ultralytics的YOLOv8为例,最常用)
pip install ultralytics
# 安装API服务依赖(FastAPI轻量高性能,uvicorn作为服务器)
pip install fastapi uvicorn python-multipart requests pillow
步骤2:理解Label Studio与模型服务的交互规范
-
请求格式 :Label Studio向模型服务发送POST请求,Body包含
tasks数组(每个task是待标注的图片任务),核心字段:json{ "tasks": [ { "id": 1, "data": { "image": "https://xxx/xxx.jpg" // 图片URL或base64格式(data:image/jpeg;base64,...) } } ] } -
响应格式 :模型服务需返回符合Label Studio标注格式的JSON,核心字段:
json{ "predictions": [ { "result": [ { "id": "random-id", "type": "rectanglelabels", // Label Studio的矩形标注类型 "value": { "x": 10.5, // 左上角x坐标(相对值,0-100) "y": 20.3, // 左上角y坐标(相对值,0-100) "width": 15.2, // 宽度(相对值,0-100) "height": 25.6, // 高度(相对值,0-100) "labels": ["person"] // 检测到的类别 }, "score": 0.95 // 置信度 } ], "score": 0.95, // 整体置信度 "model_version": "yolov8n" // 模型版本 } ] }
步骤3:编写YOLO模型服务接口代码
创建yolo_labelstudio_service.py文件,实现完整的API服务:
python
import os
import uuid
import requests
from PIL import Image
from io import BytesIO
from fastapi import FastAPI, Request
from ultralytics import YOLO
# 初始化FastAPI应用
app = FastAPI(title="YOLO Label Studio Model Service")
# 加载YOLO模型(替换为你的模型路径,如自定义训练的best.pt)
model = YOLO("yolov8n.pt") # 内置预训练模型,也可替换为本地路径
# 工具函数:从URL或base64获取图片
def get_image_from_source(source: str) -> Image.Image:
"""
解析Label Studio传入的图片源(URL或base64),返回PIL Image对象
"""
if source.startswith("data:image/"):
# 处理base64格式
import base64
base64_data = source.split(",")[1]
image_data = base64.b64decode(base64_data)
img = Image.open(BytesIO(image_data)).convert("RGB")
else:
# 处理URL格式
response = requests.get(source, timeout=10)
response.raise_for_status()
img = Image.open(BytesIO(response.content)).convert("RGB")
return img
# 工具函数:YOLO结果转换为Label Studio格式
def yolo2labelstudio(result, img_width, img_height) -> list:
"""
将YOLO的检测结果转换为Label Studio的标注格式
:param result: YOLO推理结果(单个图片的结果)
:param img_width: 图片宽度(像素)
:param img_height: 图片高度(像素)
:return: Label Studio的result数组
"""
labelstudio_results = []
# 遍历每个检测框
for box in result.boxes:
# YOLO返回的是xyxy(左上角x,y,右下角x,y)绝对像素值
x1, y1, x2, y2 = box.xyxy[0].tolist()
# 转换为Label Studio的相对值(0-100)
x = (x1 / img_width) * 100
y = (y1 / img_height) * 100
width = ((x2 - x1) / img_width) * 100
height = ((y2 - y1) / img_height) * 100
# 获取类别和置信度
cls_id = int(box.cls[0])
cls_name = result.names[cls_id]
score = float(box.conf[0])
# 构造Label Studio标注项
labelstudio_results.append({
"id": str(uuid.uuid4()), # 唯一ID
"type": "rectanglelabels", # 矩形标注类型(需与Label Studio标注配置匹配)
"value": {
"x": round(x, 2),
"y": round(y, 2),
"width": round(width, 2),
"height": round(height, 2),
"labels": [cls_name]
},
"score": round(score, 4)
})
return labelstudio_results
# 核心接口:接收Label Studio的标注请求
@app.post("/predict")
async def predict(request: Request):
"""
Label Studio调用的核心预测接口
"""
try:
# 解析请求体
req_data = await request.json()
tasks = req_data.get("tasks", [])
predictions = []
# 处理每个任务
for task in tasks:
task_id = task.get("id")
image_source = task.get("data", {}).get("image")
if not image_source:
continue
# 1. 获取图片
img = get_image_from_source(image_source)
img_width, img_height = img.size
# 2. YOLO模型推理
results = model(img) # 推理结果是列表,每个元素对应一张图片
result = results[0] # 本次只处理单张图片
# 3. 转换为Label Studio格式
ls_result = yolo2labelstudio(result, img_width, img_height)
# 4. 构造预测结果
predictions.append({
"result": ls_result,
"score": round(sum([item["score"] for item in ls_result]) / len(ls_result), 4) if ls_result else 0.0,
"model_version": "yolov8n",
"task_id": task_id
})
# 返回符合Label Studio要求的响应
return {"predictions": predictions}
except Exception as e:
# 异常处理,返回友好提示
return {"error": str(e), "predictions": []}
# 启动服务(直接运行该文件时生效)
if __name__ == "__main__":
import uvicorn
# 启动服务,监听所有IP,端口8000(可自定义)
uvicorn.run(app, host="0.0.0.0", port=8000)
步骤4:启动YOLO模型服务
运行上述代码,启动API服务:
bash
python yolo_labelstudio_service.py
服务启动后,可通过http://localhost:8000/docs访问FastAPI的自动文档,测试/predict接口是否正常。
步骤5:配置Label Studio连接模型服务
-
启动Label Studio:
bashlabel-studio start my_label_project -
新建/打开标注项目,进入「Settings」→「Model」→「Add Model」;
-
填写模型服务配置:
- Title:自定义(如YOLOv8 Model)
- URL :模型服务的预测接口地址(
http://localhost:8000/predict) - Label Studio URL :Label Studio的地址(
http://localhost:8080,默认端口) - Model version:自定义(如yolov8n)
-
点击「Validate and Save」,验证连接成功后保存。
步骤6:测试自动标注
在Label Studio中上传图片,进入标注界面,点击右侧「Model」→「Run Model」,即可看到YOLO模型自动标注的检测框。
二、代码关键部分解释
- 模型加载 :
YOLO("yolov8n.pt")加载预训练模型,若你有自定义训练的模型,替换为模型文件路径(如./runs/detect/train/weights/best.pt)即可; - 图片解析 :
get_image_from_source兼容URL和base64两种图片格式,覆盖Label Studio的常见图片传入方式; - 坐标转换 :YOLO返回的是绝对像素的
xyxy格式,需转换为Label Studio要求的「相对百分比」的x,y,width,height格式,这是核心转换逻辑; - 异常处理:接口包含基础的异常捕获,避免单个任务失败导致整个服务崩溃。
三、注意事项
-
若Label Studio和模型服务不在同一机器,需将
host="0.0.0.0"保留,并确保端口(8000)可访问; -
Label Studio的标注配置需包含
rectanglelabels类型(否则无法显示标注框),标注配置示例:json{ "labels": ["person", "car", "bike"], "type": "rectanglelabels", "toName": "image", "fromName": "label" } -
若模型推理速度慢,可调整YOLO模型大小(如
yolov8s.pt→yolov8n.pt),或开启GPU加速(需安装CUDA版本的PyTorch)。
第二步 把本地环境打包成docker包部署服务端
将集成YOLO模型的Label Studio运行环境打包成Docker镜像,部署环境可直接复用。
核心步骤
- Dockerfile核心步骤:基础镜像→系统依赖→Python依赖→复制代码→暴露端口→启动脚本;
- 构建运行关键:挂载数据目录持久化标注数据,GPU版需配置NVIDIA Docker;
- 服务访问:Label Studio在8080端口,模型服务在8000端口,配置时确保URL正确。
一、文件准备
首先在本地创建如下目录结构(方便Docker构建):
yolo-labelstudio/
├── Dockerfile # 核心构建文件
├── requirements.txt # Python依赖清单
└── yolo_labelstudio_service.py # 之前的模型服务代码
1. 编写requirements.txt(统一管理Python依赖)
将所有需要的Python包列出来,避免Dockerfile中依赖安装混乱:
txt
# 基础依赖
python==3.9.18
label-studio==1.11.0
ultralytics==8.2.2
fastapi==0.110.0
uvicorn==0.27.0
python-multipart==0.0.9
requests==2.31.0
Pillow==10.2.0
# 可选:若需要GPU加速,需添加对应PyTorch(下文会说明)
# torch==2.2.0+cu121
# torchvision==0.17.0+cu121
2. 编写Dockerfile
dockerfile
# 选择基础镜像(Python 3.9 slim轻量版,兼容大部分环境)
FROM python:3.9-slim
# 维护者信息(可选)
LABEL maintainer="your-name <your-email>"
# 设置工作目录
WORKDIR /app
# 安装系统依赖(解决YOLO/OpenCV运行时的库依赖问题)
# libgl1-mesa-glx:OpenCV图形依赖
# libglib2.0-0:PIL图片处理依赖
# gcc/g++:部分Python包编译需要
RUN apt-get update && apt-get install -y --no-install-recommends \
libgl1-mesa-glx \
libglib2.0-0 \
gcc \
g++ \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖清单并安装Python包(先复制requirements.txt,利用Docker缓存)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制模型服务代码到工作目录
COPY yolo_labelstudio_service.py .
# 暴露端口:8000(YOLO模型服务)、8080(Label Studio)
EXPOSE 8000 8080
# 设置环境变量(可选,防止Python输出缓冲)
ENV PYTHONUNBUFFERED=1
# 启动脚本:同时启动YOLO模型服务和Label Studio(用shell脚本更优雅)
# 先创建启动脚本内容,再执行
RUN echo '#!/bin/bash\n\
# 后台启动YOLO模型服务\n\
uvicorn yolo_labelstudio_service:app --host 0.0.0.0 --port 8000 &\n\
# 前台启动Label Studio(保证容器不退出)\n\
label-studio start my_yolo_project --host 0.0.0.0 --port 8080' > /app/start.sh
# 赋予启动脚本执行权限
RUN chmod +x /app/start.sh
# 容器启动时执行的命令
CMD ["/app/start.sh"]
二、关键说明
- 基础镜像选择 :
python:3.9-slim是轻量级镜像,比完整的Python镜像小很多,适合部署;若需要GPU加速,需替换为nvidia/cuda:12.1.0-cudnn8-runtime-ubuntu22.04(需提前安装NVIDIA Docker运行时)。 - 系统依赖安装 :
libgl1-mesa-glx和libglib2.0-0是YOLO运行时必须的,缺少会导致ImportError: libGL.so.1: cannot open shared object file错误。 - 依赖安装优化 :使用清华PyPI镜像源加速安装,
--no-cache-dir减少镜像体积。 - 启动方式 :通过shell脚本同时启动YOLO模型服务(后台)和Label Studio(前台),保证容器不退出;若只需要模型服务,可修改启动命令为
uvicorn yolo_labelstudio_service:app --host 0.0.0.0 --port 8000。
三、镜像构建与运行
1. 构建Docker镜像
在yolo-labelstudio目录下执行以下命令(替换yolo-labelstudio:v1为自定义镜像名):
bash
docker build -t yolo-labelstudio:v1 .
- 构建过程中会自动安装系统依赖、Python依赖,复制代码文件,耗时约5-10分钟(取决于网络)。
2. 运行Docker容器
bash
# 基础版(CPU运行)
docker run -d \
--name yolo-labelstudio \
-p 8080:8080 \
-p 8000:8000 \
-v $(pwd)/label-studio-data:/app/my_yolo_project \ # 挂载数据目录,持久化标注数据
yolo-labelstudio:v1
# GPU版(需安装NVIDIA Docker)
docker run -d \
--name yolo-labelstudio-gpu \
--gpus all \
-p 8080:8080 \
-p 8000:8000 \
-v $(pwd)/label-studio-data:/app/my_yolo_project \
yolo-labelstudio:v1
参数说明:
-d:后台运行容器;--name:自定义容器名;-p:端口映射(主机端口:容器端口);-v:挂载数据目录,防止容器删除后标注数据丢失;--gpus all:分配所有GPU给容器(仅GPU版需要)。
3. 访问服务
- Label Studio:浏览器访问
http://localhost:8080,首次登录需创建账号; - YOLO模型服务文档:访问
http://localhost:8000/docs,可测试/predict接口; - 模型配置:在Label Studio中添加模型服务时,URL填写
http://localhost:8000/predict(容器内可写http://127.0.0.1:8000/predict)。
四、自定义扩展(可选)
- 加载自定义YOLO模型 :将训练好的
best.pt复制到目录中,在Dockerfile中添加COPY best.pt .,并修改yolo_labelstudio_service.py中的模型路径为./best.pt; - 修改端口 :若8080/8000端口被占用,可修改Dockerfile中的
EXPOSE和启动脚本中的端口,或运行时映射到其他端口(如-p 8081:8080); - GPU加速 :需先安装NVIDIA Docker运行时,再修改基础镜像为CUDA版本,并在
requirements.txt中添加对应版本的PyTorch(参考注释中的torch/torchvision)。