Handbuch zur Objekterkennung für iOS

Mit der Aufgabe „Objekterkennung“ können Sie das Vorhandensein und den Standort mehrerer Klassen von Objekten erkennen. Ein Objektdetektor kann beispielsweise Hunde in einem Bild finden. In dieser Anleitung erfahren Sie, wie Sie die Aufgabe „Objektdetektor“ in iOS verwenden. Das in dieser Anleitung beschriebene Codebeispiel ist auf GitHub verfügbar.

In dieser Web-Demo können Sie sich diese Aufgabe in Aktion ansehen. Weitere Informationen zu den Funktionen, Modellen und Konfigurationsoptionen dieser Aufgabe finden Sie in der Übersicht.

Codebeispiel

Der Beispielcode für MediaPipe Tasks ist eine grundlegende Implementierung einer Objektdetektor-App für iOS. In diesem Beispiel wird die Kamera eines physischen iOS-Geräts verwendet, um kontinuierlich Objekte zu erkennen. Es können auch Bilder und Videos aus der Gerätegalerie verwendet werden, um Objekte statisch zu erkennen.

Sie können die App als Ausgangspunkt für Ihre eigene iOS-App verwenden oder darauf zurückgreifen, wenn Sie eine vorhandene App ändern. Der Beispielcode der Objekterkennung wird auf GitHub gehostet.

Code herunterladen

In der folgenden Anleitung erfahren Sie, wie Sie mit dem git-Befehlszeilentool eine lokale Kopie des Beispielcodes erstellen.

So laden Sie den Beispielcode herunter:

  1. Klonen Sie das Git-Repository mit dem folgenden Befehl:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Konfigurieren Sie optional Ihre Git-Instanz für die Verwendung von Sparse Checkout, sodass Sie nur die Dateien für die Beispielanwendung „Objekterkennung“ haben:

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

Nachdem Sie eine lokale Version des Beispielcodes erstellt haben, können Sie die MediaPipe-Aufgabenbibliothek installieren, das Projekt mit Xcode öffnen und die App ausführen. Eine Anleitung finden Sie im Einrichtungsleitfaden für iOS.

Schlüsselkomponenten

Die folgenden Dateien enthalten den wichtigen Code für die Beispielanwendung „Objekterkennung“:

  • ObjectDetectorService.swift: Initialisiert den Detektor, übernimmt die Modellauswahl und führt eine Inferenz für die Eingabedaten aus.
  • CameraViewController.swift: Implementiert die Benutzeroberfläche für den Eingabemodus des Live-Kamerafeeds und visualisiert die Erkennungsergebnisse.
  • MediaLibraryViewController.swift: Implementiert die Benutzeroberfläche für den Eingabemodus für Standbilder und Videodateien und visualisiert die Erkennungsergebnisse.

Einrichtung

In diesem Abschnitt werden die wichtigsten Schritte zum Einrichten der Entwicklungsumgebung und Codeprojekte für die Verwendung von Object Detector beschrieben. Allgemeine Informationen zum Einrichten der Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich der Anforderungen an die Plattformversion, finden Sie im Einrichtungsleitfaden für iOS.

Abhängigkeiten

Der Objektdetektor verwendet die MediaPipeTasksVision-Bibliothek, die mit CocoaPods installiert werden muss. Die Bibliothek ist sowohl mit Swift- als auch mit Objective-C-Anwendungen kompatibel und erfordert keine zusätzliche sprachspezifische Einrichtung.

Eine Anleitung zur Installation von CocoaPods unter macOS finden Sie in der CocoaPods-Installationsanleitung. Eine Anleitung zum Erstellen eines Podfile mit den erforderlichen Pods für Ihre Anwendung finden Sie unter CocoaPods verwenden.

Fügen Sie den MediaPipeTasksVision-Pod mit dem folgenden Code in Podfile ein:

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

Falls Ihre App Ziele für Einheitentests enthält, finden Sie im Einrichtungsleitfaden für iOS weitere Informationen zum Einrichten von Podfile.

Modell

Für die Aufgabe des MediaPipe-Objektdetektors ist ein trainiertes Modell erforderlich, das mit dieser Aufgabe kompatibel ist. Weitere Informationen zu den verfügbaren trainierten Modellen für Objektdetektor finden Sie in der Aufgabenübersicht im Abschnitt „Modelle“.

Wählen Sie ein Modell aus, laden Sie es herunter und fügen Sie es Ihrem Projektverzeichnis mithilfe von Xcode hinzu. Eine Anleitung zum Hinzufügen von Dateien zu Ihrem Xcode-Projekt finden Sie unter Dateien und Ordner in einem Xcode-Projekt verwalten.

