Un sistema de tracking visual que detecta tu mano con la webcam, reconoce hasta 12 gestos distintos, y controla un servo motor conectado a un Arduino UNO en tiempo real. Incluye un dashboard web para visualizar el video en vivo, las métricas del sistema y el estado del servo. Construido con MediaPipe, OpenCV, Flask y Arduino.
- Tracking de mano en tiempo real con 21 landmarks usando MediaPipe Hand Landmarker
- Reconocimiento de 12 gestos:
✋
open_hand· ✊fist· 👆pointing· ✌️peace· 👍thumbs_up· 👎thumbs_down· 🤘rock· 🖖alien· 🤙call_me· 👌ok· 3️⃣three· ❓unknown - Control del servo según el gesto: pointing=seguir, fist=pausar, open_hand=centrar, thumbs_up=derecha, thumbs_down=izquierda, peace=modo lento
- Dashboard web con video en vivo (MJPEG), métricas (FPS, latencia), indicador de gesto y visualización del ángulo del servo
- Arquitectura modular: fácil de extender con nuevos detectores o backends
- Funciona sin Arduino: modo solo-visión con advertencia en consola
- Arduino UNO R3 (con chip CH340)
- Servo motor SG90
- 3 LEDs (verde, amarillo, rojo)
- 3 resistencias de 220 Ω
- Protoboard y jumpers
- Cable USB para Arduino
- Webcam USB
- Python 3.10+ (probado con 3.14)
- Arduino IDE
- pip (administrador de paquetes de Python)
| Componente | Pin Arduino | Notas |
|---|---|---|
| Servo SG90 (señal) | Pin 9 (PWM) | Cable naranja/amarillo |
| Servo SG90 (VCC) | 5V | Cable rojo |
| Servo SG90 (GND) | GND | Cable marrón |
| LED Verde | Pin 3 | Con resistencia 220 Ω — indica: objeto detectado |
| LED Amarillo | Pin 4 | Con resistencia 220 Ω — indica: buscando |
| LED Rojo | Pin 5 | Con resistencia 220 Ω — indica: error |
ARDUINO UNO R3
┌─────────────────────────┐
│ Pin 9 (PWM) ──────────┼────► Servo Signal (naranja)
│ 5V ──────────┼────► Servo VCC (rojo)
│ GND ──────────┼────► Servo GND (marrón)
│ │
│ Pin 3 ───[220Ω]─┼────► LED Verde (+) ── GND
│ Pin 4 ───[220Ω]─┼────► LED Amarillo(+) ── GND
│ Pin 5 ───[220Ω]─┼────► LED Rojo (+) ── GND
│ │
│ USB ──────────┼────► PC (Serial 9600 baud)
└─────────────────────────┘
vision-tracker/
├── arduino/
│ └── tracker/
│ └── tracker.ino # Firmware Arduino (servo + LEDs + Serial)
├── python/
│ ├── main.py # Loop principal del tracker
│ ├── camera.py # Captura de video (OpenCV)
│ ├── detector.py # Detección de manos + gestos (MediaPipe)
│ ├── controller.py # Controlador PID
│ ├── serial_comm.py # Comunicación Serial con Arduino
│ └── config.py # Configuración centralizada
├── web/
│ ├── app.py # Servidor Flask + streaming MJPEG
│ └── templates/
│ └── index.html # Dashboard web
├── docs/ # Capturas de pantalla y recursos
├── requirements.txt
├── .gitignore
└── README.md
La webcam captura frames con OpenCV, que se pasan al modelo Hand Landmarker de MediaPipe para detectar los 21 landmarks de la mano. Las posiciones relativas de los landmarks (comparando puntas de dedos con articulaciones PIP) se analizan para reconocer el gesto activo. Un controlador PID calcula el ángulo necesario para mantener la mano centrada en el frame, y ese ángulo se transmite por Serial al Arduino, que mueve el servo con interpolación suave de 2° por ciclo. El servidor Flask transmite el video procesado por MJPEG y expone las métricas en tiempo real vía /api/metrics.
| Dirección | Comando | Ejemplo | Descripción |
|---|---|---|---|
| PC → Arduino | A<ángulo> |
A120 |
Mover servo a 120° |
| PC → Arduino | C |
C |
Centrar servo (90°) |
| Arduino → PC | P<ángulo> |
P120 |
Posición actual del servo |
| Arduino → PC | READY |
READY |
Inicialización completada |
El PID controla qué tan rápido y suave el servo sigue la mano. El error se calcula como la distancia horizontal normalizada entre el centro del frame y el centro de la palma detectada. Los parámetros se ajustan en python/config.py:
| Parámetro | Valor por defecto | Efecto |
|---|---|---|
PID_KP |
0.3 | Respuesta inmediata al error |
PID_KI |
0.01 | Elimina errores en estado estacionario |
PID_KD |
0.1 | Amortigua oscilaciones |
git clone https://github.com/AngeloVPerrotta/vision-tracker.git
cd vision-tracker- Abrir
arduino/tracker/tracker.inoen Arduino IDE - Seleccionar placa "Arduino UNO" y el puerto COM correcto
- Subir el sketch
- Verificar en Serial Monitor (9600 baud) que aparece
READY
pip install -r requirements.txtLos modelos de MediaPipe (.task) se descargan automáticamente la primera vez que ejecutás el programa.
Editar python/config.py y cambiar SERIAL_PORT según tu sistema:
SERIAL_PORT = "COM3" # Windows
# SERIAL_PORT = "/dev/ttyUSB0" # Linux
# SERIAL_PORT = "/dev/tty.usbmodem14101" # macOSpython web/app.pyAbrir http://localhost:5000 en el navegador.
Sin Arduino: si no tenés el Arduino conectado, el sistema arranca igual en modo solo-visión. Los gestos se reconocen normalmente pero no se mueve ningún servo.
| Gesto | Emoji | Acción del servo |
|---|---|---|
pointing |
👆 | Sigue la mano con PID |
fist |
✊ | Pausa (mantiene posición) |
open_hand |
✋ | Vuelve al centro (90°) |
thumbs_up |
👍 | Gira a la derecha (+3° por frame) |
thumbs_down |
👎 | Gira a la izquierda (−3° por frame) |
peace |
✌️ | Sigue en modo lento (50% del PID) |
| Otros gestos | — | Sigue la mano con PID normal |
Todo se configura en python/config.py:
SERIAL_PORT = "COM3" # Puerto del Arduino
CAMERA_INDEX = 0 # Índice de la webcam
FRAME_WIDTH = 640 # Resolución
FRAME_HEIGHT = 480
SERVO_MIN_ANGLE = 10 # Límites del servo
SERVO_MAX_ANGLE = 170
SERVO_CENTER = 90
PID_KP = 0.3 # Ganancias del PID
PID_KI = 0.01
PID_KD = 0.1
DETECTION_MODEL = "hand_gestures" # "hand_gestures" | "mediapipe_face" | "color_tracking"
FLASK_PORT = 5000| Capa | Tecnología |
|---|---|
| Visión | OpenCV + MediaPipe Hand Landmarker |
| Control | Controlador PID (Python) |
| Comunicación | PySerial (UART 9600 baud) |
| Firmware | Arduino C++ (Servo.h) |
| Backend web | Flask (Python) |
| Frontend | HTML + CSS + JavaScript (vanilla) |
| Streaming | MJPEG sobre HTTP |
MIT
Angelo Perrotta — GitHub