YOLO模型集成到Label Studio的MODEL服务

将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连接模型服务
  1. 启动Label Studio:

    bash 复制代码
    label-studio start my_label_project
  2. 新建/打开标注项目,进入「Settings」→「Model」→「Add Model」;

  3. 填写模型服务配置:

    • Title:自定义(如YOLOv8 Model)
    • URL :模型服务的预测接口地址(http://localhost:8000/predict
    • Label Studio URL :Label Studio的地址(http://localhost:8080,默认端口)
    • Model version:自定义(如yolov8n)
  4. 点击「Validate and Save」,验证连接成功后保存。

步骤6:测试自动标注

在Label Studio中上传图片,进入标注界面,点击右侧「Model」→「Run Model」,即可看到YOLO模型自动标注的检测框。

二、代码关键部分解释

  1. 模型加载YOLO("yolov8n.pt")加载预训练模型,若你有自定义训练的模型,替换为模型文件路径(如./runs/detect/train/weights/best.pt)即可;
  2. 图片解析get_image_from_source兼容URL和base64两种图片格式,覆盖Label Studio的常见图片传入方式;
  3. 坐标转换 :YOLO返回的是绝对像素的xyxy格式,需转换为Label Studio要求的「相对百分比」的x,y,width,height格式,这是核心转换逻辑;
  4. 异常处理:接口包含基础的异常捕获,避免单个任务失败导致整个服务崩溃。

三、注意事项

  1. 若Label Studio和模型服务不在同一机器,需将host="0.0.0.0"保留,并确保端口(8000)可访问;

  2. Label Studio的标注配置需包含rectanglelabels类型(否则无法显示标注框),标注配置示例:

    json 复制代码
    {
      "labels": ["person", "car", "bike"],
      "type": "rectanglelabels",
      "toName": "image",
      "fromName": "label"
    }
  3. 若模型推理速度慢,可调整YOLO模型大小(如yolov8s.ptyolov8n.pt),或开启GPU加速(需安装CUDA版本的PyTorch)。

第二步 把本地环境打包成docker包部署服务端

将集成YOLO模型的Label Studio运行环境打包成Docker镜像,部署环境可直接复用。

核心步骤

  1. Dockerfile核心步骤:基础镜像→系统依赖→Python依赖→复制代码→暴露端口→启动脚本;
  2. 构建运行关键:挂载数据目录持久化标注数据,GPU版需配置NVIDIA Docker;
  3. 服务访问: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"]

二、关键说明

  1. 基础镜像选择python:3.9-slim 是轻量级镜像,比完整的Python镜像小很多,适合部署;若需要GPU加速,需替换为nvidia/cuda:12.1.0-cudnn8-runtime-ubuntu22.04(需提前安装NVIDIA Docker运行时)。
  2. 系统依赖安装libgl1-mesa-glxlibglib2.0-0 是YOLO运行时必须的,缺少会导致ImportError: libGL.so.1: cannot open shared object file错误。
  3. 依赖安装优化 :使用清华PyPI镜像源加速安装,--no-cache-dir 减少镜像体积。
  4. 启动方式 :通过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)。

四、自定义扩展(可选)

  1. 加载自定义YOLO模型 :将训练好的best.pt复制到目录中,在Dockerfile中添加COPY best.pt .,并修改yolo_labelstudio_service.py中的模型路径为./best.pt
  2. 修改端口 :若8080/8000端口被占用,可修改Dockerfile中的EXPOSE和启动脚本中的端口,或运行时映射到其他端口(如-p 8081:8080);
  3. GPU加速 :需先安装NVIDIA Docker运行时,再修改基础镜像为CUDA版本,并在requirements.txt中添加对应版本的PyTorch(参考注释中的torch/torchvision)。
相关推荐
孤狼warrior5 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
水中加点糖7 小时前
小白都能看懂的——车牌检测与识别(最新版YOLO26快速入门)
人工智能·yolo·目标检测·计算机视觉·ai·车牌识别·lprnet
前端摸鱼匠19 小时前
YOLOv8 环境配置全攻略:Python、PyTorch 与 CUDA 的和谐共生
人工智能·pytorch·python·yolo·目标检测
2501_9413297221 小时前
改进YOLOv8-seg-act__鸡只计数检测实战
yolo
weixin_395448911 天前
mult_yolov5_post_copy.c_cursor_0205
c语言·python·yolo
王锋(oxwangfeng)1 天前
YOLOWorld 实现开集障碍物检测
yolo
喵叔哟1 天前
02-YOLO-v8-v9-v10工程差异对比
人工智能·yolo·机器学习
2501_941333102 天前
数字识别与检测_YOLOv3_C3k2改进模型解析
人工智能·yolo·目标跟踪
xsc-xyc2 天前
RuntimeError: Dataset ‘/data.yaml‘ error ❌ ‘_lz
人工智能·深度学习·yolo·计算机视觉·视觉检测