# Detección YOLOv9/v10

> **Detección de objetos en tiempo real de vanguardia — entrena y despliega los últimos modelos YOLO en GPU**

YOLO (You Only Look Once) sigue siendo el estándar de oro para la detección de objetos en tiempo real. YOLOv9 introdujo Información de Gradiente Programable (PGI) y la Red de Agregación de Capas Eficiente Generalizada (GELAN), mientras que YOLOv10 trajo detección sin NMS con asignaciones de etiquetas duales. Ambos ofrecen compensaciones de precisión/velocidad de primer nivel en GPUs NVIDIA.

* **YOLOv9 GitHub:** [WongKinYiu/yolov9](https://github.com/WongKinYiu/yolov9) — 8K+ ⭐
* **YOLOv10 GitHub:** [THU-MIG/yolov10](https://github.com/THU-MIG/yolov10) — 10K+ ⭐
* **Ultralytics (unificado):** [ultralytics/ultralytics](https://github.com/ultralytics/ultralytics) — 32K+ ⭐

***

## YOLOv9 vs YOLOv10 vs YOLOv8 — Comparación rápida

| Modelo   | mAP50-95 | Velocidad (A100) | Parámetros | NMS       |
| -------- | -------- | ---------------- | ---------- | --------- |
| YOLOv8x  | 53.9     | 14.2ms           | 68.2M      | Requerido |
| YOLOv9e  | 55.6     | 16.8ms           | 57.3M      | Requerido |
| YOLOv10x | 54.4     | 10.7ms           | 29.5M      | **Libre** |
| YOLOv10b | 53.0     | 8.8ms            | 19.1M      | **Libre** |
| YOLOv10s | 46.8     | 4.2ms            | 7.2M       | **Libre** |

{% hint style="success" %}
**YOLOv10 es sin NMS** — sin la etapa de Supresión de Máximos No Máximos en el post-procesado. Esto permite un despliegue de extremo a extremo y es particularmente beneficioso para escenarios de edge/embebidos y despliegues con TensorRT.
{% endhint %}

***

## Casos de uso

* **Seguridad y vigilancia** — detección en tiempo real de personas/vehículos/objetos
* **Vehículos autónomos** — detección de peatones y obstáculos
* **Control de calidad en manufactura** — detección de defectos en líneas de producción
* **Analítica minorista** — flujo de clientes y detección de productos
* **Imágenes médicas** — detección de anomalías en radiografías y escaneos
* **Analítica deportiva** — seguimiento de jugadores y pelota
* **Agricultura** — detección de enfermedades de cultivos y plagas

***

## Prerrequisitos

* Cuenta de Clore.ai con alquiler de GPU
* Datos de entrenamiento (para entrenar un modelo personalizado) o usar pesos preentrenados de COCO
* Conocimientos básicos de Python y línea de comandos

***

## Paso 1 — Alquila una GPU en Clore.ai

1. Ve a [clore.ai](https://clore.ai) → **Marketplace**
2. Elige la GPU según tu tarea:
   * **Solo inferencia:** RTX 3080/3090 o RTX 4080 — excelente relación precio/rendimiento
   * **Entrenamiento de modelos pequeños:** RTX 4090 24GB
   * **Entrenamiento de modelos grandes (YOLOv9e/YOLOv10x):** A100 40/80GB

{% hint style="info" %}
**Para inferencia en tiempo real** (flujos de video), la RTX 3090 o la RTX 4090 ofrecen 100–500 FPS dependiendo de la variante del modelo. Incluso la más pequeña YOLOv10n funciona a más de 1000 FPS en una 4090 con TensorRT.
{% endhint %}

***

## Paso 2 — Desplegar el contenedor de Ultralytics

La imagen Docker oficial de Ultralytics admite YOLOv8, YOLOv9 y YOLOv10 a través de una API unificada:

**Imagen Docker:**

```
ultralytics/ultralytics:latest
```

**Puertos:**

```
22
8000
```

**Variables de entorno:**

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

**Disco:** 20GB mínimo (pesos preentrenados + tu conjunto de datos)

***

## Paso 3 — Conectar y verificar

```bash
ssh root@<ip-del-servidor> -p <puerto-ssh>

# Comprobar GPU
nvidia-smi

# Comprobar instalación de Ultralytics
python3 -c "import ultralytics; ultralytics.checks()"

# Debería mostrar información de la GPU, versión de CUDA y disponibilidad de modelos
```

***

## Paso 4 — Inferencia rápida con modelos preentrenados

### Inferencia YOLOv10 (sin NMS)

```python
from ultralytics import YOLO
import cv2

# Cargar el modelo YOLOv10 (descarga automática si no está presente)
model = YOLO("yolov10x.pt")  # Opciones: n, s, m, b, l, x

# Ejecutar inferencia en una imagen
results = model("https://ultralytics.com/images/bus.jpg")

# Mostrar resultados
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]}")

# Guardar imagen anotada
results[0].save("output.jpg")
```

### Inferencia YOLOv9

```python
from ultralytics import YOLO

# Cargar el modelo YOLOv9
model = YOLO("yolov9e.pt")  # Opciones: t, s, m, c, e

# Inferencia por lotes para máximo rendimiento
results = model(
    source=[
        "image1.jpg",
        "image2.jpg",
        "image3.jpg",
    ],
    batch=8,        # Procesar 8 imágenes en paralelo
    device="cuda",
    conf=0.25,      # Umbral de confianza
    iou=0.45,       # Umbral IoU para NMS (no necesario para v10)
    imgsz=640,
    half=True       # FP16 para 2x de aceleración
)
```

### Inferencia en flujo de video en tiempo real

```python
from ultralytics import YOLO
import cv2

model = YOLO("yolov10s.pt")

# Para webcam (device=0) o archivo de video
cap = cv2.VideoCapture("input_video.mp4")

# Obtener propiedades del video
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))

# Escritor de salida
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("¡Hecho! Salida guardada en output_video.mp4")
```

***

## Paso 5 — Entrenar un modelo personalizado

### Prepara tu conjunto de datos

YOLO usa una estructura de directorios y un formato de etiquetas específicos:

```
dataset/
├── images/
│   ├── train/          # Imágenes de entrenamiento (.jpg/.png)
│   ├── val/            # Imágenes de validación
│   └── test/           # Imágenes de prueba (opcional)
└── labels/
    ├── train/          # Archivos de etiquetas (.txt)
    ├── val/
    └── test/
```

Cada archivo de etiqueta (mismo nombre que la imagen, `.txt` extensión) contiene:

```
# class_id center_x center_y width height (todos normalizados 0-1)
0 0.512 0.334 0.256 0.412
1 0.123 0.654 0.089 0.123
```

### Crear configuración del conjunto de datos

```bash
cat > /workspace/custom_dataset.yaml << 'EOF'
# Configuración del conjunto de datos
path: /workspace/dataset
train: images/train
val: images/val
test: images/test

# Número de clases
nc: 3

# Nombres de clases
names:
  0: person
  1: car
  2: bicycle
EOF
```

### Importar desde Roboflow (Recomendado)

```python
# Instalar 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")

# El conjunto de datos ahora está en ./your-project-1/
```

### Entrenar YOLOv10

```python
from ultralytics import YOLO

# Cargar modelo YOLOv10 preentrenado (aprendizaje por transferencia)
model = YOLO("yolov10m.pt")  # Variante mediana — buen equilibrio

results = model.train(
    data="/workspace/custom_dataset.yaml",
    epochs=100,
    imgsz=640,
    batch=16,               # Ajusta según la VRAM de tu GPU
    device="cuda",
    workers=8,
    project="/workspace/runs",
    name="yolov10_custom",
    patience=50,            # Parada temprana
    save=True,
    save_period=10,         # Guardar checkpoint cada 10 épocas
    plots=True,
    val=True,
    augment=True,           # Aumento de datos
    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                # Precisión mixta automática (FP16)
)

print(f"¡Entrenamiento completado! Mejor mAP: {results.results_dict['metrics/mAP50-95(B)']:.3f}")
```

### Entrenar 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 es más grande, necesita menos batch
    device="cuda",
    workers=8,
    project="/workspace/runs",
    name="yolov9_custom",
    amp=True,
    optimizer="SGD",
    momentum=0.937,
    weight_decay=0.0005
)
```

{% hint style="info" %}
**Consejos de entrenamiento:**

* **Tamaño de lote:** Comienza con `batch=16` para RTX 4090, `batch=32` para A100 40GB
* **Tamaño de imagen:** `imgsz=640` es estándar; usa 1280 para tareas de alta resolución
* **Épocas:** 100 épocas es típico para fine-tuning, 300+ para entrenar desde cero
* **AMP (Precisión Mixta):** Siempre habilita `amp=True` para 1.5–2x de aceleración
  {% endhint %}

***

## Paso 6 — Exportar a TensorRT para máxima velocidad

```python
from ultralytics import YOLO

# Cargar modelo entrenado
model = YOLO("/workspace/runs/yolov10_custom/weights/best.pt")

# Exportar a TensorRT (FP16 para mejor balance velocidad/precisión)
model.export(
    format="engine",        # Motor de TensorRT
    device="cuda",
    half=True,              # FP16
    dynamic=False,          # Formas estáticas para máxima optimización TRT
    batch=1,                # Optimizar para tamaño de lote 1 (tiempo real)
    imgsz=640,
    workspace=4             # Espacio de trabajo TRT en GB
)
# Guardado como: best.engine

# Cargar y ejecutar motor TRT
trt_model = YOLO("best.engine")
results = trt_model("image.jpg")
```

### Exportar a ONNX

```python
# Exportar a ONNX para flexibilidad de despliegue
model.export(
    format="onnx",
    opset=17,
    half=True,              # Pesos FP16
    dynamic=True,           # Tamaño de lote dinámico
    simplify=True
)
```

***

## Paso 7 — Servir como API REST

```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
):
    # Leer imagen subida
    image_data = await file.read()
    img = Image.open(io.BytesIO(image_data)).convert("RGB")
    
    # Ejecutar detección
    results = model(img, conf=conf, iou=iou, verbose=False)
    result = results[0]
    
    # Construir respuesta
    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 &

# Prueba la API
curl -X POST "http://localhost:8000/detect" \
    -F "file=@test_image.jpg" | python3 -m json.tool
```

***

## Paso 8 — Validar y medir el rendimiento de tu modelo

```python
from ultralytics import YOLO

model = YOLO("yolov10x.pt")

# Validar en el conjunto de datos 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"Precisión: {metrics.box.mp:.3f}")
print(f"Recall:    {metrics.box.mr:.3f}")

# Medir la velocidad
model.benchmark(
    format="engine",   # Comparar múltiples formatos de exportación
    imgsz=640,
    half=True,
    device="cuda"
)
```

***

## Descargar resultados

```bash
# Desde tu máquina local:
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 ./

# Descargar toda la ejecución de entrenamiento
rsync -avz -e "ssh -p <ssh-port>" \
    root@<server-ip>:/workspace/runs/ \
    ./yolo_training_runs/
```

***

## Solución de problemas

### CUDA fuera de memoria durante el entrenamiento

```python
# Reduce el tamaño del batch
model.train(data="data.yaml", batch=4, imgsz=640)

# O habilitar checkpointing de gradientes
model.train(data="data.yaml", batch=8, imgsz=640, cache=False)
```

### Velocidad de entrenamiento lenta

```python
# Habilitar caché (carga el conjunto de datos en RAM/GPU)
model.train(data="data.yaml", cache=True)  # Caché en RAM
model.train(data="data.yaml", cache="disk")  # Caché en disco

# Aumentar workers (cuidado: demasiados pueden ralentizar)
model.train(data="data.yaml", workers=8)
```

### Bajo mAP / Detección deficiente

```bash
# Verificar que las etiquetas sean correctas (normalizadas, dentro de 0-1)
python3 -c "
from ultralytics.data.utils import check_det_dataset
check_det_dataset('custom_dataset.yaml')
"

# Visualizar muestras de entrenamiento
python3 -c "
from ultralytics import YOLO
model = YOLO('yolov10m.pt')
model.train(data='data.yaml', epochs=1, batch=4, plots=True)
# Revisar /workspace/runs/train/exp/train_batch*.jpg
"
```

***

## Referencia de rendimiento (GPUs de Clore.ai)

| Modelo       | GPU      | Lote | FPS (inferencia) | 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     |

***

## Recursos adicionales

* [Documentación de Ultralytics](https://docs.ultralytics.com/)
* [Artículo YOLOv9](https://arxiv.org/abs/2402.13616)
* [Artículo YOLOv10](https://arxiv.org/abs/2405.14458)
* [Roboflow Universe](https://universe.roboflow.com/) — 100K+ conjuntos de datos públicos
* [Ultralytics HUB](https://hub.ultralytics.com/) — Plataforma de entrenamiento en la nube
* [Conjunto de datos COCO](https://cocodataset.org/) — Conjunto de datos de referencia estándar

***

*YOLOv9 y YOLOv10 en los alquileres de GPU de Clore.ai ofrecen una vía asequible para entrenar modelos personalizados de detección de objetos y desplegar canalizaciones de inferencia en tiempo real — sin la sobrecarga de AWS SageMaker o Google Vertex AI.*

***

## Recomendaciones de GPU en Clore.ai

| Caso de uso                     | GPU recomendada | Coste estimado en Clore.ai |
| ------------------------------- | --------------- | -------------------------- |
| Desarrollo/Pruebas              | RTX 3090 (24GB) | \~$0.12/gpu/hr             |
| Inferencia en Producción        | RTX 4090 (24GB) | \~$0.70/gpu/hr             |
| Entrenamiento con lotes grandes | A100 80GB       | \~$1.20/gpu/hr             |

> 💡 Todos los ejemplos en esta guía pueden desplegarse en [Clore.ai](https://clore.ai/marketplace) servidores GPU. Navega las GPUs disponibles y alquila por hora — sin compromisos, acceso root completo.


---

# 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-es/vision-por-computadora/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.
