Type something to search...
Visión artificial 3° A

Visión artificial 3° A

Link de la sesion de meet:

Link para la reunion de domingo 16 febrero 2025 actualizada https://meet.google.com/aox-anan-ttp

Índice

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

  1. Descarga la version recomendada para el proyecto python 3.12

  2. Instala PowerShell aqui

  3. 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:

  1. Instalación: Descarga e instala Python desde python.org.
  2. Editor/IDE: Puedes usar editores como VSCode, PyCharm o incluso Jupyter Notebook.
  3. 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:

  1. Captura de video: Se obtiene el frame desde la cámara.
  2. Conversión de color: OpenCV captura en BGR; MediaPipe requiere RGB.
  3. Procesamiento: MediaPipe detecta la mano y devuelve los landmarks.
  4. 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 (x o y) 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:

  1. Importaciones de las librerías necesarias
  2. Inicialización de la solución de MediaPipe Hands
  3. Definición de la función de conteo de dedos
  4. Captura y procesamiento de fotogramas de la cámara
  5. Dibujado de puntos clave y conteo de dedos
  6. 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.
    # 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.
    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 VideoCapture que abre la cámara (normalmente la cámara principal es 0).
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:
    • ret es un valor booleano que indica si la lectura de la imagen fue exitosa.
    • frame es la imagen (matriz de pixeles) capturada.
  • Si ret es False, 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 objeto results contendrá 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_landmarks es una lista que contiene los landmarks de todas las manos detectadas.
  • Se itera sobre cada mano detectada y se:
    1. Dibujan los landmarks y sus conexiones en el frame utilizando mp_drawing.draw_landmarks.
      • frame es el fotograma de video en BGR.
      • hand_landmarks es la estructura que contiene los 21 puntos clave de la mano.
      • mp_hands.HAND_CONNECTIONS indica cómo conectar estos puntos (líneas entre los landmarks).
    2. Se llama a count_fingers(hand_landmarks) para obtener cuántos dedos están levantados.
    3. 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ño 1, color verde (0, 255, 0) y grosor de línea 2.

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.
  • & 0xFF se 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 while y 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.

Publicaciones relacionadas

ATR 1° - 2° [Primaria]

ATR 1° - 2° [Primaria]

ÍndiceExplicación del Proyecto Materiales necesarios Herramientas [1](#inicialización-de

read more
Brazo Robótico 2° A

Brazo Robótico 2° A

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceExplicación del Proyecto Materiales necesarios [H

read more
Carreras de carritos 1° A

Carreras de carritos 1° A

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceÍndice Explicación del Proyecto [Materiales necesarios](#materiales-n

read more
Robot Programable 2° B

Robot Programable 2° B

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; Explicación del Proyecto Este proyecto se centra en el desarrollo de un robot programable utilizando Arduino, cuyo objetivo

read more
Elevador 5° [Primaria]

Elevador 5° [Primaria]

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceExplicación del Proyecto Materiales necesarios

read more
Figuras con luz 1° - 2° [Primaria]

Figuras con luz 1° - 2° [Primaria]

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceExplicación del Proyecto Materiales necesarios

read more
Control de motor eléctrico para automoviles

Control de motor eléctrico para automoviles

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceExplicación del Proyecto Materiales necesarios [H

read more
Programacion en Scratch 1° - 2° [Primaria]

Programacion en Scratch 1° - 2° [Primaria]

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceExplicación del Proyecto Materiales necesarios

read more
Semáforo con pluma de crucero 4° [Primaria]

Semáforo con pluma de crucero 4° [Primaria]

import YouTubeEmbed from '../../layouts/components/YouTubeEmbed.astro'; ÍndiceExplicación del Proyecto Materiales necesarios

read more