系统要求
- 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标注页面魔棒按钮已经可以使用。