Przewodnik po rozpoznaniu gestów w systemie iOS

Zadanie MediaPipe Gesture Recognizer umożliwia rozpoznawanie gestów dłoni w czasie rzeczywistym. Wyniki rozpoznawania gestów dłoni oraz punkty orientacyjne dłoni wykrywanych dłoni. Te instrukcje pokazują, jak używać rozpoznawania gestów w aplikacjach na iOS.

Aby zobaczyć to zadanie w działaniu, obejrzyj prezentację internetową. Więcej informacji o możliwościach, modelach i opcjach konfiguracji tego zadania znajdziesz w sekcji Omówienie.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to podstawowe wdrożenie aplikacji rozpoznawania gestów na iOS. Przykład używa kamery na fizycznym urządzeniu z iOS do ciągłego wykrywania gestów dłoni. Może też używać obrazów i filmów z galerii urządzenia do statycznego wykrywania gestów.

Możesz użyć tej aplikacji jako punktu wyjścia do tworzenia własnej aplikacji na iOS lub jako odniesienia podczas modyfikowania istniejącej aplikacji. Przykładowy kod rozpoznawania gestów jest hostowany na GitHub.

Pobieranie kodu

Z tych instrukcji dowiesz się, jak utworzyć lokalną kopię przykładowego kodu za pomocą narzędzia wiersza poleceń git.

Aby pobrać przykładowy kod:

  1. Sklonuj repozytorium Git za pomocą tego polecenia:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie skonfiguruj instancję git, aby używać rzadkiego sprawdzania, dzięki czemu będziesz mieć tylko pliki przykładowej aplikacji rozpoznawania gestów:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/gesture_recognizer/ios/
    

Po utworzeniu lokalnej wersji przykładowego kodu możesz zainstalować bibliotekę zadań MediaPipe, otworzyć projekt za pomocą Xcode i uruchomić aplikację. Instrukcje znajdziesz w przewodniku konfiguracji na iOS.

Kluczowe komponenty

Te pliki zawierają kluczowy kod aplikacji przykładowej rozpoznawania gestów:

  • GestureRecognizerService.swift: inicjuje narzędzie do rozpoznawania gestów, obsługuje wybór modelu i wywołuje wnioskowanie na podstawie danych wejściowych.
  • CameraViewController.swift: implementuje interfejs użytkownika w trybie podglądu na żywo z kamery i wizualizuje wyniki.
  • MediaLibraryViewController.swift implementuje interfejs użytkownika dla trybu wprowadzania statycznych obrazów i plików wideo oraz wizualizuje wyniki.

Konfiguracja

W tej sekcji opisaliśmy najważniejsze kroki konfigurowania środowiska programistycznego i projektów kodu na potrzeby używania usługi Rozpoznawanie gestów. Ogólne informacje o konfigurowaniu środowiska programistycznego do korzystania z zadań MediaPipe, w tym wymagania dotyczące wersji platformy, znajdziesz w przewodniku konfiguracji dla iOS.

Zależności

Rozpoznawanie gestów korzysta z biblioteki MediaPipeTasksVision, którą należy zainstalować za pomocą CocoaPods. Biblioteka jest zgodna z aplikacją w języku Swift i Objective-C i nie wymaga dodatkowej konfiguracji językowej.

Instrukcje instalacji CocoaPods na macOS znajdziesz w przewodniku instalacji CocoaPods. Instrukcje tworzenia Podfile z podstawowymi komponentami potrzebnymi do działania aplikacji znajdziesz w artykule Korzystanie z CocoaPods.

Dodaj podproces MediaPipeTasksVision w pliku Podfile, używając tego kodu:

target 'MyGestureRecognizerApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

Jeśli Twoja aplikacja zawiera cele testu jednostkowego, zapoznaj się z przewodnikiem konfiguracji dla iOS, w którym znajdziesz dodatkowe informacje o konfigurowaniu Podfile.

Model

Zadanie rozpoznawania gestów MediaPipe wymaga wytrenowanego modelu, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach usługi Rozpoznawanie gestów znajdziesz w sekcji Modele w omówieniu zadania.

Wybierz i pobierz model, a potem dodaj go do katalogu projektu za pomocą Xcode. Instrukcje dodawania plików do projektu Xcode znajdziesz w artykule Zarządzanie plikami i folderami w projekcie Xcode.

