Przewodnik po rozpoznaniu gestów w systemie iOS

Zadanie rozpoznawania gestów MediaPipe umożliwia rozpoznawanie gestów dłoni w czasie rzeczywistym i wyświetla wyniki rozpoznawanych gestów oraz punktów orientacyjnych wykrytych dłoni. W tych instrukcjach pokazujemy, jak używać rozpoznawania gestów w aplikacjach na iOS.

Możesz zobaczyć, jak działa to zadanie, wyświetlając prezentację internetową. Więcej informacji na temat możliwości, modeli i opcji konfiguracji tego zadania znajdziesz w sekcji Omówienie.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to podstawowa implementacja aplikacji do rozpoznawania gestów na iOS. W tym przykładzie użyto aparatu w fizycznym urządzeniu z iOS, aby stale wykrywać gesty dłoni, a także do statycznego wykrywania gestów za pomocą obrazów i filmów z galerii urządzenia.

Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na iOS lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod modułu rozpoznawania gestów jest hostowany na GitHub.

Pobieranie kodu

Z instrukcji poniżej 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 tak, aby używała rozproszonego procesu płatności, aby mieć tylko pliki dla przykładowej aplikacji do 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 po konfiguracji na iOS.

Kluczowe elementy

Poniższe pliki zawierają kluczowy kod dla przykładowej aplikacji Rozpoznawanie gestów:

Konfiguracja

W tej sekcji opisujemy najważniejsze czynności, jakie należy wykonać, by skonfigurować środowisko programistyczne i projekty kodu tak, aby używały modułu rozpoznawania gestów. Ogólne informacje o konfigurowaniu środowiska programistycznego na potrzeby zadań MediaPipe, w tym o wymaganiach dotyczących wersji platformy, znajdziesz w przewodniku konfiguracji dla iOS.

Zależności

Moduł rozpoznawania gestów korzysta z biblioteki MediaPipeTasksVision, która musi być zainstalowana przy użyciu CocoaPods. Biblioteka jest zgodna z aplikacjami Swift i Objective-C i nie wymaga dodatkowej konfiguracji pod kątem określonego języka.

Instrukcje instalowania CocoaPods w systemie macOS znajdziesz w przewodniku instalacji CocoaPods. Instrukcje tworzenia Podfile z podami niezbędnymi do działania aplikacji znajdziesz w artykule Korzystanie z CocoaPods.

Dodaj pod MediaPipeTasksVision w narzędziu Podfile za pomocą tego kodu:

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

Jeśli aplikacja zawiera cele testu jednostkowego, dodatkowe informacje o konfigurowaniu Podfile znajdziesz w przewodniku konfiguracji na iOS.

Model

Zadanie rozpoznawania gestów MediaPipe wymaga wytrenowanego modelu zgodnego z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach na potrzeby rozpoznawania gestów znajdziesz w sekcji przeglądu zadań w sekcji „Modele”.

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

Aby określić ścieżkę do modelu w pakiecie aplikacji, użyj właściwości BaseOptions.modelAssetPath. Przykładowy kod znajdziesz w następnej sekcji.

Tworzenie zadania

Zadanie rozpoznawania gestów możesz utworzyć, wywołując jeden z jego inicjatorów. Inicjator GestureRecognizer(options:) akceptuje wartości opcji konfiguracji.

Jeśli nie potrzebujesz narzędzia do rozpoznawania gestów zainicjowanego z dostosowanymi opcjami konfiguracji, możesz użyć inicjatora GestureRecognizer(modelPath:), by utworzyć narzędzie do rozpoznawania 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 strumienie wideo na żywo. Domyślnie GestureRecognizer(modelPath:) inicjuje zadanie dotyczące nieruchomych obrazów. Jeśli chcesz, aby Twoje zadanie zostało zainicjowane w celu przetworzenia plików wideo lub strumieni wideo na żywo, użyj funkcji GestureRecognizer(options:), aby określić tryb działania filmu lub transmisji na żywo. Tryb transmisji na żywo wymaga też dodatkowej opcji konfiguracji gestureRecognizerLiveStreamDelegate, która umożliwia modułowi rozpoznawania gestów asynchronicznie dostarczanie wyników rozpoznawania gestów do przedstawicieli.

Wybierz kartę odpowiadającą Twojemu trybowi biegowemu, aby zobaczyć, jak utworzyć zadanie i uruchomić wnioskowanie.

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 ma te opcje konfiguracji w przypadku aplikacji na iOS:

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

IMAGE: tryb wprowadzania pojedynczych obrazów.

WIDEO: tryb dekodowanych klatek filmu.

