# Детекция YOLOv9/v10

> **Современное обнаружение объектов в реальном времени — обучайте и разворачивайте последние модели YOLO на GPU**

YOLO (You Only Look Once) по-прежнему является эталоном для обнаружения объектов в реальном времени. YOLOv9 представил Программируемую Информацию Градиента (PGI) и Обобщенную Эффективную Сеть Агрегации Слоев (GELAN), в то время как YOLOv10 привнес обнаружение без NMS с двойным назначением меток. Обе версии обеспечивают первоклассный баланс точности и скорости на GPU NVIDIA.

* **YOLOv9 GitHub:** [WongKinYiu/yolov9](https://github.com/WongKinYiu/yolov9) — 8K+ ⭐
* **YOLOv10 GitHub:** [THU-MIG/yolov10](https://github.com/THU-MIG/yolov10) — 10K+ ⭐
* **Ultralytics (объединённый):** [ultralytics/ultralytics](https://github.com/ultralytics/ultralytics) — 32K+ ⭐

***

## YOLOv9 vs YOLOv10 vs YOLOv8 — Краткое сравнение

| Модель   | mAP50-95 | Скорость (A100) | Параметры | NMS       |
| -------- | -------- | --------------- | --------- | --------- |
| YOLOv8x  | 53.9     | 14.2ms          | 68.2M     | Требуется |
| YOLOv9e  | 55.6     | 16.8ms          | 57.3M     | Требуется |
| YOLOv10x | 54.4     | 10.7ms          | 29.5M     | **Без**   |
| YOLOv10b | 53.0     | 8.8ms           | 19.1M     | **Без**   |
| YOLOv10s | 46.8     | 4.2ms           | 7.2M      | **Без**   |

{% hint style="success" %}
**YOLOv10 работает без NMS** — без этапа постобработки подавления немаксимумов. Это позволяет развертывать модель end-to-end и особенно полезно для встраиваемых/edge-сценариев и развертывания с TensorRT.
{% endhint %}

***

## Сценарии использования

* **Безопасность и наблюдение** — обнаружение людей/транспортных средств/объектов в реальном времени
* **Автономные транспортные средства** — обнаружение пешеходов и препятствий
* **Контроль качества в производстве** — обнаружение дефектов на производственных линиях
* **Аналитика ритейла** — анализ потока клиентов и обнаружение товаров
* **Медицинская визуализация** — обнаружение аномалий на рентгенах и сканах
* **Спортивная аналитика** — отслеживание игроков и мяча
* **Сельское хозяйство** — обнаружение болезней культур и вредителей

***

## Требования

* Аккаунт Clore.ai с арендой GPU
* Данные для обучения (для обучения кастомной модели) или использование предобученных весов COCO
* Базовые знания Python и командной строки

***

## Шаг 1 — Арендуйте GPU на Clore.ai

1. Перейдите на [clore.ai](https://clore.ai) → **Маркетплейс**
2. Выберите GPU в зависимости от задачи:
   * **Только инференс:** RTX 3080/3090 или RTX 4080 — отличное соотношение цена/производительность
   * **Обучение небольших моделей:** RTX 4090 24GB
   * **Обучение больших моделей (YOLOv9e/YOLOv10x):** A100 40/80GB

{% hint style="info" %}
**Для инференса в реальном времени** (видеопотоки) RTX 3090 или RTX 4090 дают 100–500 FPS в зависимости от варианта модели. Даже самая маленькая YOLOv10n работает на 4090 с TensorRT со скоростью 1000+ FPS.
{% endhint %}

***

## Шаг 2 — Разверните контейнер Ultralytics

Официальный Docker-образ Ultralytics поддерживает YOLOv8, YOLOv9 и YOLOv10 через единый API:

**Docker-образ:**

```
ultralytics/ultralytics:latest
```

**Порты:**

```
22
8000
```

**Переменные окружения:**

```
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,utility
```

**Диск:** Минимум 20 ГБ (предобученные веса + ваш датасет)

***

## Шаг 3 — Подключитесь и проверьте

```bash
ssh root@<server-ip> -p <ssh-port>

# Проверить GPU
nvidia-smi

# Проверить установку Ultralytics
python3 -c "import ultralytics; ultralytics.checks()"

# Должна отображаться информация о GPU, версии CUDA и доступности моделей
```

***

## Шаг 4 — Быстрый инференс с предобученными моделями

### Инференс YOLOv10 (без NMS)

```python
from ultralytics import YOLO
import cv2

# Загрузить модель YOLOv10 (автозагрузка, если отсутствует)
model = YOLO("yolov10x.pt")  # Варианты: n, s, m, b, l, x

# Выполнить инференс на изображении
results = model("https://ultralytics.com/images/bus.jpg")

# Показать результаты
for result in results:
    boxes = result.boxes
    print(f"Detected {len(boxes)} objects")
    for box in boxes:
        cls = int(box.cls[0])
        conf = float(box.conf[0])
        xyxy = box.xyxy[0].tolist()
        print(f"  {model.names[cls]}: {conf:.2f} at {[int(x) for x in xyxy]}")

# Сохранить аннотированное изображение
results[0].save("output.jpg")
```

### Инференс YOLOv9

```python
from ultralytics import YOLO

# Загрузить модель YOLOv9
model = YOLO("yolov9e.pt")  # Варианты: t, s, m, c, e

# Пакетный инференс для максимальной пропускной способности
results = model(
    source=[
        "image1.jpg",
        "image2.jpg",
        "image3.jpg",
    ],
    batch=8,        # Обрабатывать 8 изображений параллельно
    device="cuda",
    conf=0.25,      # Порог уверенности
    iou=0.45,       # Порог IoU для NMS (не нужен для v10)
    imgsz=640,
    half=True       # FP16 для ускорения в 2 раза
)
```

### Инференс потокового видео в реальном времени

```python
from ultralytics import YOLO
import cv2

model = YOLO("yolov10s.pt")

# Для веб-камеры (device=0) или видеофайла
cap = cv2.VideoCapture("input_video.mp4")

# Получить свойства видео
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# Видео-писатель для вывода
out = cv2.VideoWriter(
    "output_video.mp4",
    cv2.VideoWriter_fourcc(*"mp4v"),
    fps,
    (width, height)
)

frame_count = 0
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    
    results = model(frame, conf=0.25, verbose=False)
    annotated = results[0].plot()
    out.write(annotated)
    frame_count += 1
    
    if frame_count % 100 == 0:
        print(f"Processed {frame_count} frames")

cap.release()
out.release()
print("Готово! Вывод сохранён в output_video.mp4")
```

***

## Шаг 5 — Обучение собственной модели

### Подготовьте ваш набор данных

YOLO использует специфическую структуру каталогов и формат меток:

```
dataset/
├── images/
│   ├── train/          # Изображения для обучения (.jpg/.png)
│   ├── val/            # Изображения для валидации
│   └── test/           # Тестовые изображения (опционально)
└── labels/
    ├── train/          # Файлы меток (.txt)
    ├── val/
    └── test/
```

Каждый файл меток (с тем же именем, что и изображение, `.txt` расширение) содержит:

```
# class_id center_x center_y width height (все нормализованы 0-1)
0 0.512 0.334 0.256 0.412
1 0.123 0.654 0.089 0.123
```

### Создать конфигурацию датасета

```bash
cat > /workspace/custom_dataset.yaml << 'EOF'
# Конфигурация датасета
path: /workspace/dataset
train: images/train
val: images/val
test: images/test

# Количество классов
nc: 3

# Имена классов
names:
  0: person
  1: car
  2: bicycle
EOF
```

### Импорт из Roboflow (рекомендуется)

```python
# Установить Roboflow
pip install roboflow

from roboflow import Roboflow
rf = Roboflow(api_key="YOUR_API_KEY")
project = rf.workspace("your-workspace").project("your-project")
version = project.version(1)
dataset = version.download("yolov9")

# Датасет теперь находится в ./your-project-1/
```

### Обучение YOLOv10

```python
from ultralytics import YOLO

# Загрузить предобученную модель YOLOv10 (transfer learning)
model = YOLO("yolov10m.pt")  # Средний вариант — хороший баланс

results = model.train(
    data="/workspace/custom_dataset.yaml",
    epochs=100,
    imgsz=640,
    batch=16,               # Настройте под объем VRAM вашего GPU
    device="cuda",
    workers=8,
    project="/workspace/runs",
    name="yolov10_custom",
    patience=50,            # Ранняя остановка
    save=True,
    save_period=10,         # Сохранять чекпоинт каждые 10 эпох
    plots=True,
    val=True,
    augment=True,           # Аугментация данных
    degrees=10.0,
    flipud=0.0,
    fliplr=0.5,
    mosaic=1.0,
    mixup=0.1,
    copy_paste=0.1,
    lr0=0.01,
    lrf=0.01,
    momentum=0.937,
    weight_decay=0.0005,
    warmup_epochs=3.0,
    amp=True                # Автоматическая смешанная точность (FP16)
)

print(f"Обучение завершено! Лучший mAP: {results.results_dict['metrics/mAP50-95(B)']:.3f}")
```

### Обучение YOLOv9

```python
from ultralytics import YOLO

model = YOLO("yolov9e.pt")

results = model.train(
    data="/workspace/custom_dataset.yaml",
    epochs=100,
    imgsz=640,
    batch=8,               # v9e больше, требует меньшего батча
    device="cuda",
    workers=8,
    project="/workspace/runs",
    name="yolov9_custom",
    amp=True,
    optimizer="SGD",
    momentum=0.937,
    weight_decay=0.0005
)
```

{% hint style="info" %}
**Советы по обучению:**

* **Размер батча:** Начните с `batch=16` для RTX 4090, `batch=32` для A100 40GB
* **Размер изображения:** `imgsz=640` это стандарт; используйте 1280 для задач с высоким разрешением
* **Эпохи:** 100 эпох обычно для тонкой настройки, 300+ для обучения с нуля
* **AMP (смешанная точность):** Всегда включайте `amp=True` для ускорения в 1.5–2 раза
  {% endhint %}

***

## Шаг 6 — Экспорт в TensorRT для максимальной скорости

```python
from ultralytics import YOLO

# Загрузить обученную модель
model = YOLO("/workspace/runs/yolov10_custom/weights/best.pt")

# Экспорт в TensorRT (FP16 для лучшего баланса скорости и точности)
model.export(
    format="engine",        # TensorRT engine
    device="cuda",
    half=True,              # FP16
    dynamic=False,          # Статические формы для максимальной оптимизации TRT
    batch=1,                # Оптимизация под batch size 1 (реальное время)
    imgsz=640,
    workspace=4             # TRT workspace в ГБ
)
# Сохранено как: best.engine

# Загрузить и запустить TRT-движок
trt_model = YOLO("best.engine")
results = trt_model("image.jpg")
```

### Экспорт в ONNX

```python
# Экспорт в ONNX для гибкости развертывания
model.export(
    format="onnx",
    opset=17,
    half=True,              # FP16 веса
    dynamic=True,           # Динамический размер батча
    simplify=True
)
```

***

## Шаг 7 — Подать как REST API

```bash
pip install fastapi uvicorn python-multipart

cat > /workspace/yolo_api.py << 'EOF'
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse, FileResponse
from ultralytics import YOLO
from PIL import Image
import io
import uuid
import os

app = FastAPI(title="YOLOv10 Detection API")
model = YOLO("yolov10x.pt")

@app.get("/health")
async def health():
    return {"status": "ok", "model": "yolov10x", "device": "cuda"}

@app.post("/detect")
async def detect(
    file: UploadFile = File(...),
    conf: float = 0.25,
    iou: float = 0.45,
    return_image: bool = False
):
    # Прочитать загруженное изображение
    image_data = await file.read()
    img = Image.open(io.BytesIO(image_data)).convert("RGB")
    
    # Выполнить детекцию
    results = model(img, conf=conf, iou=iou, verbose=False)
    result = results[0]
    
    # Построить ответ
    detections = []
    for box in result.boxes:
        detections.append({
            "class": model.names[int(box.cls[0])],
            "confidence": round(float(box.conf[0]), 4),
            "bbox": [round(x, 2) for x in box.xyxy[0].tolist()],
            "class_id": int(box.cls[0])
        })
    
    response = {
        "count": len(detections),
        "detections": detections,
        "image_size": list(result.orig_shape)
    }
    
    if return_image:
        output_path = f"/tmp/{uuid.uuid4()}.jpg"
        result.save(filename=output_path)
        return FileResponse(output_path, media_type="image/jpeg")
    
    return JSONResponse(response)

@app.post("/detect/batch")
async def detect_batch(files: list[UploadFile] = File(...)):
    results = []
    for file in files:
        data = await file.read()
        img = Image.open(io.BytesIO(data)).convert("RGB")
        res = model(img, verbose=False)[0]
        results.append({
            "filename": file.filename,
            "count": len(res.boxes),
            "detections": [
                {"class": model.names[int(b.cls[0])], "conf": float(b.conf[0])}
                for b in res.boxes
            ]
        })
    return JSONResponse({"results": results})

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
EOF

python3 /workspace/yolo_api.py &

# Протестировать API
curl -X POST "http://localhost:8000/detect" \
    -F "file=@test_image.jpg" | python3 -m json.tool
```

***

## Шаг 8 — Валидировать и провести бенчмарк модели

```python
from ultralytics import YOLO

model = YOLO("yolov10x.pt")

# Валидация на датасете COCO
metrics = model.val(
    data="coco.yaml",
    imgsz=640,
    batch=32,
    device="cuda",
    half=True
)

print(f"mAP50:    {metrics.box.map50:.3f}")
print(f"mAP50-95: {metrics.box.map:.3f}")
print(f"Precision: {metrics.box.mp:.3f}")
print(f"Recall:    {metrics.box.mr:.3f}")

# Тест скорости
model.benchmark(
    format="engine",   # Сравнить несколько форматов экспорта
    imgsz=640,
    half=True,
    device="cuda"
)
```

***

## Скачать результаты

```bash
# С вашей локальной машины:
scp -P <ssh-port> root@<server-ip>:/workspace/runs/yolov10_custom/weights/best.pt ./
scp -P <ssh-port> root@<server-ip>:/workspace/output_video.mp4 ./

# Скачать весь прогон обучения
rsync -avz -e "ssh -p <ssh-port>" \
    root@<server-ip>:/workspace/runs/ \
    ./yolo_training_runs/
```

***

## Устранение неполадок

### Ошибка CUDA Out of Memory во время обучения

```python
# Уменьшите размер батча
model.train(data="data.yaml", batch=4, imgsz=640)

# Или включить gradient checkpointing
model.train(data="data.yaml", batch=8, imgsz=640, cache=False)
```

### Медленная скорость обучения

```python
# Включите кеширование (загружает датасет в RAM/GPU)
model.train(data="data.yaml", cache=True)  # Кеш в RAM
model.train(data="data.yaml", cache="disk")  # Кеш на диск

# Увеличьте число workers (внимание: слишком много может замедлить)
model.train(data="data.yaml", workers=8)
```

### Низкий mAP / Плохое обнаружение

```bash
# Убедитесь, что метки корректны (нормализованы, в пределах 0-1)
python3 -c "
from ultralytics.data.utils import check_det_dataset
check_det_dataset('custom_dataset.yaml')
"

# Визуализировать образцы обучения
python3 -c "
from ultralytics import YOLO
model = YOLO('yolov10m.pt')
model.train(data='data.yaml', epochs=1, batch=4, plots=True)
# Проверьте /workspace/runs/train/exp/train_batch*.jpg
"
```

***

## Справочные показатели производительности (GPU Clore.ai)

| Модель       | GPU      | Батч | FPS (инференс) | mAP50-95 |
| ------------ | -------- | ---- | -------------- | -------- |
| YOLOv10n     | RTX 3090 | 1    | 1,200          | 38.5     |
| YOLOv10s     | RTX 3090 | 1    | 780            | 46.8     |
| YOLOv10m     | RTX 4090 | 1    | 950            | 51.3     |
| YOLOv10x     | RTX 4090 | 1    | 380            | 54.4     |
| YOLOv9e      | A100 40G | 1    | 720            | 55.6     |
| YOLOv10x TRT | RTX 4090 | 1    | 920            | 54.2     |

***

## Дополнительные ресурсы

* [Документация Ultralytics](https://docs.ultralytics.com/)
* [Статья YOLOv9](https://arxiv.org/abs/2402.13616)
* [Статья YOLOv10](https://arxiv.org/abs/2405.14458)
* [Roboflow Universe](https://universe.roboflow.com/) — 100K+ публичных датасетов
* [Ultralytics HUB](https://hub.ultralytics.com/) — Облачная платформа для обучения
* [Датасет COCO](https://cocodataset.org/) — Стандартный эталонный датасет

***

*YOLOv9 и YOLOv10 на арендуемых GPU Clore.ai предоставляют доступный путь для обучения пользовательских моделей обнаружения объектов и развёртывания конвейеров инференса в реальном времени — без накладных расходов AWS SageMaker или Google Vertex AI.*

***

## Рекомендации Clore.ai по GPU

| Сценарий использования      | Рекомендуемый GPU | Примерная стоимость на Clore.ai |
| --------------------------- | ----------------- | ------------------------------- |
| Разработка/Тестирование     | RTX 3090 (24GB)   | \~$0.12/gpu/hr                  |
| Производственный инференс   | RTX 4090 (24GB)   | \~$0.70/gpu/hr                  |
| Обучение с большими батчами | A100 80GB         | \~$1.20/gpu/hr                  |

> 💡 Все примеры в этом руководстве можно развернуть на [Clore.ai](https://clore.ai/marketplace) GPU-серверах. Просматривайте доступные GPU и арендуйте по часам — без обязательств, с полным root-доступом.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-ru/kompyuternoe-zrenie/yolov9-v10.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