Użyj właściwości BaseOptions.modelAssetPath, aby określić ścieżkę do modelu w pakiecie aplikacji. Przykład kodu znajdziesz w następnej sekcji.

Tworzenie zadania

Zadaniem rozpoznawania gestów możesz utworzyć, wywołując jedną z jego funkcji inicjującej. Inicjalizator GestureRecognizer(options:) może przyjmować wartości opcji konfiguracji.

Jeśli nie potrzebujesz rozpoznawania gestów zainicjowanego za pomocą niestandardowych opcji konfiguracji, możesz użyć funkcji inicjalizującej GestureRecognizer(modelPath:), aby utworzyć rozpoznawanie gestów z opcjami domyślnymi. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.

Zadanie rozpoznawania gestów obsługuje 3 typy danych wejściowych: obrazy, pliki wideo i transmisje na żywo. Domyślnie GestureRecognizer(modelPath:) inicjuje zadanie dotyczące zdjęć statycznych. Jeśli chcesz zainicjować zadanie przetwarzania plików wideo lub transmisji wideo na żywo, użyj właściwości GestureRecognizer(options:), aby określić tryb działania wideo lub transmisji na żywo. Tryb transmisji na żywo wymaga też dodatkowej opcji konfiguracji gestureRecognizerLiveStreamDelegate, która umożliwia modułowi rozpoznawania gestów asynchroniczne przesyłanie wyników rozpoznawania gestów do delegata.

Aby dowiedzieć się, jak utworzyć zadanie i przeprowadzić wnioskowanie, wybierz kartę odpowiadającą trybowi działania.

Swift

Obraz

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "gesture_recognizer",
                                      ofType: "task")

let options = GestureRecognizerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let gestureRecognizer = try GestureRecognizer(options: options)
    

Wideo

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "gesture_recognizer",
                                      ofType: "task")

let options = GestureRecognizerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let gestureRecognizer = try GestureRecognizer(options: options)
    

Transmisja na żywo

import MediaPipeTasksVision

// Class that conforms to the `GestureRecognizerLiveStreamDelegate` protocol and
// implements the method that the gesture recognizer calls once it finishes
// performing recognizing hand gestures in each input frame.
class GestureRecognizerResultProcessor: NSObject, GestureRecognizerLiveStreamDelegate {

  func gestureRecognizer(
    _ gestureRecognizer: GestureRecognizer,
    didFinishRecognition result: GestureRecognizerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the gesture recognizer result or errors here.

  }
}

let modelPath = Bundle.main.path(
  forResource: "gesture_recognizer",
  ofType: "task")

let options = GestureRecognizerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

// Assign an object of the class to the `gestureRecognizerLiveStreamDelegate`
// property.
let processor = GestureRecognizerResultProcessor()
options.gestureRecognizerLiveStreamDelegate = processor

let gestureRecognizer = try GestureRecognizer(options: options)
    

Objective-C

Obraz

@import MediaPipeTasksVision;

NSString *modelPath =
  [[NSBundle mainBundle] pathForResource:@"gesture_recognizer"
                                  ofType:@"task"];