Verwenden Sie das Attribut BaseOptions.modelAssetPath, um den Pfad zum Modell in Ihrem App Bundle anzugeben. Ein Codebeispiel finden Sie im nächsten Abschnitt.

Aufgabe erstellen

Sie können die Aufgabe „Objektdetektor“ erstellen, indem Sie einen ihrer Initialisierer aufrufen. Der ObjectDetector(options:)-Initialisierer legt Werte für Konfigurationsoptionen fest, darunter den Ausführungsmodus, die Sprache für Anzeigenamen, die maximale Anzahl von Ergebnissen, den Konfidenzgrenzwert, die Zulassungsliste und die Sperrliste für Kategorien.

Wenn Sie keinen Objektdetektor benötigen, der mit benutzerdefinierten Konfigurationsoptionen initialisiert wurde, können Sie mit dem ObjectDetector(modelPath:)-Initialisierer einen Objektdetektor mit den Standardoptionen erstellen. Weitere Informationen zu Konfigurationsoptionen finden Sie in der Konfigurationsübersicht.

Die Aufgabe „Objekterkennung“ unterstützt drei Eingabedatentypen: Standbilder, Videodateien und Live-Videostreams. Standardmäßig initialisiert ObjectDetector(modelPath:) eine Aufgabe für Standbilder. Wenn Sie möchten, dass die Aufgabe zur Verarbeitung von Videodateien oder Live-Videostreams initialisiert wird, geben Sie den Video- oder Livestream-Ausführungsmodus mit ObjectDetector(options:) an. Für den Livestream-Modus ist außerdem die zusätzliche Konfigurationsoption objectDetectorLiveStreamDelegate erforderlich, mit der der Objektdetektor Erkennungsergebnisse asynchron an den Bevollmächtigten senden kann.

Wählen Sie den Tab für Ihren Ausführungsmodus aus, um zu erfahren, wie Sie die Aufgabe erstellen und die Inferenz ausführen.

Swift

Bild

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ObjectDetectorOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.maxResults = 5

let objectDetector = try ObjectDetector(options: options)
    

Video

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ObjectDetectorOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.maxResults = 5

let objectDetector = try ObjectDetector(options: options)
    

Livestream

import MediaPipeTasksVision

// Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and
// implements the method that the object detector calls once it
// finishes performing detection on each input frame.
class ObjectDetectorResultProcessor: NSObject, ObjectDetectorLiveStreamDelegate {

  func objectDetector(
    _ objectDetector: ObjectDetector,
    didFinishDetection objectDetectionResult: ObjectDetectorResult?,
    timestampInMilliseconds: Int,
    error: Error?) {
    // Process the detection result or errors here.
  }
}

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ObjectDetectorOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.maxResults = 5

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

let objectDetector = try ObjectDetector(options: options)
    

Objective-C

