Detección
Detección de objetos con modelos YOLO (Ultralytics), detección de landmarks con MediaPipe, y otros paradigmas de detección: R-CNN, CenterNet, FCOS, DETR. Incluye ejemplos prácticos de código en PyTorch y TensorFlow.
🎯 ¿Qué es la detección de objetos?
La detección de objetos va un paso más allá de la clasificación. Mientras que un clasificador responde «¿qué hay en la imagen?», un detector responde «¿qué hay y dónde está?». Para cada objeto relevante en la imagen, el modelo produce:
- Una clase (persona, coche, perro…).
- Un bounding box — un rectángulo que enmarca al objeto.
- Una confianza (confidence score) de la predicción.
Detección ≠ Clasificación + localización: un clasificador con localización predice un único objeto por imagen. Un detector maneja un número variable de objetos — pueden ser 0, 1, 5 o 50 en la misma imagen. Este es el reto fundamental.
📦 Bounding boxes y representaciones
Un bounding box (bbox) se puede representar de varias formas. Las dos más comunes son:
| Formato | Valores | Uso típico |
|---|---|---|
| (x₁, y₁, x₂, y₂) | Esquina superior-izquierda + esquina inferior-derecha | Pascal VOC, Faster R-CNN |
| (x_c, y_c, w, h) | Centro + ancho + alto | YOLO, COCO |
Todos los valores suelen estar normalizados entre 0 y 1 respecto al tamaño de la imagen, facilitando el aprendizaje y la generalización a distintas resoluciones.
Anchor boxes
Muchos detectores (YOLO, SSD, Faster R-CNN) no predicen bounding boxes «desde cero». En su lugar, parten de anchor boxes: un conjunto de recuadros predefinidos con distintas proporciones (aspect ratios) distribuidos en una grid sobre la imagen. El modelo aprende a ajustar estos anchors — predice offsets (Δx, Δy, Δw, Δh) respecto al anchor más cercano.
Donde (c_x, c_y) es la posición de la celda de la grid, (p_w, p_h) son las dimensiones del anchor, y (t_x, t_y, t_w, t_h) son las predicciones del modelo.
📐 IoU y métricas de detección
Intersection over Union (IoU)
La métrica fundamental para evaluar la calidad de un bounding box es el IoU (también llamado Jaccard index): la razón entre el área de intersección y el área de unión de la predicción y el ground truth.
Non-Maximum Suppression (NMS)
Un detector suele generar múltiples bounding boxes solapados para el mismo objeto. NMS filtra los duplicados manteniendo solo la predicción con mayor confianza:
Ordenar todos los bboxes por su confidence score de mayor a menor.
Seleccionar el bbox con mayor confianza y añadirlo al resultado final.
Eliminar todos los bboxes restantes cuyo IoU con el seleccionado supere un umbral (típicamente 0.5).
Repetir los pasos 2-3 hasta procesar todos los bboxes.
Métricas: Precision, Recall y mAP
Para evaluar un detector se usa la curva Precision-Recall y su área bajo la curva:
| Métrica | Definición | Uso |
|---|---|---|
| AP | Área bajo la curva Precision-Recall para una clase | Rendimiento por clase |
| mAP@0.5 | Media del AP sobre todas las clases con IoU ≥ 0.5 | Métrica principal Pascal VOC |
| mAP@[.5:.95] | Media del AP promediada en IoU de 0.5 a 0.95 (paso 0.05) | Métrica principal COCO (más estricta) |
mAP@[.5:.95] es más exigente porque penaliza los bboxes imprecisos. Un modelo puede tener mAP@0.5 del 70% pero mAP@[.5:.95] del 45% — los bboxes aciertan en ubicación general pero no son lo suficientemente ajustados.
⚙️ Pipeline general de detección
Independientemente del modelo concreto, todo detector sigue un pipeline con tres etapas principales:
Componentes del pipeline
| Componente | Función | Ejemplos |
|---|---|---|
| Backbone | Extrae features jerárquicas de la imagen | ResNet, CSPDarknet, EfficientNet |
| Neck | Fusiona features de distintas escalas (multi-scale) | FPN, PANet, BiFPN |
| Head | Predice clases + bounding boxes | Anchor-based, anchor-free, transformer |
Two-stage vs. One-stage
Históricamente, los detectores se dividen en dos grandes familias según cómo generan las predicciones:
🐢 Two-stage (R-CNN family)
- Paso 1: proponer regiones candidatas (RPN)
- Paso 2: clasificar y refinar cada propuesta
- Mayor precisión (especialmente para objetos pequeños)
- Más lento (10-20 FPS típico)
- Ejemplos: Faster R-CNN, Cascade R-CNN
🚀 One-stage (YOLO, SSD)
- Un solo paso: predicción directa sobre la grid
- Mucho más rápido (30-300+ FPS)
- Ideal para tiempo real
- Históricamente menos preciso, pero YOLO moderno cierra la brecha
- Ejemplos: YOLO, SSD, RetinaNet
Estado actual (2024-2025): los detectores one-stage modernos (especialmente YOLO) han alcanzado y en muchos casos superado a los two-stage en precisión, manteniendo velocidades de inferencia muy superiores. Por eso YOLO domina las aplicaciones de producción.
⚡ YOLO: You Only Look Once
YOLO (Redmon et al., 2016) revolucionó la detección de objetos con una idea radical: en lugar de recorrer la imagen múltiples veces buscando objetos, mirar la imagen completa una sola vez y predecir simultáneamente todas las bounding boxes y clases. Esto convirtió la detección en un problema de regresión directa, logrando velocidades de tiempo real por primera vez.
La idea fundamental
YOLO divide la imagen en una grid de S×S celdas. Cada celda es responsable de detectar los objetos cuyo centro cae dentro de ella. Para cada celda, el modelo predice:
- B bounding boxes, cada una con 5 valores: (x, y, w, h, \text{confidence})
- C probabilidades de clase condicionales
📈 Evolución de YOLO
Desde el YOLO original (v1, 2016) hasta las versiones actuales de Ultralytics, la familia YOLO ha atravesado una evolución extraordinaria, incorporando innovaciones de toda la comunidad:
🏗️ Arquitectura de YOLO moderno
Las versiones modernas de YOLO (v8, v11) comparten una arquitectura de tres componentes que ha convergido como el estándar de los detectores one-stage:
Innovaciones clave de YOLO moderno
📦 Anchor-free detection (YOLOv8+)
Las versiones clásicas de YOLO usaban anchor boxes predefinidas. YOLOv8+ elimina los anchors y predice directamente las distancias desde el centro del objeto a los cuatro bordes del bounding box:
(l, t, r, b) = distancias left, top, right, bottom desde el centro del objeto. Esto simplifica el diseño, elimina hiperparámetros de anchors, y mejora la generalización.
📦 Head desacoplado (Decoupled Head)
En lugar de usar un único head para clasificación y regresión, YOLOv8+ usa ramas separadas. La clasificación y la localización son tareas con objetivos diferentes — desacoplar los heads permite que cada rama se especialice, mejorando la precisión.
📦 Loss functions: CIoU + DFL
YOLO moderno usa CIoU loss (Complete IoU) para regresión de bboxes, que considera overlap, distancia de centros y proporción de aspecto. Para la distribución de offsets usa DFL (Distribution Focal Loss), que modela la localización como una distribución de probabilidad discreta en lugar de un valor puntual.
Familia de modelos Ultralytics
| Modelo | Params | mAP@[.5:.95] | Velocidad (ms) | Caso de uso |
|---|---|---|---|---|
| YOLO11n | 2.6M | 39.5 | 1.5 | Edge devices, IoT, móviles |
| YOLO11s | 9.4M | 47.0 | 2.5 | Balance velocidad/precisión |
| YOLO11m | 20.1M | 51.5 | 4.7 | Uso general de producción |
| YOLO11l | 25.3M | 53.4 | 6.2 | Alta precisión |
| YOLO11x | 56.9M | 54.7 | 11.3 | Máxima precisión (servidor) |
Ecosistema Ultralytics: más allá de detección, los modelos YOLO de Ultralytics soportan 5 tareas con la misma API: detección, segmentación de instancias, clasificación, estimación de pose (keypoints) y detección orientada (OBB). Un solo framework para todo.
🔄 Otras arquitecturas one-stage
Aunque YOLO domina el ecosistema, existen otros detectores one-stage relevantes con ideas complementarias:
SSD (Single Shot MultiBox Detector)
SSD (Liu et al., 2016) fue contemporáneo de YOLO y pionero en la detección multi-escala: aplica heads de detección en múltiples capas de features del backbone, cada una con resolución diferente. Los objetos grandes se detectan en capas profundas (baja resolución) y los pequeños en capas tempranas (alta resolución).
RetinaNet y Focal Loss
RetinaNet (Lin et al., 2017) identificó que el principal problema de los detectores one-stage no era la arquitectura sino el desbalance de clases: en una grid de detección, la inmensa mayoría de celdas son background (negativos fáciles) que dominan la loss. Su solución fue la Focal Loss:
El factor (1 - p_t)^\gamma reduce el peso de los ejemplos fáciles (alta p_t), concentrando el aprendizaje en los casos difíciles. Con \gamma = 2, RetinaNet superó a Faster R-CNN por primera vez desde un detector one-stage.
Focal Loss en YOLO: las versiones modernas de YOLO incorporaron variantes de focal loss. YOLOv8 usa BCE con logits para clasificación y DFL + CIoU para regresión — ideas que evolucionaron a partir del principio de la focal loss.
📍 Detección de landmarks y keypoints
Mientras que la detección de objetos localiza qué hay y dónde (bounding box), la detección de landmarks (o keypoints) va un paso más allá: identifica puntos anatómicos o estructurales precisos dentro del objeto — articulaciones del cuerpo, rasgos faciales, puntos de la mano, etc.
Dos enfoques principales
🔥 Heatmap-based
Se genera un mapa de calor para cada keypoint. El modelo predice una imagen del mismo tamaño (o downscaled) donde la intensidad indica la probabilidad de cada punto:
- ✅ Alta precisión espacial (resolución pixel)
- ✅ Robusto ante oclusiones parciales
- ❌ Costoso en memoria (un mapa por keypoint)
- ❌ Resolución limitada por el stride de la red
📐 Regression-based
El modelo predice directamente las coordenadas (x, y) de cada keypoint como salida de regresión. Es más eficiente pero históricamente menos preciso.
- ✅ Ligero, rápido, bajo consumo de memoria
- ✅ End-to-end sin post-procesado
- ❌ Menor precisión sub-pixel
- ❌ Más difícil de entrenar (señal supervisora débil)
Tendencia actual: los modelos modernos combinan ambos enfoques. Por ejemplo, YOLO-Pose usa regresión directa de coordenadas, mientras que HRNet usa heatmaps de alta resolución. MediaPipe usa un enfoque híbrido con regresión para velocidad en dispositivos móviles.
🤖 MediaPipe: detección en tiempo real
MediaPipe (Google) es un framework de ML para procesamiento de medios en tiempo real, diseñado para ejecutarse de forma eficiente en dispositivos móviles, navegadores y edge devices. Su suite de solutions incluye modelos de landmarks preentrenados de alto rendimiento.
Soluciones de landmarks de MediaPipe
| Solución | Landmarks | Descripción | Uso típico |
|---|---|---|---|
| Face Mesh | 478 puntos 3D | Malla facial completa con iris tracking | Filtros AR, análisis de expresiones |
| Hand Landmarks | 21 puntos 3D | Articulaciones de cada mano | Gestos, lengua de señas, XR |
| Pose Landmarks | 33 puntos 3D | Esqueleto corporal completo | Fitness, deporte, motion capture |
| Holistic | 543 puntos | Face + hands + pose combinados | Interacción multimodal, XR |
Arquitectura de MediaPipe Pose
MediaPipe sigue un pipeline de dos etapas para lograr velocidad en tiempo real:
Localiza la persona en la imagen (solo en el primer frame o cuando se pierde el tracking)
Recibe el ROI (region of interest) y predice las coordenadas de los N landmarks
Usa los landmarks predichos para actualizar el ROI del siguiente frame
📦 ¿Por qué dos etapas?
El detector (ligero, ~4M params) es más costoso que el tracker, pero solo se ejecuta esporádicamente (primer frame o cuando se pierde el tracking). El tracker recibe un crop estrecho alrededor de la persona, lo que reduce drásticamente el área de entrada y permite correr a 30+ FPS en móviles.
Esta estrategia de detect-then-track es clave para la eficiencia de MediaPipe en edge devices.
📦 Coordenadas 3D en MediaPipe
MediaPipe predice landmarks en 3D: (x, y, z, \text{visibility}). Las coordenadas (x, y) están normalizadas al tamaño de imagen [0, 1]. La coordenada z representa la profundidad relativa al centro de la cadera (en Pose) o la muñeca (en Hand), con la misma escala que x. Visibility indica la confianza de que el punto sea visible (no ocluido).
Otros frameworks de landmarks
📦 YOLO-Pose (Ultralytics)
Ultralytics integra la estimación de pose directamente en el framework YOLO. El modelo predice simultáneamente bounding boxes + keypoints en una sola inferencia. Ventajas:
- Multi-persona nativo: detecta y estima pose de varias personas a la vez
- Misma API de Ultralytics:
model.predict(source) - Alto rendimiento: hereda la velocidad de YOLO
📦 HRNet (High-Resolution Network)
HRNet mantiene representaciones de alta resolución a lo largo de toda la red, en lugar de reducir la resolución y luego recuperarla (como en los encoders-decoders tradicionales). Esto lo hace especialmente preciso para tareas que requieren localización fina como keypoints.
Es el backbone de referencia para benchmarks de pose estimation como COCO Keypoints y MPII.
¿Cuándo usar cada framework?
- MediaPipe: cuando necesitas velocidad en dispositivos con recursos limitados (móviles, navegadores).
- YOLO-Pose: cuando quieres detección + pose multi-persona en un pipeline unificado.
- HRNet: cuando la máxima precisión de landmarks es más importante que la velocidad.
🔬 Detectores two-stage (R-CNN family)
Antes de YOLO, la detección de objetos estaba dominada por los detectores two-stage: primero generan propuestas de regiones candidatas, y después clasifican y refinan cada propuesta individualmente. Aunque más lentos, durante años lograron la mayor precisión.
Evolución de la familia R-CNN
Two-stage vs one-stage: los detectores two-stage examinan cada propuesta individualmente con más detalle, lo que les da ventaja en objetos pequeños y escenas complejas. Sin embargo, los detectores one-stage modernos (YOLO, FCOS) han cerrado la brecha de precisión manteniendo su ventaja de velocidad.
🎯 Detectores anchor-free
Los anchor boxes (cajas predefinidas de referencia) fueron centrales en los primeros detectores modernos, pero introducen hiperparámetros difíciles de ajustar. Los detectores anchor-free eliminan esta dependencia, prediciendo las bounding boxes de formas más directas.
CenterNet: detección como detección de puntos
CenterNet (Zhou et al., 2019) reformula la detección como un problema de detección del punto central del objeto. El modelo predice un heatmap de centros (como en landmark detection) y luego regresa el tamaño del bbox desde cada centro detectado:
- Sin anchors, sin NMS (el heatmap produce centros directamente)
- Simple y elegante — un solo backbone + 3 heads (heatmap, size, offset)
- Extensible a 3D detection, pose, tracking
FCOS: Fully Convolutional One-Stage detector
FCOS (Tian et al., 2019) predice, para cada posición del feature map, las 4 distancias al borde del bbox (l, t, r, b) más un score de centerness que indica qué tan centrado está el punto respecto al objeto:
El centerness penaliza predicciones lejos del centro del objeto, reduciendo detecciones de baja calidad sin necesidad de heurísticas complejas.
YOLO heredó ideas anchor-free: la transición de YOLOv5 (anchor-based) a YOLOv8 (anchor-free) incorporó directamente la idea de FCOS de predecir distancias (l, t, r, b) desde cada punto, combinándola con Distribution Focal Loss para mayor precisión.
🔮 Detección con Transformers
Los transformers, originados en NLP, han revolucionado también la detección de objetos. El concepto clave es usar atención para modelar relaciones globales entre las features de la imagen y un conjunto de queries que aprenden a detectar objetos.
DETR: DEtection TRansformer
DETR (Carion et al., 2020, Meta AI) fue el primer detector basado en transformers. Su innovación radical: eliminar completamente anchors, NMS y todo el post-procesado heurístico, reemplazándolo con un enfoque puramente basado en conjuntos.
ResNet-50 → features
Self-attention sobre features + pos. encoding
N object queries atenúan a features
FFN: clase + bbox por query
📦 Object queries y matching bipartito
DETR usa N queries aprendibles (típicamente N=100) que funcionan como slots de detección. Cada query se especializa en detectar objetos en ciertas posiciones y escalas. El entrenamiento usa Hungarian matching (asignación bipartita) para emparejar predicciones con ground truth:
Esto elimina la necesidad de NMS: el propio mecanismo de atención aprende a no predecir el mismo objeto dos veces.
Evolución de DETR
| Modelo | Mejora principal | mAP (COCO) | Característica |
|---|---|---|---|
| DETR (2020) | Primer detector con transformer | 42.0 | Sin NMS, sin anchors |
| Deformable DETR | Atención deformable multi-escala | 46.2 | 10× más rápido en entrenamiento |
| DINO (2022) | Denoising anchor boxes + contrastive | 49.4 | SOTA en COCO |
| RT-DETR (2023) | Hybrid CNN-transformer, tiempo real | 53.1 | Integrado en Ultralytics |
RT-DETR en Ultralytics: desde YOLOv8, Ultralytics integra RT-DETR
como alternativa a YOLO. Usa un encoder híbrido CNN-transformer y un decoder
IoU-aware. Compite en velocidad con YOLO manteniendo las ventajas de
la arquitectura transformer (sin NMS, mejor en objetos parcialmente ocluidos).
from ultralytics import RTDETR
Comparativa de paradigmas
| Aspecto | Two-stage | One-stage (YOLO) | Transformer (DETR) |
|---|---|---|---|
| Velocidad | 🔴 Lenta (~5 FPS) | 🟢 Tiempo real (30+ FPS) | 🟡 Variable (5-30 FPS) |
| Precisión objetos grandes | 🟢 Alta | 🟢 Alta | 🟢 Alta |
| Precisión objetos pequeños | 🟡 Media-alta | 🟡 Media (mejorando) | 🟡 Media (mejorando) |
| Post-procesado | NMS necesario | NMS necesario | Sin NMS ✨ |
| Anchors | Sí (RPN) | No (v8+) | No (queries) |
| Deploy edge | 🔴 Difícil | 🟢 Fácil (ONNX, TRT) | 🟡 Posible (RT-DETR) |
Recuerda: en el submódulo anterior vimos clasificación de imágenes y transfer learning. En el siguiente submódulo exploraremos la segmentación (semántica e instancias), que extiende la detección prediciendo una máscara pixel a pixel en lugar de un rectángulo.
💻 Código: Detección con Ultralytics YOLO
El ecosistema Ultralytics ofrece la API más sencilla para detección de objetos con modelos YOLO. A continuación, los casos de uso más comunes.
Instalación
# Instalación
pip install ultralytics
# Verificar instalación
yolo checks
Inferencia básica (detección de objetos)
from ultralytics import YOLO
# Cargar modelo preentrenado (descarga automática)
model = YOLO("yolo11n.pt") # nano: rápido, ligero
# model = YOLO("yolo11s.pt") # small: balance
# model = YOLO("yolo11m.pt") # medium: producción
# Inferencia en una imagen
results = model("imagen.jpg")
# Procesar resultados
for result in results:
boxes = result.boxes # Bounding boxes
for box in boxes:
xyxy = box.xyxy[0] # Coordenadas [x1, y1, x2, y2]
conf = box.conf[0] # Confianza
cls = box.cls[0] # Índice de clase
name = model.names[int(cls)] # Nombre de clase
print(f"{name}: {conf:.2f} en ({xyxy[0]:.0f}, {xyxy[1]:.0f}) → "
f"({xyxy[2]:.0f}, {xyxy[3]:.0f})")
# Guardar imagen anotada
result.save("resultado.jpg")
Detección en vídeo y webcam
from ultralytics import YOLO
model = YOLO("yolo11n.pt")
# Detección en vídeo
results = model("video.mp4", stream=True) # stream=True para uso eficiente de memoria
for result in results:
annotated = result.plot() # Frame con anotaciones dibujadas
# cv2.imshow("YOLO", annotated)
# Detección en webcam (fuente 0)
results = model(source=0, show=True)
# Detección en stream RTSP
results = model("rtsp://192.168.1.100:554/stream")
Entrenamiento con dataset personalizado
from ultralytics import YOLO
# Cargar modelo preentrenado como base
model = YOLO("yolo11n.pt")
# Entrenar con dataset personalizado
# El archivo data.yaml define clases, paths de train/val
results = model.train(
data="mi_dataset/data.yaml",
epochs=100,
imgsz=640,
batch=16,
patience=20, # Early stopping
lr0=0.01, # Learning rate inicial
augment=True, # Augmentación automática
device="cuda", # GPU (o "cpu", "mps")
project="runs/detect",
name="mi_experimento"
)
# Evaluar en validation set
metrics = model.val()
print(f"mAP@50: {metrics.box.map50:.3f}")
print(f"mAP@50:95: {metrics.box.map:.3f}")
# mi_dataset/data.yaml
path: /ruta/a/mi_dataset
train: images/train
val: images/val
test: images/test
names:
0: gato
1: perro
2: pajaro
Exportación del modelo
from ultralytics import YOLO
model = YOLO("runs/detect/mi_experimento/weights/best.pt")
# Exportar a diferentes formatos
model.export(format="onnx") # ONNX (multiplataforma)
model.export(format="torchscript")# TorchScript (C++ deployment)
model.export(format="engine") # TensorRT (NVIDIA, máxima velocidad)
model.export(format="coreml") # CoreML (Apple)
model.export(format="tflite") # TFLite (Android, Edge TPU)
# Inferencia con modelo exportado
onnx_model = YOLO("best.onnx")
results = onnx_model("imagen.jpg")
Tareas adicionales con la misma API: Ultralytics soporta
model = YOLO("yolo11n-seg.pt") para segmentación,
"yolo11n-pose.pt" para estimación de pose, y
"yolo11n-obb.pt" para bounding boxes orientados.
🤖 Código: Landmarks con MediaPipe
MediaPipe ofrece detección de landmarks ligera y eficiente. A continuación se muestran ejemplos para las tres tareas principales.
Instalación
pip install mediapipe opencv-python
Detección de pose (33 landmarks)
import cv2
import mediapipe as mp
mp_pose = mp.solutions.pose
mp_draw = mp.solutions.drawing_utils
# Inicializar detector de pose
with mp_pose.Pose(
static_image_mode=False, # False para vídeo (tracking)
model_complexity=1, # 0=lite, 1=full, 2=heavy
min_detection_confidence=0.5,
min_tracking_confidence=0.5
) as pose:
cap = cv2.VideoCapture(0) # Webcam
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Convertir BGR → RGB (MediaPipe usa RGB)
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = pose.process(rgb)
if results.pose_landmarks:
# Dibujar landmarks y conexiones
mp_draw.draw_landmarks(
frame,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS
)
# Acceder a landmarks individuales
landmarks = results.pose_landmarks.landmark
nariz = landmarks[mp_pose.PoseLandmark.NOSE]
print(f"Nariz: x={nariz.x:.3f}, y={nariz.y:.3f}, "
f"z={nariz.z:.3f}, vis={nariz.visibility:.2f}")
cv2.imshow("Pose", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
Detección de manos (21 landmarks)
import cv2
import mediapipe as mp
mp_hands = mp.solutions.hands
mp_draw = mp.solutions.drawing_utils
with mp_hands.Hands(
static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.7,
min_tracking_confidence=0.5
) as hands:
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(rgb)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# Dibujar landmarks
mp_draw.draw_landmarks(
frame, hand_landmarks, mp_hands.HAND_CONNECTIONS
)
# Ejemplo: posición de la punta del índice
index_tip = hand_landmarks.landmark[
mp_hands.HandLandmark.INDEX_FINGER_TIP
]
h, w, _ = frame.shape
px = int(index_tip.x * w)
py = int(index_tip.y * h)
cv2.circle(frame, (px, py), 8, (0, 255, 0), -1)
cv2.imshow("Hands", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
Face Mesh (478 landmarks)
import cv2
import mediapipe as mp
mp_face = mp.solutions.face_mesh
mp_draw = mp.solutions.drawing_utils
mp_styles = mp.solutions.drawing_styles
with mp_face.FaceMesh(
static_image_mode=False,
max_num_faces=1,
refine_landmarks=True, # Incluye iris (478 en total)
min_detection_confidence=0.5,
min_tracking_confidence=0.5
) as face_mesh:
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = face_mesh.process(rgb)
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# Dibujar malla facial
mp_draw.draw_landmarks(
image=frame,
landmark_list=face_landmarks,
connections=mp_face.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=mp_styles
.get_default_face_mesh_tesselation_style()
)
cv2.imshow("Face Mesh", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
🔧 Detección con PyTorch y TensorFlow
Aunque Ultralytics y MediaPipe son las opciones más prácticas, entender cómo usar los frameworks base es valioso para proyectos personalizados.
PyTorch: detección con torchvision
import torch
import torchvision
from torchvision.models.detection import fasterrcnn_resnet50_fpn_v2
from torchvision.transforms import functional as F
from PIL import Image
# Cargar modelo preentrenado
model = fasterrcnn_resnet50_fpn_v2(
weights=torchvision.models.detection
.FasterRCNN_ResNet50_FPN_V2_Weights.DEFAULT
)
model.eval()
# Preprocesar imagen
image = Image.open("imagen.jpg")
tensor = F.to_tensor(image).unsqueeze(0)
# Inferencia
with torch.no_grad():
predictions = model(tensor)[0]
# Filtrar por confianza
threshold = 0.5
for i, score in enumerate(predictions["scores"]):
if score >= threshold:
box = predictions["boxes"][i].tolist()
label = predictions["labels"][i].item()
print(f"Clase {label}: {score:.2f} → {box}")
TensorFlow: TF Hub Object Detection
import tensorflow as tf
import tensorflow_hub as hub
import numpy as np
from PIL import Image
# Cargar modelo desde TF Hub
model = hub.load(
"https://tfhub.dev/tensorflow/efficientdet/d0/1"
)
# Cargar y preprocesar imagen
image = Image.open("imagen.jpg")
image_np = np.array(image)
input_tensor = tf.convert_to_tensor(image_np)[tf.newaxis, ...]
# Inferencia
results = model(input_tensor)
# Extraer resultados
boxes = results["detection_boxes"][0].numpy() # [y1,x1,y2,x2] normalizado
scores = results["detection_scores"][0].numpy()
classes = results["detection_classes"][0].numpy().astype(int)
# Filtrar por confianza
threshold = 0.5
for i, score in enumerate(scores):
if score >= threshold:
y1, x1, y2, x2 = boxes[i]
h, w = image_np.shape[:2]
print(f"Clase {classes[i]}: {score:.2f} → "
f"({int(x1*w)}, {int(y1*h)}) → ({int(x2*w)}, {int(y2*h)})")
Nota práctica: para la mayoría de proyectos de detección, Ultralytics YOLO es la opción recomendada por su simplicidad, rendimiento y comunidad. Usa los frameworks base (PyTorch/TF) cuando necesites control total sobre la arquitectura o estés investigando nuevos modelos.