Visión artificial 3° A
- AGR
- Web , Programación
- 05 Jan, 2025
Link de la sesion de meet:
Link para la reunion de domingo 16 febrero 2025 actualizada https://meet.google.com/aox-anan-ttp
Índice
- Link de la sesion de meet:
- Explicación del Proyecto
- Desarrollo
- Tutorial: Detección de Dedos y Juego de Piedra, Papel o Tijera
- Electrónica
- Programación
- Desafíos
- Recursos
- Explicación detallada del código para detección de dedos con MediaPipe y OpenCV
Explicación del Proyecto
Materiales necesarios
- 1 Arduino
- 5 Servomotores
- 1 Protoboard
- 1 Fuente de alimentación
- 1 Cable USB
Herramientas
- 1 Destornillador
- 1 Pinza
- 1 Tijera
- 1 Cautín
- 1 Soldadura
- 1 Cableado
Desarrollo
Instalacion de pyton
-
Descarga la version recomendada para el proyecto python 3.12
-
Instala PowerShell aqui
-
Instala las dependencias necesaias
py -m pip install --upgrade pip
pip install mediapipe
pip install opencv-python
pip install pyserial
Tutorial: Detección de Dedos y Juego de Piedra, Papel o Tijera
Este tutorial se divide en 6 etapas, en las que se explica paso a paso cómo llegar al proyecto final. Aprenderás desde la introducción a las librerías necesarias, pasando por la detección de dedos con MediaPipe, hasta la implementación de un juego interactivo.
Etapa 1: Explicación de las Librerías
En esta etapa se presentan las librerías utilizadas:
- OpenCV (
cv2): Biblioteca para procesamiento de imágenes y video. - MediaPipe (
mediapipe): Framework para aplicaciones de visión por computadora en tiempo real (por ejemplo, detección de manos). - NumPy (
numpy): Biblioteca para manejo de arrays y operaciones matemáticas.
Ejemplo de importación:
import cv2 # Manejo de imágenes y video
import mediapipe as mp # Detección y seguimiento de manos
import numpy as np # Operaciones matemáticas y manejo de arrays
Etapa 2: Introducción a Python y Ejecución de Códigos Sencillos
Python es un lenguaje de programación sencillo y poderoso. Para comenzar:
- Instalación: Descarga e instala Python desde python.org.
- Editor/IDE: Puedes usar editores como VSCode, PyCharm o incluso Jupyter Notebook.
- Ejecución: Escribe un código sencillo, guarda el archivo (por ejemplo,
hola.py) y ejecútalo desde la terminal con:
python hola.py
Ejemplo de código simple:
# Imprime "Hola, mundo!" en la consola
print("Hola, mi nombre es:")
Etapa 3: Lectura de los Dedos de la Mano
Utilizando MediaPipe, podemos detectar la mano y sus puntos clave (landmarks). El proceso es el siguiente:
- Captura de video: Se obtiene el frame desde la cámara.
- Conversión de color: OpenCV captura en BGR; MediaPipe requiere RGB.
- Procesamiento: MediaPipe detecta la mano y devuelve los landmarks.
- Visualización: Se dibujan los puntos y conexiones en el frame.
Etapa 4: Modificaciones para Detectar tus Propias Posiciones
Puedes personalizar el sistema modificando:
- Índices de landmarks: Cada dedo tiene un conjunto de índices (por ejemplo, el pulgar usa los puntos 4 y 3).
- Condiciones de comparación: Cambia la comparación de coordenadas (
xoy) para ajustar la detección según la forma en que sostienes la mano.
Ejemplo:
# Compara la posición X para detectar si el pulgar está levantado
if hand_landmarks.landmark[4].x < hand_landmarks.landmark[3].x:
# Pulgar levantado
Etapa 5: Código de Detección de Dedos
A continuación, se presenta el código completo para la detección de dedos:
import cv2 # Importar OpenCV para manejo de video e imágenes
import mediapipe as mp # Importar MediaPipe para detección de manos
import numpy as np # Importar NumPy para operaciones numéricas
# Inicializar la solución de manos de MediaPipe
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils # Utilidad para dibujar la estructura de la mano
# Configuración de MediaPipe Hands
hands = mp_hands.Hands(
static_image_mode=False, # Modo video (detección continua)
max_num_hands=1, # Se detecta solo una mano
min_detection_confidence=0.7, # Confianza mínima para la detección inicial
min_tracking_confidence=0.7 # Confianza mínima para el seguimiento
)
# Función para contar los dedos levantados usando los landmarks
def count_fingers(hand_landmarks):
# Índices de las puntas de los dedos (thumb, index, middle, ring, pinky)
finger_tips = [4, 8, 12, 16, 20]
# Índices de las bases de cada dedo (usados para comparación)
finger_base = [3, 6, 10, 14, 18]
fingers = [] # Lista que almacenará 1 (dedo levantado) o 0 (dedo no levantado)
# Evaluar el pulgar (se compara la posición en el eje X)
if hand_landmarks.landmark[finger_tips[0]].x < hand_landmarks.landmark[finger_base[0]].x:
fingers.append(1) # Pulgar levantado
else:
fingers.append(0) # Pulgar no levantado
# Evaluar los otros dedos (comparando la posición en el eje Y)
for i in range(1, 5):
if hand_landmarks.landmark[finger_tips[i]].y < hand_landmarks.landmark[finger_base[i]].y:
fingers.append(1) # Dedo levantado
else:
fingers.append(0) # Dedo no levantado
return sum(fingers) # Retornar el número total de dedos levantados
# Inicializar la cámara web
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read() # Capturar frame por frame
if not ret:
break # Salir si no se puede leer un frame
# Convertir el frame de BGR a RGB para procesarlo con MediaPipe
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Procesar el frame para detectar manos
results = hands.process(frame_rgb)
# Si se detecta una mano, dibujar los landmarks y contar dedos
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# Dibujar la estructura (puntos y conexiones) de la mano en el frame
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
# Contar la cantidad de dedos levantados
fingers_up = count_fingers(hand_landmarks)
# Mostrar el número de dedos levantados en la ventana
cv2.putText(frame, f'Dedos levantados: {fingers_up}', (10, 70),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Mostrar el video con la detección de manos
cv2.imshow('Detección de Dedos', frame)
# Salir presionando la tecla 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Liberar la cámara y cerrar todas las ventanas abiertas
cap.release()
cv2.destroyAllWindows()
Etapa 6: Juego de Piedra, Papel o Tijera
En esta etapa implementamos un juego interactivo usando la detección de dedos. Se asignan los siguientes gestos:
- Rock (Piedra): 0 dedos levantados (puño cerrado)
- Scissors (Tijera): 2 dedos levantados (por ejemplo, índice y medio)
- Paper (Papel): 5 dedos levantados (mano abierta)
Además, se implementa una cuenta regresiva para capturar el gesto del usuario y se genera un movimiento aleatorio para la computadora. Se compara el resultado y se muestra en pantalla.
A continuación, el código completo con comentarios:
import cv2 # Importar OpenCV para manejo de video e imágenes
import mediapipe as mp # Importar MediaPipe para detección de manos
import numpy as np # Importar NumPy para operaciones numéricas
import random # Importar random para seleccionar movimientos aleatorios
import time # Importar time para gestionar la cuenta regresiva y temporizadores
# Inicializar MediaPipe Hands y la utilidad de dibujo
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
# Configuración de MediaPipe Hands para detección en tiempo real
hands = mp_hands.Hands(
static_image_mode=False, # Modo video
max_num_hands=1, # Detectar solo una mano
min_detection_confidence=0.7, # Umbral de confianza para la detección inicial
min_tracking_confidence=0.7 # Umbral de confianza para el seguimiento
)
# Función para contar los dedos levantados (igual que en la etapa anterior)
def count_fingers(hand_landmarks):
finger_tips = [4, 8, 12, 16, 20] # Índices de las puntas de cada dedo
finger_base = [3, 6, 10, 14, 18] # Índices para las bases de cada dedo
fingers = [] # Lista para almacenar 1 (levantado) o 0 (no levantado)
# Evaluar el pulgar (se compara en el eje X)
if hand_landmarks.landmark[finger_tips[0]].x < hand_landmarks.landmark[finger_base[0]].x:
fingers.append(1) # Pulgar levantado
else:
fingers.append(0) # Pulgar no levantado
# Evaluar los otros dedos (comparando en el eje Y)
for i in range(1, 5):
if hand_landmarks.landmark[finger_tips[i]].y < hand_landmarks.landmark[finger_base[i]].y:
fingers.append(1) # Dedo levantado
else:
fingers.append(0) # Dedo no levantado
return sum(fingers) # Retornar la suma de dedos levantados
# Función para mapear el número de dedos al gesto correspondiente
def get_gesture(fingers_up):
if fingers_up == 0:
return "Rock" # Puño cerrado representa 'Piedra'
elif fingers_up == 2:
return "Scissors" # Dos dedos levantados representan 'Tijera'
elif fingers_up == 5:
return "Paper" # Cinco dedos levantados representan 'Papel'
else:
return "Unknown" # Cualquier otro número no es reconocido
# Función para determinar el ganador del juego
def determine_winner(user_move, computer_move):
# Reglas del juego:
# - Rock vence a Scissors
# - Scissors vence a Paper
# - Paper vence a Rock
if user_move == computer_move:
return "Tie" # Empate
elif (user_move == "Rock" and computer_move == "Scissors") or \
(user_move == "Scissors" and computer_move == "Paper") or \
(user_move == "Paper" and computer_move == "Rock"):
return "User wins!" # Gana el usuario
else:
return "Computer wins!" # Gana la computadora
# Inicializar la cámara web
cap = cv2.VideoCapture(0)
# Variables para manejar la cuenta regresiva y el estado del juego
start_time = time.time() # Tiempo de inicio para la cuenta regresiva
game_started = False # Indica si ya se capturó el movimiento
captured_move = None # Almacena el movimiento detectado del usuario
while cap.isOpened():
ret, frame = cap.read() # Capturar un frame de la cámara
if not ret:
break
# Voltear el frame horizontalmente para un efecto de espejo
frame = cv2.flip(frame, 1)
# Convertir el frame de BGR a RGB para MediaPipe
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Procesar el frame para detectar la mano
results = hands.process(frame_rgb)
# Variable para almacenar el gesto detectado en el frame actual
user_move = "No hand detected"
# Si se detecta una mano, dibujar landmarks y contar dedos
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# Dibujar la estructura de la mano en el frame
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
# Contar los dedos levantados
fingers_up = count_fingers(hand_landmarks)
# Mapear el número de dedos al gesto correspondiente
user_move = get_gesture(fingers_up)
# Mostrar el gesto detectado en el frame
cv2.putText(frame, f'Gesture: {user_move}', (10, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
# Calcular el tiempo transcurrido para la cuenta regresiva
elapsed = time.time() - start_time
if elapsed < 3:
# Mostrar la cuenta regresiva (3, 2, 1...) en pantalla
cv2.putText(frame, f'Prepare: {int(3 - elapsed)}', (200, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
else:
if not game_started:
# Al finalizar la cuenta regresiva, capturamos el movimiento del usuario
captured_move = user_move
# Seleccionar aleatoriamente el movimiento de la computadora
computer_move = random.choice(["Rock", "Paper", "Scissors"])
# Determinar el resultado del juego comparando ambos movimientos
result = determine_winner(captured_move, computer_move)
game_started = True # Indicar que el movimiento ya fue capturado
result_time = time.time() # Guardar el tiempo para mostrar el resultado
else:
# Mostrar en pantalla el movimiento del usuario, de la computadora y el resultado
cv2.putText(frame, f'Your Move: {captured_move}', (10, 100),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f'Computer: {computer_move}', (10, 150),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f'Result: {result}', (10, 200),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# Reiniciar el juego después de 5 segundos para una nueva ronda
if time.time() - result_time > 5:
game_started = False
start_time = time.time() # Reiniciar la cuenta regresiva
# Mostrar el frame actualizado con el juego
cv2.imshow('Rock Paper Scissors', frame)
# Salir del juego presionando la tecla 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Liberar la cámara y cerrar todas las ventanas
cap.release()
cv2.destroyAllWindows()
Codigo ejemplo
import cv2
import mediapipe as mp
import numpy as np
# Inicializar MediaPipe Hands
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
# Configuración de MediaPipe Hands
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
# Función para contar dedos
def count_fingers(hand_landmarks):
# Coordenadas de los dedos basadas en los puntos clave de MediaPipe
finger_tips = [4, 8, 12, 16, 20]
finger_base = [3, 6, 10, 14, 18]
fingers = []
# Pulgar (comparar posición X)
if hand_landmarks.landmark[finger_tips[0]].x < hand_landmarks.landmark[finger_base[0]].x:
fingers.append(1)
else:
fingers.append(0)
# Otros dedos (comparar posición Y)
for i in range(1, 5):
if hand_landmarks.landmark[finger_tips[i]].y < hand_landmarks.landmark[finger_base[i]].y:
fingers.append(1)
else:
fingers.append(0)
return sum(fingers)
# Inicializar la cámara
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Convertir a RGB
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Procesar el marco
results = hands.process(frame_rgb)
# Dibujar y contar dedos
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
fingers_up = count_fingers(hand_landmarks)
cv2.putText(frame, f'Dedos levantados: {fingers_up}', (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Mostrar el video
cv2.imshow('Detección de Dedos', frame)
# Salir con la tecla 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Liberar recursos
cap.release()
cv2.destroyAllWindows()
Como ejecutar el programa
- en vscode seleccionar interprete y despues run
- en powershell ir a la carpeta contenedora y usar el comando
py deteccion_manos.py
Electrónica
Programación
Desafíos
Recursos
Videos
Video de ensamble de brazo robotico
Código
Aqui el codigo para mapear
import cv2
import mediapipe as mp
import numpy as np
# Inicializar MediaPipe Hands y Drawing Utils
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
# Configuración de MediaPipe Hands (se usa 1 mano, se puede ajustar según necesidad)
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
# Diccionario de mapeo complejo
# La clave es una tupla de 10 elementos, correspondiente a:
# (thumb_extended, thumb_curved, index_extended, index_curved,
# middle_extended, middle_curved, ring_extended, ring_curved,
# pinky_extended, pinky_curved)
#
# Los valores asociados son etiquetas que tú defines (por ejemplo, nombres de gestos o letras).
complex_gesture_mapping = {
(1, 1, 0, 0, 0, 0, 0, 0, 0, 0): 'PUNIO_CERRADO', # Puño cerrado
(0, 1, 1, 1, 1, 1, 1, 1, 1, 1): 'PALMA_ABIERTA', # Mano abierta
(0, 1, 0, 0, 0, 0, 0, 0, 0, 0): 'PULGAR_ARRIBA', # Ejemplo: solo el pulgar extendido y con curvatura (personalizable)
(1, 1, 1, 1, 0, 0, 0, 0, 0, 0): 'NUMERO_1', # NUMERO 1
# Puedes agregar más mapeos según las posiciones definidas en tu proyecto
}
def detect_complex_gesture(hand_landmarks):
"""
Genera un vector de 10 elementos (2 por cada dedo) usando varios landmarks:
- Para cada dedo, se calcula:
* "Extended": se compara la posición del tip con la base (PIP o similar)
* "Curved": se compara la posición del DIP (o el punto intermedio) con la base
La lógica puede ajustarse según las características de la seña.
"""
features = []
# Pulgar: usamos landmarks 4 (tip), 3 (IP) y 2 (MCP)
thumb_extended = 1 if hand_landmarks.landmark[4].x < hand_landmarks.landmark[3].x else 0
thumb_curved = 1 if hand_landmarks.landmark[4].y < hand_landmarks.landmark[2].y else 0
features.extend([thumb_extended, thumb_curved])
# Índice: landmarks 8 (tip), 6 (PIP) y 7 (DIP)
index_extended = 1 if hand_landmarks.landmark[8].y < hand_landmarks.landmark[6].y else 0
index_curved = 1 if hand_landmarks.landmark[7].y < hand_landmarks.landmark[6].y else 0
features.extend([index_extended, index_curved])
# Medio: landmarks 12 (tip), 10 (PIP) y 11 (DIP)
middle_extended = 1 if hand_landmarks.landmark[12].y < hand_landmarks.landmark[10].y else 0
middle_curved = 1 if hand_landmarks.landmark[11].y < hand_landmarks.landmark[10].y else 0
features.extend([middle_extended, middle_curved])
# Anular: landmarks 16 (tip), 14 (PIP) y 15 (DIP)
ring_extended = 1 if hand_landmarks.landmark[16].y < hand_landmarks.landmark[14].y else 0
ring_curved = 1 if hand_landmarks.landmark[15].y < hand_landmarks.landmark[14].y else 0
features.extend([ring_extended, ring_curved])
# Meñique: landmarks 20 (tip), 18 (PIP) y 19 (DIP)
pinky_extended = 1 if hand_landmarks.landmark[20].y < hand_landmarks.landmark[18].y else 0
pinky_curved = 1 if hand_landmarks.landmark[19].y < hand_landmarks.landmark[18].y else 0
features.extend([pinky_extended, pinky_curved])
return tuple(features)
# Mostrar en consola el diccionario de mapeo para referencia
print("Complex Gesture Mapping:")
for key, value in complex_gesture_mapping.items():
print(f"{key}: {value}")
# Inicializar la cámara
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Convertir el frame a RGB para el procesamiento con MediaPipe
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(frame_rgb)
# Procesar cada mano detectada
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# Dibujar landmarks de la mano
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
# Obtener el vector complejo de características
complex_features = detect_complex_gesture(hand_landmarks)
# Consultar el mapeo; si no existe, se muestra "Desconocido"
gesture_name = complex_gesture_mapping.get(complex_features, "Desconocido")
# Mostrar en pantalla el vector y la asignación del gesto
cv2.putText(frame, f'Features: {complex_features}', (10, 40),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
cv2.putText(frame, f'Gesture: {gesture_name}', (10, 80),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Mostrar el diccionario de mapeo en la parte inferior (opcional)
mapping_text = "Mapping: " + ", ".join([f"{k}:{v}" for k, v in complex_gesture_mapping.items()])
cv2.putText(frame, mapping_text, (10, frame.shape[0]-20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1)
cv2.imshow("Complex Gesture Mapping", frame)
# Salir con la tecla 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Enlaces
Enlaces a web Chareditor.
Enlaces a blog Instalacion de arduino.
Explicación detallada del código para detección de dedos con MediaPipe y OpenCV
En este documento se describe paso a paso el funcionamiento del código que utiliza la librería MediaPipe (en específico, el módulo de Hands) y OpenCV para detectar cuántos dedos de la mano están levantados. El código se compone de las siguientes secciones principales:
- Importaciones de las librerías necesarias
- Inicialización de la solución de MediaPipe Hands
- Definición de la función de conteo de dedos
- Captura y procesamiento de fotogramas de la cámara
- Dibujado de puntos clave y conteo de dedos
- Visualización y finalización de la ventana de video
A continuación, se muestra el código completo y se explica cada parte con detalle.
import cv2
import mediapipe as mp
import numpy as np
# Inicializar MediaPipe Hands
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
# Configuración de MediaPipe Hands
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
# Función para contar dedos
def count_fingers(hand_landmarks):
# Coordenadas de los dedos basadas en los puntos clave de MediaPipe
finger_tips = [4, 8, 12, 16, 20]
finger_base = [3, 6, 10, 14, 18]
fingers = []
# Pulgar (comparar posición X)
if hand_landmarks.landmark[finger_tips[0]].x < hand_landmarks.landmark[finger_base[0]].x:
fingers.append(1)
else:
fingers.append(0)
# Otros dedos (comparar posición Y)
for i in range(1, 5):
if hand_landmarks.landmark[finger_tips[i]].y < hand_landmarks.landmark[finger_base[i]].y:
fingers.append(1)
else:
fingers.append(0)
return sum(fingers)
# Inicializar la cámara
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Convertir a RGB
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Procesar el marco
results = hands.process(frame_rgb)
# Dibujar y contar dedos
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
fingers_up = count_fingers(hand_landmarks)
cv2.putText(frame, f'Dedos levantados: {fingers_up}', (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Mostrar el video
cv2.imshow('Detección de Dedos', frame)
# Salir con la tecla 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Liberar recursos
cap.release()
cv2.destroyAllWindows()
1. Importaciones de las librerías necesarias
import cv2
import mediapipe as mp
import numpy as np
- cv2: Corresponde a la librería OpenCV, la cual se encarga del procesamiento de imágenes y la captura de video.
- mediapipe as mp: Importa la librería MediaPipe. Esta librería contiene soluciones pre-entrenadas para reconocimiento de manos, rostros, posturas, etc.
- numpy as np: Se utiliza principalmente para operaciones matemáticas y de manejo de arreglos, aunque en este caso no se ve un uso destacado dentro del código.
2. Inicialización de la solución de MediaPipe Hands
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
- mp_hands: Aquí hacemos referencia al módulo de MediaPipe especializado en detección y seguimiento de manos (Hands).
- mp_drawing: Este módulo provee funciones para dibujar anotaciones y conexiones (landmarks) en la imagen (específicamente,
mp.solutions.drawing_utils).
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
- Hands(): Crea un objeto configurado para la detección y seguimiento de manos. Entre sus parámetros principales:
static_image_mode=False: Indica que el programa asume que se trata de un video o secuencia de imágenes, no de una imagen estática. De esta manera se optimiza el rendimiento.max_num_hands=1: Indica cuántas manos como máximo se van a detectar.min_detection_confidence=0.7: Nivel mínimo de confianza (0-1) para considerar que una detección es válida.min_tracking_confidence=0.7: Nivel mínimo de confianza para el seguimiento de la mano detectada.
3. Definición de la función de conteo de dedos
def count_fingers(hand_landmarks):
# Coordenadas de los dedos basadas en los puntos clave de MediaPipe
finger_tips = [4, 8, 12, 16, 20]
finger_base = [3, 6, 10, 14, 18]
fingers = []
- Se definen dos listas:
- finger_tips: Son los índices dentro de la lista de landmarks que corresponden a las puntas de los dedos pulgar (4), índice (8), medio (12), anular (16) y meñique (20).
- finger_base: Son los índices que corresponden a la base de los mismos dedos (3, 6, 10, 14 y 18, respectivamente).
# Pulgar (comparar posición X)
if hand_landmarks.landmark[finger_tips[0]].x < hand_landmarks.landmark[finger_base[0]].x:
fingers.append(1)
else:
fingers.append(0)
- Para el pulgar, se compara la posición en el eje X (horizontal):
- Si la punta del pulgar (finger_tips[0]) está a la izquierda (menor X) que la base del pulgar (finger_base[0]), se considera que el pulgar está “levantado” (o extendido) y se añade un
1. - De lo contrario, se añade un
0.
- Si la punta del pulgar (finger_tips[0]) está a la izquierda (menor X) que la base del pulgar (finger_base[0]), se considera que el pulgar está “levantado” (o extendido) y se añade un
# Otros dedos (comparar posición Y)
for i in range(1, 5):
if hand_landmarks.landmark[finger_tips[i]].y < hand_landmarks.landmark[finger_base[i]].y:
fingers.append(1)
else:
fingers.append(0)
- Para los otros cuatro dedos (índice, medio, anular y meñique), se compara la posición en el eje Y:
- Si la punta del dedo (finger_tips[i]) está por encima (menor Y) de la base del dedo (finger_base[i]), se entiende que el dedo está extendido y se añade un
1. - De lo contrario, se añade un
0.
- Si la punta del dedo (finger_tips[i]) está por encima (menor Y) de la base del dedo (finger_base[i]), se entiende que el dedo está extendido y se añade un
return sum(fingers)
- Finalmente, se devuelve la suma de todos los valores en
fingers. Esta suma representa la cantidad de dedos levantados.
4. Captura y procesamiento de fotogramas de la cámara
cap = cv2.VideoCapture(0)
- Se crea un objeto
VideoCaptureque abre la cámara (normalmente la cámara principal es0).
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
- Se entra en un bucle (loop) que funcionará mientras la cámara esté abierta.
ret, frame = cap.read()obtiene un fotograma de la cámara:retes un valor booleano que indica si la lectura de la imagen fue exitosa.framees la imagen (matriz de pixeles) capturada.
- Si
retesFalse, significa que no se pudo leer la imagen, y se finaliza el bucle.
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(frame_rgb)
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)convierte la imagen de formato BGR (formato que usa OpenCV por defecto) a RGB (requerido por MediaPipe).results = hands.process(frame_rgb)procesa la imagen y detecta los landmarks de la mano, si los hay. Este objetoresultscontendrá la información de la(s) mano(s) detectadas.
5. Dibujado de puntos clave y conteo de dedos
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
fingers_up = count_fingers(hand_landmarks)
cv2.putText(frame, f'Dedos levantados: {fingers_up}', (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
results.multi_hand_landmarkses una lista que contiene los landmarks de todas las manos detectadas.- Se itera sobre cada mano detectada y se:
- Dibujan los landmarks y sus conexiones en el
frameutilizandomp_drawing.draw_landmarks.framees el fotograma de video en BGR.hand_landmarkses la estructura que contiene los 21 puntos clave de la mano.mp_hands.HAND_CONNECTIONSindica cómo conectar estos puntos (líneas entre los landmarks).
- Se llama a
count_fingers(hand_landmarks)para obtener cuántos dedos están levantados. - Se dibuja el texto sobre el fotograma utilizando
cv2.putText:- El texto indica el número de dedos levantados.
- La posición del texto es
(10, 70). - Se usa la fuente
cv2.FONT_HERSHEY_SIMPLEX, con tamaño1, color verde(0, 255, 0)y grosor de línea2.
- Dibujan los landmarks y sus conexiones en el
6. Visualización y finalización de la ventana de video
cv2.imshow('Detección de Dedos', frame)
- Se muestra el fotograma con los landmarks y el texto en una ventana llamada
"Detección de Dedos".
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.waitKey(1)espera 1 milisegundo para detectar si el usuario ha presionado alguna tecla.& 0xFFse utiliza para obtener el valor ASCII de la tecla presionada.ord('q')es el valor ASCII de la letra ‘q’.- Si se presiona ‘q’, se rompe el bucle
whiley se cierra la ventana.
cap.release()
cv2.destroyAllWindows()
cap.release()libera la cámara.cv2.destroyAllWindows()cierra todas las ventanas de OpenCV abiertas.
Al presionar la tecla ‘q’, la ejecución se detiene, se libera la cámara y se cierran las ventanas de OpenCV.