Bild

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPObjectDetectorOptions *options = [[MPPObjectDetectorOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.maxResults = 5;

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

Video

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPObjectDetectorOptions *options = [[MPPObjectDetectorOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.maxResults = 5;

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

Livestream

@import MediaPipeTasksVision;

// Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and
// implements the method that the object detector calls once it
// finishes performing detection on each input frame.

@interface APPObjectDetectorResultProcessor : NSObject 

@end

@implementation MPPObjectDetectorResultProcessor

-   (void)objectDetector:(MPPObjectDetector *)objectDetector
    didFinishDetectionWithResult:(MPPObjectDetectorResult *)ObjectDetectorResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the detection result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPObjectDetectorOptions *options = [[MPPObjectDetectorOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.maxResults = 5;

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

Konfigurationsoptionen

Diese Aufgabe bietet die folgenden Konfigurationsoptionen für iOS-Apps:

Option Beschreibung Wertebereich Standardwert
runningMode Legt den Ausführungsmodus für die Task fest. Es gibt drei Modi:

IMAGE: Der Modus für Einzelbildeingaben.

VIDEO: Der Modus für decodierte Frames eines Videos.

LIVE_STREAM: Der Modus für einen Livestream der Eingabedaten, z. B. von einer Kamera. In diesem Modus muss resultListener aufgerufen werden, um einen Listener einzurichten, der die Ergebnisse asynchron empfängt.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
displayNamesLocales Legt die Sprache von Labels fest, die für Anzeigenamen bereitgestellt werden, die in den Metadaten des Aufgabenmodells angegeben sind, sofern verfügbar. Der Standardwert für Englisch ist en. Mit der TensorFlow Lite Metadata Writer API können Sie den Metadaten eines benutzerdefinierten Modells lokalisierte Labels hinzufügen. Sprachcode en
maxResults Legt die optionale maximale Anzahl der Ergebnisse mit den besten Bewertungen fest, die zurückgegeben werden sollen. Beliebige positive Zahlen -1 (alle Ergebnisse werden zurückgegeben)
scoreThreshold Legt den Schwellenwert für den Vorhersagewert fest, der den in den Modellmetadaten angegebenen Grenzwert überschreibt (falls vorhanden). Ergebnisse unter diesem Wert werden abgelehnt. Beliebige Gleitkommazahl Nicht festgelegt
categoryAllowlist Legt die optionale Liste der zulässigen Kategorienamen fest. Wenn das Feld nicht leer ist, werden Erkennungsergebnisse herausgefiltert, deren Kategoriename nicht in diesem Satz enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option und categoryDenylist schließen sich gegenseitig aus und die Verwendung beider Werte führt zu einem Fehler. Beliebige Strings Nicht festgelegt
categoryDenylist Legt die optionale Liste der nicht zulässigen Kategorienamen fest. Wenn das Feld nicht leer ist, werden Erkennungsergebnisse herausgefiltert, deren Kategoriename in diesem Satz enthalten ist. Doppelte oder unbekannte Kategorienamen werden ignoriert. Diese Option und categoryAllowlist schließen sich gegenseitig aus und die Verwendung beider Optionen führt zu einem Fehler. Beliebige Strings Nicht festgelegt

Livestream-Konfiguration

Wenn der Ausführungsmodus auf Livestream festgelegt ist, benötigt der Objektdetektor die zusätzliche Konfigurationsoption objectDetectorLiveStreamDelegate, mit der der Detektor Erkennungsergebnisse asynchron liefern kann. Der Delegate implementiert die Methode objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:), die der Objektdetektor nach der Verarbeitung des Erkennungsergebnisses für jeden Frame aufruft.

Optionsname Beschreibung Wertebereich Standardwert
objectDetectorLiveStreamDelegate Ermöglicht dem Objektdetektor, Erkennungsergebnisse im Livestream-Modus asynchron zu empfangen. Die Klasse, deren Instanz auf dieses Attribut festgelegt ist, muss die Methode objectDetector(_:didFinishDetection:timestampInMilliseconds:error:) implementieren. Nicht zutreffend Nicht festgelegt

Daten vorbereiten

Sie müssen das Eingabebild oder den Eingabeframe in ein MPImage-Objekt konvertieren, bevor Sie es an den Objektdetektor übergeben. MPImage unterstützt verschiedene Arten von iOS-Bildformaten und kann in jedem Ausführungsmodus für die Inferenz verwendet werden. Weitere Informationen zu MPImage finden Sie in der MPImage API.

Wählen Sie ein iOS-Bildformat basierend auf Ihrem Anwendungsfall und dem Ausführungsmodus Ihrer Anwendung aus.MPImage akzeptiert die iOS-Bildformate UIImage, CVPixelBuffer und CMSampleBuffer.

UIImage

Das Format UIImage eignet sich gut für die folgenden Ausführungsmodi:

  • Bilder: Bilder aus einem App Bundle, einer Nutzergalerie oder einem Dateisystem, die als UIImage-Bilder formatiert sind, können in ein MPImage-Objekt konvertiert werden.

  • Videos: Extrahieren Sie Videoframes mit AVAssetImageGenerator in das CGImage und konvertieren Sie sie dann in UIImage-Bilder.

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];
    

Im Beispiel wird ein MPImage mit der Standardausrichtung UIImage.Orientation.Up initialisiert. Sie können ein MPImage mit jedem der unterstützten UIImage.Orientation-Werte initialisieren. Objekterkennung unterstützt keine gespiegelten Ausrichtungen wie .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

Weitere Informationen zu UIImage finden Sie in der Apple-Entwicklerdokumentation UIImage.

CVPixelBuffer

Das Format CVPixelBuffer eignet sich gut für Anwendungen, die Frames generieren und das iOS CoreImage-Framework für die Verarbeitung verwenden.

Das Format CVPixelBuffer eignet sich gut für die folgenden Ausführungsmodi:

  • Bilder: Apps, die nach einiger Verarbeitung mit dem CoreImage-Framework von iOS CVPixelBuffer-Bilder generieren, können im Bildausführungsmodus an den Objektdetektor gesendet werden.

  • Videos: Videoframes können zur Verarbeitung in das Format CVPixelBuffer konvertiert und dann im Videomodus an den Objektdetektor gesendet werden.

  • Livestream: Apps, bei denen Frames mit einer iOS-Kamera generiert werden, können zur Verarbeitung in das CVPixelBuffer-Format konvertiert werden, bevor sie im Livestream-Modus an den Objektdetektor gesendet werden.

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];
    

Weitere Informationen zu CVPixelBuffer findest du in der CVPixelBuffer-Entwicklerdokumentation.

CMSampleBuffer

Im Format CMSampleBuffer werden Medienbeispiele eines einheitlichen Medientyps gespeichert. Es eignet sich gut für den Livestream-Ausführungsmodus. Live-Frames von iOS-Kameras werden von iOS AVCaptureVideoDataOutput asynchron im CMSampleBuffer-Format übertragen.

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];
    

Weitere Informationen zu CMSampleBuffer finden Sie in der Entwicklerdokumentation zu CMSampleBuffer von Apple.

Task ausführen

Verwenden Sie zum Ausführen des Objektdetektors die Methode detect(), die für den zugewiesenen Ausführungsmodus spezifisch ist:

  • Standbild: detect(image:)
  • Video: detect(videoFrame:timestampInMilliseconds:)
  • Livestream: detectAsync(image:)

Die folgenden Codebeispiele enthalten grundlegende Beispiele dafür, wie der Objektdetektor in den verschiedenen Ausführungsmodi ausgeführt wird:

Swift

Bild

let objectDetector.detect(image:image)
    

Video

let objectDetector.detect(videoFrame:image)
    

Livestream

let objectDetector.detectAsync(image:image)
    

Objective-C

Bild

MPPObjectDetectorResult *result = [objectDetector detectInImage:image error:nil];
    

Video

MPPObjectDetectorResult *result = [objectDetector detectInVideoFrame:image          timestampInMilliseconds:timestamp error:nil];
    

Livestream

BOOL success = [objectDetector detectAsyncInImage:image
                          timestampInMilliseconds:timestamp
                                            error:nil];
    

Das Codebeispiel für Objektdetektoren zeigt die Implementierungen der einzelnen Modi genauer: detect(image:), detect(videoFrame:) und detectAsync(image:). Mit dem Beispielcode kann der Nutzer zwischen den Verarbeitungsmodi wechseln, die für Ihren Anwendungsfall möglicherweise nicht erforderlich sind.

Wichtige Hinweise:

  • Bei Ausführung im Video- oder Livestream-Modus müssen Sie auch den Zeitstempel des Eingabe-Frames an die Objekterkennungsaufgabe übergeben.

  • Im Bild- oder Videomodus blockiert die Aufgabe „Objekterkennung“ den aktuellen Thread, bis die Verarbeitung des Eingabebilds oder ‐frames abgeschlossen ist. Damit der aktuelle Thread nicht blockiert wird, führen Sie die Verarbeitung mithilfe von iOS Dispatch- oder NSOperation-Frameworks in einem Hintergrundthread aus.

  • Im Livestream-Modus wird die Aufgabe der Objekterkennung sofort zurückgegeben und der aktuelle Thread nicht blockiert. Nach der Verarbeitung jedes Eingabeframes wird die Methode objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:) mit dem Erkennungsergebnis aufgerufen. Der Objektdetektor ruft diese Methode in einer dedizierten seriellen Weiterleitungswarteschlange asynchron auf. Leiten Sie die Ergebnisse nach der Verarbeitung an die Hauptwarteschlange zur Anzeige der Ergebnisse auf der Benutzeroberfläche weiter. Wenn die Funktion detectAsync aufgerufen wird, während die Objekterkennungsaufgabe mit der Verarbeitung eines anderen Frames beschäftigt ist, ignoriert der Objektdetektor den neuen Eingabeframe.

Ergebnisse verarbeiten und anzeigen

Beim Ausführen der Inferenz gibt die Objektdetektor-Aufgabe ein ObjectDetectorResult-Objekt zurück, das die Objekte beschreibt, die im Eingabebild gefunden wurden.

Im Folgenden sehen Sie ein Beispiel für die Ausgabedaten dieser Aufgabe:

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

Die folgende Abbildung zeigt eine Visualisierung der Aufgabenausgabe:

Der Beispielcode des Objektdetektors zeigt, wie die von der Aufgabe zurückgegebenen Erkennungsergebnisse angezeigt werden. Weitere Informationen finden Sie im Codebeispiel.