Resumen
Un backend en Python que convierte un flujo de webcam en una predicción numérica estable. El Hand Landmarker de MediaPipe localiza 21 landmarks en una sola mano, esas coordenadas se convierten en un vector de 63 valores, un modelo de scikit-learn clasifica la seña, y una ventana de suavizado por moda convierte la salida ruidosa por cuadro en una predicción suficientemente estable para actuar sobre ella. Se exponen tanto la predicción cruda como la estabilizada, para que el consumidor elija entre capacidad de respuesta y confiabilidad.
- Landmarks por mano
- 21
- Longitud del vector
- 6321 landmarks × 3 coordenadas
- Ventana de suavizado
- 10cuadros, por moda
Problema
La clasificación por cuadro de un video en vivo es inusable tal cual sale del modelo. Una mano en movimiento, un momento de oclusión parcial o un solo cuadro borroso producen una predicción que parpadea entre clases vecinas varias veces por segundo.
El problema de reconocimiento lo resolvió en buena medida el modelo de landmarks. El problema de ingeniería fue convertir una secuencia de suposiciones individualmente plausibles en una sola respuesta sobre la que un consumidor pueda actuar.
Restricciones
- Debe correr a tasas de cuadro interactivas en hardware de consumo común, sin suponer GPU
- Solo una mano, lo que acota el vector de características y mantiene el modelo pequeño
- Diez clases, señas del 1 al 10
- Presupuesto de latencia lo bastante ajustado para que la salida siga sintiéndose como respuesta al gesto del usuario
Rol y contribución
Ingeniero de Software — visión por computadora y backend
- Construí el pipeline de captura y detección sobre OpenCV y MediaPipe
- Diseñé la transformación de landmarks a vector de características
- Entrené y persistí el clasificador de señas
- Implementé la ventana de suavizado por moda y la separación de salida cruda/estable
- Estructuré el backend en módulos reemplazables por etapa del pipeline
Diseño del sistema
Arquitectura
Pipeline de inferencia
Un cuadro de webcam se captura con OpenCV y se pasa al Hand Landmarker de MediaPipe, que devuelve 21 landmarks de una sola mano detectada. Esos landmarks se aplanan en un vector de 63 valores y los clasifica un modelo de scikit-learn cargado desde disco con joblib, produciendo una predicción cruda por cuadro. La predicción cruda entra a una ventana de 10 cuadros cuya moda se convierte en la predicción estable. La API Flask expone tanto el valor crudo como el estable.
- Visión
- OpenCV
- MediaPipe Tasks Hand Landmarker
- Modelo
- scikit-learn
- joblib
- Servicio
- Python 3.11
- Flask
De landmarks a características
El Hand Landmarker devuelve 21 puntos de una mano detectada, cada uno con tres coordenadas. Aplanados, eso es un vector fijo de 63 valores por cuadro — lo bastante pequeño para que un modelo clásico lo clasifique muy por debajo del presupuesto de cuadro, y lo bastante estable en estructura para no requerir reajustes por cuadro.
Usar landmarks en vez de píxeles crudos es lo que vuelve tan barato al modelo. El trabajo caro de percepción lo hace el landmarker; el clasificador solo tiene que separar diez formas en un espacio de baja dimensión.
Predicción cruda contra estabilizada
La predicción cruda es la opinión del clasificador sobre el cuadro actual. Es inmediata y parpadea. La predicción estable es la moda de las últimas diez predicciones crudas: un solo cuadro de ruido no la mueve, pero un cambio genuino de seña sí la mueve una vez que la mayoría de la ventana coincide.
Se devuelven ambos valores. Un consumidor que quiere capacidad de respuesta — una superposición de depuración en vivo, por ejemplo — puede leer el valor crudo; uno que va a ejecutar una acción lee el estable. Elegir por el consumidor habría sido la decisión equivocada, porque el trade-off correcto depende de para qué se usa la predicción.
Estructura modular
Cada etapa — captura, detección, extracción de características, clasificación, suavizado, API — es un módulo separado con una interfaz estrecha. El beneficio práctico apareció durante el ajuste: la ventana de suavizado se pudo cambiar, y el clasificador intercambiar, sin tocar captura ni detección.
Limitación conocida: sin normalización relativa a la muñeca
La versión actual alimenta al clasificador con coordenadas de landmarks sin trasladarlas primero respecto a la muñeca. El modelo por lo tanto ve una seña hecha a la izquierda del cuadro como distinta de la misma seña hecha a la derecha, y tiene que gastar capacidad aprendiendo que son equivalentes.
Es una debilidad real, no estilística: hace que la precisión dependa de dónde queda la mano en el cuadro y de la distancia a la cámara. El arreglo es trasladar todos los landmarks a un marco de referencia anclado en la muñeca y escalar por el tamaño de la mano antes de clasificar, lo que debería mejorar la generalización sin cambiar la forma del pipeline.
Decisiones clave y trade-offs
Decisión
Estabilizar la salida con una ventana de suavizado por moda
- Contexto
- Las clasificaciones cuadro a cuadro fluctúan, incluso cuando la mano sostiene una seña.
- Alternativas consideradas
- Devolver cada predicción cruda directamente
- Exigir N cuadros consecutivos idénticos antes de emitir un cambio
- Promediar probabilidades de clase a lo largo de los cuadros
- Enfoque elegido
- La moda de una ventana deslizante de 10 cuadros, expuesta junto a la predicción cruda.
- Razón
- La moda es robusta a valores atípicos aislados sin exigir una racha de cuadros perfectos, y no necesita calibración de probabilidades del clasificador.
- Trade-off
- La salida se retrasa respecto a un cambio genuino de seña aproximadamente media ventana. Exponer también el valor crudo significa que un consumidor que no puede pagar ese retraso no se ve obligado a aceptarlo.
- Resultado
- Los cuadros mal clasificados aislados ya no llegan a los consumidores de la predicción estable.
Decisión
Clasificar landmarks en vez de píxeles crudos
- Contexto
- La alternativa es un modelo convolucional entrenado sobre imágenes de manos.
- Alternativa considerada
- Una CNN sobre regiones recortadas de mano
- Enfoque elegido
- Landmarks de MediaPipe aplanados en un vector de 63 valores, clasificados por un modelo de scikit-learn.
- Razón
- Los landmarks cargan la geometría de la que realmente depende la tarea y descartan iluminación, fondo y tono de piel. El resultado corre a tasas interactivas en CPU y entrena con un dataset pequeño.
- Trade-off
- Dependencia total del landmarker: si no detecta una mano, no hay ruta alterna hacia una predicción.
Resultado
- Un pipeline funcional en tiempo real, de webcam a predicción estabilizada, sobre hardware CPU común
- Parpadeo por cuadro eliminado de la salida estable sin pérdida perceptible de capacidad de respuesta
- Un backend modular donde el modelo y la estrategia de suavizado se pueden reemplazar de forma independiente
Aprendizajes
- El modelo fue la parte fácil. Volver usable su salida a lo largo del tiempo fue la ingeniería de verdad.
- Exponer tanto el valor crudo como el suavizado evitó adivinar qué trade-off necesita el consumidor.
- Elegir una buena representación intermedia — landmarks sobre píxeles — rindió más que cualquier cantidad de ajuste del modelo.
- Saltarse la normalización relativa a la muñeca fue un atajo que cuesta precisión en silencio; el arreglo pertenece a la etapa de características, no al modelo.
Próximas mejoras
- Trasladar los landmarks respecto a la muñeca y escalar por tamaño de mano antes de clasificar
- Evaluar la precisión en distintas posiciones y distancias para cuantificar la brecha actual de normalización
- Manejar el caso de mano no detectada como una clase explícita en vez de una ausencia de predicción
- Extender más allá de una sola mano y más allá de diez señas estáticas