MPPGestureRecognizerOptions *options =
  [[MPPGestureRecognizerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

MPPGestureRecognizer *gestureRecognizer =
      [[MPPGestureRecognizer alloc] initWithOptions:options error:nil];
    

Wideo

@import MediaPipeTasksVision;

NSString *modelPath =
  [[NSBundle mainBundle] pathForResource:@"gesture_recognizer"
                                  ofType:@"task"];

MPPGestureRecognizerOptions *options =
  [[MPPGestureRecognizerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

MPPGestureRecognizer *gestureRecognizer =
      [[MPPGestureRecognizer alloc] initWithOptions:options error:nil];
    

Transmisja na żywo

@import MediaPipeTasksVision;

// Class that conforms to the `MPPGestureRecognizerLiveStreamDelegate` protocol
// and implements the method that the gesture recognizer calls once it finishes
// performing gesture recognition on each input frame.

@interface APPGestureRecognizerResultProcessor : NSObject 

@end

@implementation APPGestureRecognizerResultProcessor

-   (void)gestureRecognizer:(MPPGestureRecognizer *)gestureRecognizer
    didFinishRecognitionWithResult:(MPPGestureRecognizerResult *)gestureRecognizerResult
           timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                             error:(NSError *)error {

    // Process the gesture recognizer result or errors here.

}

@end

NSString *modelPath =
  [[NSBundle mainBundle] pathForResource:@"gesture_recognizer"
                                  ofType:@"task"];

MPPGestureRecognizerOptions *options =
  [[MPPGestureRecognizerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

// Assign an object of the class to the `gestureRecognizerLiveStreamDelegate`
// property.
APPGestureRecognizerResultProcessor *processor =
  [APPGestureRecognizerResultProcessor new];
options.gestureRecognizerLiveStreamDelegate = processor;

MPPGestureRecognizer *gestureRecognizer =
      [[MPPGestureRecognizer alloc] initWithOptions:options error:nil];
    

Opcje konfiguracji

To zadanie zawiera te opcje konfiguracji aplikacji na iOS:

Nazwa opcji Opis Zakres wartości Wartość domyślna
runningMode Ustawia tryb działania zadania. Dostępne są 3 tryby:

IMAGE (Obraz): tryb do wprowadzania pojedynczych obrazów.

FILM: tryb dekodowanych klatek filmu.

TRANSMISJA NA ŻYWO: tryb transmisji danych wejściowych, np. z kamery. W tym trybie należy wywołać metodę resultListener, aby skonfigurować odbiornik, który będzie asynchronicznie odbierał wyniki. W tym trybie gestureRecognizerLiveStreamDelegate musi być ustawiony jako instancja klasy, która implementuje GestureRecognizerLiveStreamDelegate, aby otrzymywać wyniki asynchronicznego rozpoznawania gestów.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_hands Maksymalna liczba dłoni, które może wykryć GestureRecognizer, to Any integer > 0 1
min_hand_detection_confidence Minimalny wynik ufności wykrywania dłoni, który jest uznawany za udany w przypadku modelu wykrywania dłoni. 0.0 - 1.0 0.5
min_hand_presence_confidence Minimalny wynik ufności obecności ręki w modelu wykrywania punktów orientacyjnych ręki. W trybie wideo i w trybie strumieniowania na żywo w rozpoznawaniu gestów, jeśli wskaźnik ufności obecności ręki z modelu punktów orientacyjnych ręki jest poniżej tego progu, uruchamia model wykrywania dłoni. W przeciwnym razie do określenia położenia dłoni służy lekki algorytm śledzenia dłoni, który służy do wykrywania punktów orientacyjnych. 0.0 - 1.0 0.5
min_tracking_confidence Minimalny wynik ufności śledzenia dłoni, który jest uznawany za udany. To próg współczynnika podobieństwa ramki ograniczającej między dłońmi w bieżącej i ostatniej ramie. W trybie wideo i strumień w rozpoznawaniu gestów, jeśli śledzenie zawiedzie, rozpoznawanie gestów uruchamia wykrywanie ręki. W przeciwnym razie wykrywanie dłoni zostanie pominięte. 0.0 - 1.0 0.5
canned_gestures_classifier_options Opcje konfiguracji zachowania klasyfikatora gotowych gestów. Gotowe gesty: ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"]
  • Język wyświetlanych nazw: język, którego należy używać do wyświetlanych nazw określonych w metadanych modelu TFLite (jeśli istnieją).
  • Maksymalna liczba wyników: maksymalna liczba najwyżej punktowanych wyników klasyfikacji do zwrócenia. Jeśli wartość jest mniejsza od 0, zwracane są wszystkie dostępne wyniki.
  • Próg wyniku: wynik, poniżej którego wyniki są odrzucane. Jeśli ustawisz wartość 0, zwrócone zostaną wszystkie dostępne wyniki.
  • Lista dozwolonych kategorii: lista dozwolonych nazw kategorii. Jeśli niepuste wyniki klasyfikacji nie należą do tego zbioru, zostaną odfiltrowane. Wyklucza się z listą blokowanych adresów.
  • Lista odrzuconych kategorii: lista odrzuconych nazw kategorii. Jeśli nie są puste, wyniki klasyfikacji, których kategoria należy do tego zbioru, zostaną odfiltrowane. Wyklucza się z listą dozwolonych.
    • Język wyświetlania nazw: any string
    • Maksymalna liczba wyników: any integer
    • Próg wyniku: 0.0-1.0
    • Lista dozwolonych kategorii: vector of strings
    • Lista odrzuconych kategorii: vector of strings
    • Język wyświetlania nazw: "en"
    • Maks. liczba wyników: -1
    • Próg wyniku: 0
    • Lista dozwolonych kategorii: pusta
    • Lista odrzuconych kategorii: pusta
    custom_gestures_classifier_options Opcje konfigurowania działania klasyfikatora gestów niestandardowych.
  • Język wyświetlanych nazw: język, którego należy używać do wyświetlanych nazw określonych w metadanych modelu TFLite (jeśli istnieją).
  • Maksymalna liczba wyników: maksymalna liczba najwyżej punktowanych wyników klasyfikacji do zwrócenia. Jeśli wartość jest mniejsza od 0, zwracane są wszystkie dostępne wyniki.
  • Próg wyniku: wynik, poniżej którego wyniki są odrzucane. Jeśli ustawisz wartość 0, zwrócone zostaną wszystkie dostępne wyniki.
  • Lista dozwolonych kategorii: lista dozwolonych nazw kategorii. Jeśli niepuste wyniki klasyfikacji nie należą do tego zbioru, zostaną odfiltrowane. Wyklucza się z listą blokowanych adresów.
  • Lista odrzuconych kategorii: lista odrzuconych nazw kategorii. Jeśli nie są puste, wyniki klasyfikacji, których kategoria należy do tego zbioru, zostaną odfiltrowane. Wyklucza się z listą dozwolonych.
    • Język wyświetlania nazw: any string
    • Maksymalna liczba wyników: any integer
    • Próg wyniku: 0.0-1.0
    • Lista dozwolonych kategorii: vector of strings
    • Lista odrzuconych kategorii: vector of strings
    • Język wyświetlania nazw: "en"
    • Maks. liczba wyników: -1
    • Próg wyniku: 0
    • Lista dozwolonych kategorii: pusta
    • Lista odrzuconych kategorii: pusta
    result_listener Gdy rozpoznawanie gestów jest w trybie transmisji na żywo, słuchacz wyników otrzymuje wyniki klasyfikacji asynchronicznie. Tej opcji można używać tylko wtedy, gdy tryb działania jest ustawiony na LIVE_STREAM ResultListener Nie dotyczy Nie dotyczy

    Gdy tryb działania jest ustawiony na „transmisja na żywo”, moduł rozpoznawania gestów wymaga dodatkowej opcji konfiguracji gestureRecognizerLiveStreamDelegate, która umożliwia asynchroniczne rozpoznawanie gestów. Delegat musi zaimplementować metodę gestureRecognizer(_:didFinishRecognition:timestampInMilliseconds:error:), którą usługa rozpoznawania gestów wywołuje po przetworzeniu wyników rozpoznawania gestów w każdej klatce.

    Nazwa opcji Opis Zakres wartości Wartość domyślna
    gestureRecognizerLiveStreamDelegate Umożliwia usługie Rozpoznawanie gestów asynchroniczne otrzymywanie wyników rozpoznawania gestów w trybie transmisji na żywo. Klasa, której instancja jest ustawiona na tę właściwość, musi implementować metodę gestureRecognizer(_:didFinishRecognition:timestampInMilliseconds:error:). Nie dotyczy Nie ustawiono

    Przygotuj dane

    Przed przekazaniem go do usługi rozpoznawania gestów musisz przekonwertować podany obraz lub ramkę na obiekt MPImage. MPImage obsługuje różne typy formatów obrazów iOS i może ich używać w dowolnym trybie działania do wnioskowania. Więcej informacji o MPImage znajdziesz w dokumentacji interfejsu MPImage API.

    Wybierz format obrazu iOS na podstawie przypadku użycia i trybułu działania wymaganego przez aplikację. MPImage obsługuje formaty obrazów iOS UIImage, CVPixelBufferCMSampleBuffer.

    UIImage

    Format UIImage jest odpowiedni do tych trybów działania:

    • Obrazy: obrazy z pakietu aplikacji, galerii użytkownika lub systemu plików sformatowane jako obrazy UIImage można przekształcić w obiekt MPImage.

    • Filmy: użyj narzędzia AVAssetImageGenerator, aby wyodrębnić klatki wideo do formatu CGImage, a następnie przekonwertuj je na obrazy UIImage.

    Swift

    // Load an image on the user's device as an iOS `UIImage` object.
    
    // Convert the `UIImage` object to a MediaPipe's Image object having the default
    // orientation `UIImage.Orientation.up`.
    let image = try MPImage(uiImage: image)
        

    Objective-C

    // Load an image on the user's device as an iOS `UIImage` object.
    
    // Convert the `UIImage` object to a MediaPipe's Image object having the default
    // orientation `UIImageOrientationUp`.
    MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
        

    Ten przykład inicjuje obiekt MPImage z domyślną orientacją UIImage.Orientation.Up. Możesz zainicjować MPImage przy użyciu dowolnej z obsługiwanych wartości UIImage.Orientation. Moduł rozpoznawania gestów nie obsługuje lustrzanych orientacji, takich jak .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

    Więcej informacji o UIImage znajdziesz w dokumentacji UIImage dla deweloperów Apple.

    CVPixelBuffer

    Format CVPixelBuffer sprawdza się w aplikacjach, które generują ramki i wykorzystują do przetwarzania platformę CoreImage na iOS.

    Format CVPixelBuffer jest odpowiedni do tych trybów działania:

    • Obrazy: aplikacje, które generują obrazy CVPixelBuffer po przetworzeniu ich za pomocą interfejsu CoreImage w iOS, mogą być wysyłane do rozpoznawacza gestów w trybie uruchamiania obrazu.

    • Filmy: ramki wideo można przekształcić w format CVPixelBuffer do przetwarzania, a następnie wysłać do rozpoznawania gestów w trybie wideo.

    • transmisja na żywo: aplikacje korzystające z kamery iOS do generowania klatek mogą być konwertowane do formatu CVPixelBuffer na potrzeby przetwarzania przed wysłaniem do rozpoznawacza gestów w trybie transmisji na żywo.

    Swift

    // Obtain a CVPixelBuffer.
    
    // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
    // orientation `UIImage.Orientation.up`.
    let image = try MPImage(pixelBuffer: pixelBuffer)
        

    Objective-C

    // Obtain a CVPixelBuffer.
    
    // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
    // default orientation `UIImageOrientationUp`.
    MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
        

    Więcej informacji o CVPixelBuffer znajdziesz w dokumentacji dla deweloperów Apple dotyczącej CVPixelBuffer.

    CMSampleBuffer

    Format CMSampleBuffer przechowuje próbki multimediów o jednolitym typie i jest odpowiedni do uruchamiania transmisji na żywo. Ramki na żywo z kamer iOS są asynchronicznie dostarczane w formacie CMSampleBuffer przez AVCaptureVideoDataOutput.

    Swift

    // Obtain a CMSampleBuffer.
    
    // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
    // orientation `UIImage.Orientation.up`.
    let image = try MPImage(sampleBuffer: sampleBuffer)
        

    Objective-C

    // Obtain a `CMSampleBuffer`.
    
    // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
    // default orientation `UIImageOrientationUp`.
    MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
        

    Więcej informacji o CMSampleBuffer znajdziesz w dokumentacji CMSampleBuffer dla deweloperów Apple.

    Uruchamianie zadania

    Aby uruchomić rozpoznawanie gestów, użyj metody recognize() odpowiedniej do przypisanego trybu działania:

    • Statyczny obraz: recognize(image:)
    • Film: recognize(videoFrame:timestampInMilliseconds:)
    • Transmisja na żywo: recognizeAsync(image:timestampInMilliseconds:)

    Poniżej znajdziesz przykładowy kod pokazujący, jak uruchomić Rozpoznawanie gestów w różnych trybach działania:

    Swift

    Obraz

    let result = try gestureRecognizer.recognize(image: image)
        

    Wideo

    let result = try gestureRecognizer.recognize(
      videoFrame: image,
      timestampInMilliseconds: timestamp)
        

    Transmisja na żywo

    try gestureRecognizer.recognizeAsync(
      image: image,
      timestampInMilliseconds: timestamp)
        

    Objective-C

    Obraz

      MPPGestureRecognizerResult *result =
        [gestureRecognizer recognizeImage:mppImage
                                    error:nil];
        

    Wideo

    MPPGestureRecognizerResult *result =
      [gestureRecognizer recognizeVideoFrame:image
                     timestampInMilliseconds:timestamp
                                       error:nil];
        

    Transmisja na żywo

    BOOL success =
      [gestureRecognizer recognizeAsyncImage:image
                     timestampInMilliseconds:timestamp
                                       error:nil];
        

    Przykładowy kod umożliwia użytkownikowi przełączanie się między trybami przetwarzania, które mogą nie być wymagane w Twoim przypadku.

    Pamiętaj:

    • W trybie wideo lub w trybie transmisji na żywo musisz też podać w zadaniu Rozpoznawanie gestów sygnaturę czasową klatki wejściowej.

    • W trybie obrazu lub filmu zadanie rozpoznawania gestów blokuje bieżący wątek, dopóki nie przetworzy wejściowego obrazu lub klatki. Aby uniknąć blokowania bieżącego wątku, przeprowadź przetwarzanie w wątku tła za pomocą frameworków iOS Dispatch lub NSOperation.

    • W trybie transmisji na żywo zadanie wykrywania gestów zwraca wynik natychmiast i nie blokuje bieżącego wątku. Po przetworzeniu każdego klatki wejściowej wywołuje metodę gestureRecognizer(_:didFinishRecognition:timestampInMilliseconds:error:) z wynikiem rozpoznawania gestów. Moduł rozpoznawania gestów wywołuje tę metodę asynchronicznie w dedykowanej kolejce wysyłania szeregowej. Aby wyświetlać wyniki w interfejsie, po ich przetworzeniu prześlij wyniki do głównej kolejki. Jeśli funkcja recognizeAsync zostanie wywołana, gdy zadanie wykrywania gestów jest zajęte przetwarzaniem innego kadru, wykrywanie gestów zignoruje nowy element danych.

    Obsługa i wyświetlanie wyników

    Po przeprowadzeniu wnioskowania zadanie rozpoznawania gestów zwraca wartość GestureRecognizerResult, która zawiera punkty orientacyjne dłoni we współrzędnych zdjęcia, punkty orientacyjne dłoni we współrzędnych świata, ręka(lewa/prawa) oraz kategorie gestów rąk wykrytych dłoni.

    Poniżej znajdziesz przykład danych wyjściowych z tego zadania:

    Wynik GestureRecognizerResult zawiera 4 komponenty, z których każdy jest tablicą, a każdy element zawiera wykryty wynik dla jednej wykrytej ręki.

    • Ręka dominująca

      Ręka wskazuje, czy wykryte ręce są lewe czy prawa.

    • Gesty

      Kategorie rozpoznanych gestów wykrytych rąk.

    • Punkty orientacyjne

      Dostępnych jest 21 punktów orientacyjnych rozmieszczonych na dłoni, a każdy z nich składa się ze współrzędnych x, y i z. Współrzędne x i y są normalizowane do wartości [0,0, 1,0] odpowiednio szerokością i wysokością obrazu. Współrzędna z reprezentuje głębokość punktu orientacyjnego, przy czym punktem wyjścia jest głębokość na wysokości nadgarstka. Im mniejsza wartość, tym bliżej punktu orientacyjnego jest kamera. Wielkość z używa mniej więcej tej samej skali co x.

    • Punkty orientacyjne na świecie

      21 punktów orientacyjnych dłoni jest też przedstawionych w współrzędnych światowych. Każdy punkt orientacyjny składa się z wartości x, yz, które reprezentują rzeczywiste współrzędne 3D w metrach z początkiem w geometrycznym środku dłoni.

    GestureRecognizerResult:
      Handedness:
        Categories #0:
          index        : 0
          score        : 0.98396
          categoryName : Left
      Gestures:
        Categories #0:
          score        : 0.76893
          categoryName : Thumb_Up
      Landmarks:
        Landmark #0:
          x            : 0.638852
          y            : 0.671197
          z            : -3.41E-7
        Landmark #1:
          x            : 0.634599
          y            : 0.536441
          z            : -0.06984
        ... (21 landmarks for a hand)
      WorldLandmarks:
        Landmark #0:
          x            : 0.067485
          y            : 0.031084
          z            : 0.055223
        Landmark #1:
          x            : 0.063209
          y            : -0.00382
          z            : 0.020920
        ... (21 world landmarks for a hand)
    

    Te obrazy przedstawiają wizualizację danych wyjściowych zadania: