Bienvenido

Machine Learning

GestureKey

PythonOpenCVMediaPipeScikit-learnPyQt6

Sistema de detección de gestos de la mano en tiempo real que convierte la imagen de la webcam en atajos de teclado del sistema operativo. Arquitectura limpia por capas con un pipeline de ML integrado: de los fotogramas de la cámara a las acciones del sistema, como app en la bandeja del sistema.

El problema

Quería controlar mi computadora durante presentaciones y grabaciones sin tocar el teclado: una capa de atajos por gestos funcionando en segundo plano. El reto principal era que la detección fuera lo bastante rápida y estable para usarse en condiciones reales: iluminación variable, ligeros movimientos de cámara y la imprecisión natural de la posición de la mano.

Decisiones clave

MediaPipe para detectar los puntos de referencia en lugar de un pipeline de visión propio

MediaPipe devuelve 21 puntos de referencia 3D normalizados por mano en menos de 10 ms en CPU. Construir algo equivalente desde cero con OpenCV habría llevado meses y dado un resultado peor. La decisión de ingeniería correcta fue tratar la detección de la mano como un problema resuelto y concentrar el trabajo original en el clasificador y el motor de gestos encima.

Random Forest en lugar de una red neuronal para clasificar gestos

Una CNN necesita miles de imágenes y una GPU para entrenarse en un tiempo razonable. Pero MediaPipe ya extrae puntos de referencia semánticos —las posiciones relativas de 21 articulaciones—, así que los píxeles en bruto son irrelevantes. Sobre esa entrada estructurada, un Random Forest entrenado con 200 muestras por gesto supera el 98 % de precisión e infiere en menos de 2 ms. Una red neuronal habría sumado complejidad, tiempo de entrenamiento y peso de despliegue sin ganar precisión.

Estabilizador temporal con una ventana de votación por mayoría

Las predicciones fotograma a fotograma son ruidosas: si un dedo se mueve un píxel, el clasificador puede devolver la clase equivocada por un instante. Disparar un atajo del sistema con cada predicción haría la app inutilizable. El estabilizador guarda un búfer de las últimas N predicciones y solo emite una acción cuando el mismo gesto gana la votación en toda la ventana. Así elimina el parpadeo sin añadir una latencia perceptible.

PyQt6 para la app de bandeja en lugar de Tkinter o Electron

La app tiene que correr en silencio en segundo plano, capturar atajos de teclado globales e inyectar eventos de teclado a nivel del sistema operativo, y todo eso requiere acceso nativo. PyQt6 se integra limpiamente con las APIs de la bandeja del sistema y ofrece hooks de atajos globales. Tkinter no tiene soporte de bandeja. Electron habría sido absurdo para una utilidad en segundo plano: una instancia de Chromium de 150 MB para reemplazar un binario nativo de 4 MB.

Resultado

GestureKey corre de forma estable como proceso en segundo plano sin un impacto notable en CPU ni memoria. El modelo generaliza bien con distintas condiciones de luz y con usuarios que no estaban en el conjunto de entrenamiento. El proyecto afinó mi idea de dónde aporta valor el ML: no reemplazando la visión clásica, sino en la capa de clasificación, donde ya existen características estructuradas.

Puntos destacados

  • —Pipeline modular: Cámara → Tracker → Clasificador → Motor de gestos
  • —Modelo Random Forest entrenado con 21 puntos anatómicos de la mano
  • —8 gestos distintos: scroll, volumen, zoom, captura de pantalla, vista de tareas y más
  • —Estabilizador temporal que elimina el ruido de las predicciones fotograma a fotograma
  • —App de bandeja con PyQt6: corre en silencio en segundo plano

Pipeline

CapturaOpenCV
→
Puntos de referenciaMediaPipe
→
ClasificaciónRandom Forest
→
AcciónMotor de gestos

Gestos

TWO_FINGERS → ScrollTHREE_FINGERS → VolumenPINCH → ZoomPALM→FIST → PausaPALM×2 → Vista de tareas

Demo

Scroll

Volumen

Vista de tareas

Pausa

App de bandeja

Trabajemos juntos