MediaPipe to potężna i wszechstronna biblioteka Google, która umożliwia tworzenie aplikacji do rozpoznawania gestów, śledzenia obiektów i wielu innych zadań związanych z przetwarzaniem obrazu i wideo. Dzięki swojej prostocie i wydajności, MediaPipe stał się popularnym narzędziem wśród programistów i entuzjastów sztucznej inteligencji.

W tym artykule pokażemy, jak wykorzystać MediaPipe do rozpoznawania gestów dłoni w czasie rzeczywistym, tworząc prostą grę „papier, kamień, nożyce”. Ten przykład pozwoli Ci zrozumieć podstawowe koncepcje i otworzy drzwi do tworzenia bardziej zaawansowanych aplikacji.

Google AI Edge i MediaPipe Gesture Recognizer

Rozpoznawanie gestów to kluczowy element interakcji człowiek-komputer, a platforma Google AI Edge wraz z zadaniem MediaPipe Gesture Recognizer oferuje potężne narzędzia do jego implementacji. Google AI Edge to platforma deweloperska, która umożliwia uruchamianie modeli uczenia maszynowego na urządzeniach brzegowych, takich jak smartfony czy komputery, co zapewnia szybkość i prywatność przetwarzania.

Zadanie MediaPipe Gesture Recognizer, będące częścią Google AI Edge, pozwala na rozpoznawanie gestów dłoni w czasie rzeczywistym. Wykorzystuje modele uczenia maszynowego do przetwarzania obrazów z kamery i zwraca informacje o położeniu dłoni, ich stronności oraz rozpoznanych gestach.

Funkcje MediaPipe Gesture Recognizer

  • Przetwarzanie obrazu: Zadanie automatycznie przetwarza obrazy z kamery, obejmując obrót, zmianę rozmiaru, normalizację i konwersję przestrzeni barw.
  • Progowanie wyników: Możliwość filtrowania wyników rozpoznawania gestów na podstawie progu pewności, co pozwala na eliminację fałszywych detekcji.
  • Listy dozwolonych i zablokowanych etykiet: Możliwość definiowania, które gesty mają być rozpoznawane, a które ignorowane.
  • Różne tryby pracy: Zadanie obsługuje różne tryby pracy, w tym przetwarzanie pojedynczych obrazów, strumieni wideo i danych z kamery na żywo.

Instalacja i konfiguracja

Przed rozpoczęciem upewnij się, że masz zainstalowane niezbędne biblioteki:

pip install opencv-python mediapipe

Implementacja rozpoznawania gestów

Kamień norzyce.

Aplikacja ma rozpoznać rękę (lewa, prawa) oraz na podstawie gestu podjąć decyzję o wygranym.

Tym razem norzyce papier.
Papier nożyce
Kamień koamień (gest Trumpa)- remis,

Dzialanie mechanizmu identyfikacji dłoni pozwla zarówno rozróżnić lewą i prawą stronę, bardzo szcegółowo opisuje to dokumentacja Google:

Przedstawiona definicja zdecydowanie ułatwia identyfikacje poszczególnych segmentów i zwalnia programistę z konieczności żmudnego procesu tworzenia wzorców (modeli) do rozpoznawania szczegółów.

Przykładowy kod, który implementuje rozpoznawanie gestów i logikę gry „papier, kamień, nożyce” działającą jak w załaczonych obrazkach:

 import cv2
import mediapipe as mp
import time

mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils

hands = mp_hands.Hands(
    static_image_mode=False,
    max_num_hands=2,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

def count_fingers(hand_landmarks):
    tips = [8, 12, 16, 20]
    count = 0
    for tip in tips:
        if hand_landmarks.landmark[tip].y < hand_landmarks.landmark[tip - 2].y:
            count += 1
    if hand_landmarks.landmark[4].x > hand_landmarks.landmark[2].x:
        count += 1
    return count

def detect_gesture(hand_landmarks, is_right):
    tips = [8, 12, 16, 20]
    fingers = []
    for tip in tips:
        extended = hand_landmarks.landmark[tip].y < hand_landmarks.landmark[tip - 2].y
        fingers.append(extended)

    index, middle, ring, pinky = fingers

    thumb = hand_landmarks.landmark[4].x < hand_landmarks.landmark[3].x if is_right else hand_landmarks.landmark[4].x > hand_landmarks.landmark[3].x

    if not any(fingers) and not thumb:
        return "Rock"
    elif all(fingers) and thumb:
        return "Paper"
    elif index and middle and not ring and not pinky:
        return "Scissors"
    else:
        return "Unknown"

def decide_winner(gesture1, gesture2):
    rules = {
        "Rock": "Scissors",
        "Scissors": "Paper",
        "Paper": "Rock"
    }
    if gesture1 == gesture2:
        return "Draw"
    elif rules.get(gesture1) == gesture2:
        return "Player 1 Wins"
    else:
        return "Player 2 Wins"

while True:
    countdown = 5
    while countdown > 0:
        ret, frame = cap.read()
        cv2.putText(frame, str(countdown), (250, 200), cv2.FONT_HERSHEY_SIMPLEX, 5, (255, 0, 0), 5)
        cv2.imshow("Rock Paper Scissors", frame)
        cv2.waitKey(1000)
        countdown -= 1

    gestures = ["?", "?"]
    hand_labels = ["", ""]
    outcome = "Need 2 hands"

    while True:
        ret, frame = cap.read()
        results = hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

        if results.multi_hand_landmarks and results.multi_handedness:
            for idx, (hand_landmarks, handedness) in enumerate(zip(results.multi_hand_landmarks, results.multi_handedness)):
                label = handedness.classification[0].label
                is_right = label == "Right"
                gesture = detect_gesture(hand_landmarks, is_right)
                gestures[idx] = gesture
                hand_labels[idx] = label

                mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
                x = int(hand_landmarks.landmark[0].x * frame.shape[1])
                y = int(hand_landmarks.landmark[0].y * frame.shape[0])
                cv2.putText(frame, f"{label} - Hand {idx+1}", (x, y - 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2)

            if gestures[0] != "?" and gestures[1] != "?":
                outcome = decide_winner(gestures[0], gestures[1])

        cv2.putText(frame, f"{hand_labels[0]} Hand 1: {gestures[0]}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)
        cv2.putText(frame, f"{hand_labels[1]} Hand 2: {gestures[1]}", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)
        cv2.putText(frame, f"Result: {outcome}", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0,0,255), 3)

        cv2.imshow("Rock Paper Scissors", frame)
        key = cv2.waitKey(1)
        if key & 0xFF == ord('n'):
            break
        elif key & 0xFF == ord('q'):
            cap.release()
            cv2.destroyAllWindows()
            exit() 

Podsumowanie

Ten przykład pokazuje, jak łatwo można wykorzystać MediaPipe i Google AI Edge do rozpoznawania gestów dłoni i tworzenia interaktywnych aplikacji. Możesz rozszerzyć ten kod, dodając własne gesty, interfejs użytkownika lub integrację z innymi systemami. W planowaniu procesów można brać pod uwagę alternatywne metody odpowiedzi na interakcje systemu w oparciu o identyfikacje pozycji głoni czy palców.

MediaPipe oferuje szeroki zakres możliwości, a rozpoznawanie nie tylko gestów, ale pozy ciała, twarzy to tylko jedna z nich. Zachęcamy do eksperymentowania i odkrywania potencjału tej potężnej biblioteki i platformy Google AI Edge.

Źródła

  1. https://ai.google.dev/edge/mediapipe/solutions/vision/gesture_recognizer?hl=pl
  2. https://github.com/GrzegorzOle/Mediapipe-Rock-Paper-Scissors