TRANSMISJA NA ŻYWO: tryb transmisji danych wejściowych na żywo, np. z kamery. W tym trybie należy wywołać metodę resultListener, aby skonfigurować odbiornik, który będzie odbierał wyniki asynchronicznie. W tym trybie gestureRecognizerLiveStreamDelegate musi być ustawiony na instancję klasy, która implementuje GestureRecognizerLiveStreamDelegate, aby asynchronicznie otrzymywać wyniki rozpoznawania gestów.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_hands GestureRecognizer może wykryć maksymalną liczbę rąk. Any integer > 0 1
min_hand_detection_confidence Minimalny stopień pewności, że wykrywanie dłoni zostanie uznane za udane w modelu wykrywania dłoni. 0.0 - 1.0 0.5
min_hand_presence_confidence Minimalny wynik ufności wskaźnika obecności ręki w modelu wykrywania punktów orientacyjnych ręki. W trybie wideo i w trybie transmisji na żywo Modułu rozpoznawania gestów, jeśli wynik wiarygodności modelu ręki z modelu punktu orientacyjnego dłoni jest poniżej tego progu, uruchamia model wykrywania dłoni. W przeciwnym razie do określenia lokalizacji rąk używany jest uproszczony algorytm śledzenia punktów orientacyjnych. 0.0 - 1.0 0.5
min_tracking_confidence Minimalny wynik pewności, że śledzenie dłoni zostanie uznane za udane. Jest to próg interfejsu użytkownika w ramce ograniczającej między rękami w bieżącej a ostatniej klatce. W trybie wideo i trybie strumienia Modułu rozpoznawania gestów, jeśli śledzenie nie powiedzie się, rozpoznawanie gestów aktywuje wykrywanie dłoni. W przeciwnym razie wykrywanie rąk zostanie pominięte. 0.0 - 1.0 0.5
canned_gestures_classifier_options Opcje konfigurowania działania klasyfikatora gotowych gestów. Gotowe gesty to ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"]
  • Język wyświetlanych nazw: język, który ma być używany dla wyświetlanych nazw określonych za pomocą metadanych modelu TFLite (jeśli występują).
  • Maksymalna liczba wyników: maksymalna liczba najwyżej wyników do zwrócenia. Jeśli wartość jest mniejsza niż 0, zostaną zwrócone wszystkie dostępne wyniki.
  • Próg wyniku: wynik, poniżej którego wyniki są odrzucane. Jeśli ma wartość 0, zwracane są wszystkie dostępne wyniki.
  • Lista dozwolonych kategorii: lista dozwolonych nazw kategorii. Jeśli pole nie jest puste, wyniki klasyfikacji, których kategoria nie należy do tego zbioru, zostaną odfiltrowane. Wzajemnie wykluczają się z listą odrzuconych.
  • Lista odrzuconych kategorii: lista odrzuconych nazw kategorii. Jeśli pole nie jest puste, wyniki klasyfikacji, których kategoria należy do tego zbioru, zostaną odfiltrowane. Wzajemnie wykluczające się dzięki liście dozwolonych.
    • Język wyświetlanych 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świetlanych nazw: "en"
    • Maksymalna 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óry ma być używany dla wyświetlanych nazw określonych za pomocą metadanych modelu TFLite (jeśli występują).
  • Maksymalna liczba wyników: maksymalna liczba najwyżej wyników do zwrócenia. Jeśli wartość jest mniejsza niż 0, zostaną zwrócone wszystkie dostępne wyniki.
  • Próg wyniku: wynik, poniżej którego wyniki są odrzucane. Jeśli ma wartość 0, zwracane są wszystkie dostępne wyniki.
  • Lista dozwolonych kategorii: lista dozwolonych nazw kategorii. Jeśli pole nie jest puste, wyniki klasyfikacji, których kategoria nie należy do tego zbioru, zostaną odfiltrowane. Wzajemnie wykluczają się z listą odrzuconych.
  • Lista odrzuconych kategorii: lista odrzuconych nazw kategorii. Jeśli pole nie jest puste, wyniki klasyfikacji, których kategoria należy do tego zbioru, zostaną odfiltrowane. Wzajemnie wykluczające się dzięki liście dozwolonych.
    • Język wyświetlanych 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świetlanych nazw: "en"
    • Maksymalna liczba wyników: -1
    • Próg wyniku: 0
    • Lista dozwolonych kategorii: pusta
    • Lista odrzuconych kategorii: pusta
    result_listener Ustawia detektor wyników, aby asynchronicznie otrzymywać wyniki klasyfikacji, gdy moduł rozpoznawania gestów jest w trybie transmisji na żywo. Tego ustawienia można używać tylko wtedy, gdy tryb biegowy jest ustawiony na LIVE_STREAM ResultListener Nie dotyczy Nie dotyczy

    Gdy tryb biegowy jest ustawiony na transmisję na żywo, narzędzie do rozpoznawania gestów wymaga dodatkowej opcji konfiguracji gestureRecognizerLiveStreamDelegate, która umożliwia asynchronicznie dostarczanie wyników rozpoznawania gestów. Osoba, której przekazano dostęp, musi wdrożyć metodę gestureRecognizer(_:didFinishRecognition:timestampInMilliseconds:error:), którą narzędzie do 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 Włącza funkcję rozpoznawania gestów, która asynchronicznie odbiera wyniki 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 obrazu wejściowego lub ramki do obiektu MPImage musisz go przekonwertować do modułu rozpoznawania gestów. MPImage obsługuje różne typy formatów obrazów na iOS i może ich używać w każdym trybie działania, aby wnioskować. Więcej informacji na temat MPImage znajdziesz w interfejsie MPImage API

    Wybierz format obrazu na iOS zależnie od swojego przypadku użycia i trybu uruchamiania, którego wymaga Twoja aplikacja.MPImage akceptuje formaty obrazów UIImage, CVPixelBuffer i CMSampleBuffer (iOS).

    UIImage

    Format UIImage dobrze sprawdza się w tych trybach biegania:

    • Obrazy: obrazy z pakietu aplikacji, galerii użytkownika lub systemu plików sformatowane jako obrazy UIImage można przekonwertować na 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];
        

    W tym przykładzie inicjuje się 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 odbicia lustrzanego w orientacji takich jak .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

    Więcej informacji na temat UIImage znajdziesz w dokumentacji dla programistów Apple dotyczącej UIImage (w języku angielskim).

    CVPixelBuffer

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

    Format CVPixelBuffer dobrze sprawdza się w tych trybach biegania:

    • Obrazy: aplikacje generujące obrazy CVPixelBuffer po przetworzeniu przy użyciu platformy CoreImage systemu iOS mogą być wysyłane do modułu rozpoznawania gestów w trybie uruchamiania obrazów.

    • Filmy: klatki wideo można przekonwertować do formatu CVPixelBuffer, aby je przetworzyć, a potem wysłać do modułu rozpoznawania gestów w trybie wideo.

    • transmisja na żywo: aplikacje korzystające z kamery w iOS do generowania klatek można skonwertować do formatu CVPixelBuffer w celu przetworzenia, zanim trafią do modułu rozpoznawania 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 na temat CVPixelBuffer znajdziesz w dokumentacji dla programistów Apple CVPixelBuffer.

    CMSampleBuffer

    Format CMSampleBuffer przechowuje próbki multimediów jednolitego typu i dobrze sprawdza się w trybie transmisji na żywo. Klatki na żywo z kamer na iOS są przesyłane asynchronicznie w formacie CMSampleBuffer przez system iOS 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 na temat CMSampleBuffer znajdziesz w dokumentacji dla programistów Apple CMSampleBuffer.

    Uruchamianie zadania

    Aby uruchomić rozpoznawanie gestów, użyj metody recognize() odpowiedniej dla przypisanego trybu biegowego:

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

    Poniższe przykłady kodu pokazują podstawowe przykłady uruchamiania rozpoznawania gestów w różnych trybach biegania:

    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 pozwala użytkownikowi przełączać się między trybami przetwarzania, które mogą nie być wymagane w Twoim przypadku.

    Uwaga:

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

    • Gdy działa w trybie obrazu lub filmu, zadanie Rozpoznawanie gestów blokuje bieżący wątek do momentu zakończenia przetwarzania obrazu lub klatki wejściowej. Aby uniknąć zablokowania bieżącego wątku, wykonaj przetwarzanie w wątku w tle za pomocą platform Dispatch lub NSOperation w systemie iOS.

    • W trybie transmisji na żywo zadanie rozpoznawania gestów jest natychmiast zwracane i nie blokuje bieżącego wątku. Po przetworzeniu każdej ramki 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 szeregowej kolejce wysyłki. W przypadku wyświetlania wyników w interfejsie po ich przetworzeniu wyślij do głównej kolejki. Jeśli funkcja recognizeAsync zostanie wywołana, gdy zadanie Rozpoznawanie gestów jest zajęte przetwarzaniem innej ramki, moduł rozpoznawania gestów ignoruje nową ramkę wejściową.

    Obsługa i wyświetlanie wyników

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

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

    Wynikowy GestureRecognizerResult zawiera 4 komponenty, a każdy z nich jest tablicą, w której każdy element zawiera wykryty wynik pojedynczej wykrytej dłoni.

    • Ręka dominująca

      Ręka wskazuje, czy wykryte ręce są lewą czy prawą ręką.

    • Gesty

      Rozpoznawane kategorie gestów wykrytych dłoni.

    • Punkty orientacyjne

      Jest 21 punktów orientacyjnych wskazujących dłonie, 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 do szerokości i wysokości obrazu. Współrzędna z reprezentuje głębokość punktu orientacyjnego, przy czym głębokość na nadgarstku jest punktem początkowym. Im mniejsza wartość, tym zbliża się punkt orientacyjny do aparatu. Siła działania z jest mniej więcej zbliżona do skali x.

    • Punkty orientacyjne na świecie

      We współrzędnych świata są również przedstawione 21 punktów orientacyjnych. Każdy punkt orientacyjny składa się z elementów x, y i z, które reprezentują rzeczywiste współrzędne 3D w metrach z punktem początkowym w środku geometrycznym 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)
    

    Na tych obrazach pokazano wizualizację wyników zadania: