系统要求

  • Ubuntu 22.04/20.04 (x86_64/amd64)
  • Docker
  • Nvidia Driver
  • Nvidia Container Toolkit

部署及HTTPS配置

  • clone项目
git clone https://github.com/cvat-ai/cvat
cd cvat
  • 配置域名及ACME邮箱
echo "export CVAT_HOST=<域名>" >> env.sh 
echo "export ACME_EMAIL=<ACME通知邮箱>" >> env.sh
source env.sh
  • 启动
source env.sh
docker compose -f docker-compose.yml -f docker-compose.https.yml -f components/serverless/docker-compose.serverless.yml up -d

cvat 端口 80/443 nuclio 端口 8070

  • 停止
source env.sh
docker compose -f docker-compose.yml -f docker-compose.https.yml -f components/serverless/docker-compose.serverless.yml down

安装nuctl

官方参考文档

  • 查看版本
cat components/serverless/docker-compose.serverless.yml | grep image
  • 下载(比如1.13.0)
version=1.13.0
wget https://github.com/nuclio/nuclio/releases/download/${version}/nuctl-${version}-linux-amd64
sudo chmod +x nuctl-${version}-linux-amd64
sudo ln -sf $(pwd)/nuctl-${version}-linux-amd64 /usr/local/bin/nuctl
# 确认是否生效
nuctl version
  • 部署函数(将自动在nuclio上创建cvat项目)
./serverless/deploy_cpu.sh serverless/openvino/dextr
./serverless/deploy_cpu.sh serverless/openvino/omz/public/yolo-v3-tf

添加自训练模型用于自动标注

serverless目录下创建 自定义函数目录,这里以自训练的YOLO11目标检测模型为例

mkdir -p serverless/pytorch/ultralytics/yolo11/nuclio

创建镜像构建文件function-gpu.yaml

metadata:
  name: rescue-element-detector
  namespace: cvat
  annotations:
    name: 救援人车合影要素检测 v1
    type: detector
    framework: pytorch
    spec: |
      [
        { "id": 0, "name": "SafetyVest", "type": "rectangle" },
        { "id": 1, "name": "Person", "type": "rectangle" },
        { "id": 2, "name": "Car", "type": "rectangle" },
        { "id": 3, "name": "LicencePlate", "type": "rectangle" }
      ]

spec:
  description: 道路救援人车合影要素检测
  runtime: "python:3.9"
  handler: main:handler
  eventTimeout: 30s

  build:
    image: cvat.pth.yolo11.rescue-element-detector:latest-gpu
    baseImage: python:3.9
    directives:
      preCopy:
        - kind: ENV
          value: DEBIAN_FRONTEND=noninteractive
        - kind: RUN
          value: apt-get update && apt install -y libgl1-mesa-glx && apt-get clean
        - kind: RUN
          value: pip install ultralytics torch torchvision opencv-python-headless && pip cache purge

  triggers:
    myHttpTrigger:
      numWorkers: 1
      kind: 'http'
      workerAvailabilityTimeoutMilliseconds: 10000
      attributes:
        # Set value from the calculation of tracking of 100 objects at the same time on a 4k image
        maxRequestBodySize: 268435456 # 256MB

  volumes:
    - volume:
        name: model-volume
        hostPath:
          path: /root/cvat/models/rescue-element-detection/best.pt  # 可选:如果使用HostPath挂载模型
      volumeMount:
        name: model-volume
        mountPath: /opt/nuclio/best.pt

  resources:
    limits:
      nvidia.com/gpu: 1

  platform:
    attributes:
      restartPolicy:
        name: always
        maximumRetryCount: 3
      mountMode: volume

创建函数入口文件main.py

import json
import base64
# from PIL import Image
import io
from model_handler import ModelHandler

def init_context(context):
    context.logger.info("Init context...  0%")

    context.logger.info("Initializing RescueElementDetection model...")
    context.user_data.model_handler = ModelHandler()

    context.logger.info("Init context...100%")

def handler(context, event):
    context.logger.info("Run RescueElementDetection model")
    data = event.body
    image_data = base64.b64decode(data["image"])
    threshold = float(data.get("threshold", 0.5))

    results = context.user_data.model_handler.infer(image_data, threshold)

    return context.Response(body=json.dumps(results), headers={},
        content_type='application/json', status_code=200)

创建推理函数文件model_handler.py

import io
from PIL import Image
from ultralytics import YOLO


class ModelHandler:
    def __init__(self):
        """加载 YOLOv11 模型"""
        self.model = YOLO("/opt/nuclio/best.pt")  # 确保路径正确

    def infer(self, image_data, threshold=0.3):
        """
        执行推理
        :param image_data: 图片的二进制数据
        :param threshold: 置信度阈值(默认0.3)
        :return: 符合阈值的检测结果
        """
        image = Image.open(io.BytesIO(image_data))
        results = self.model(image)

        detections = []
        for result in results:
            for box in result.boxes.data.tolist():
                x1, y1, x2, y2, score, class_id = box
                if score >= threshold:  # 过滤低置信度目标
                    detections.append({
                        "confidence": score,
                        "label": self.model.names[int(class_id)],
                        "points": [x1, y1, x2, y2],
                        "type": "rectangle",
                    })

        return detections

部署自定义函数

./serverless/deploy_gpu.sh serverless/pytorch/ultralytics/yolo11

至此,不出意外的话 CVAT标注页面魔棒按钮已经可以使用。