Handbuch zur Objekterkennung für iOS

Mit der Aufgabe „Objekterkennung“ können Sie das Vorhandensein und die Position mehrerer Objektklassen erkennen. Ein Objektdetektor kann beispielsweise Hunde in einem Bild finden. In dieser Anleitung erfahren Sie, wie Sie die Aufgabe „Objekterkennung“ unter iOS verwenden. Der in dieser Anleitung beschriebene Beispielcode ist auf GitHub verfügbar.

In dieser Webdemo 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 Objekterkennungs-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 sich an ihr orientieren, wenn Sie eine vorhandene App ändern. Der Beispielcode für den Objektdetektor wird auf GitHub gehostet.

Code herunterladen

In der folgenden Anleitung wird beschrieben, wie Sie mit dem Befehlszeilentool git 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. Optional können Sie Ihre Git-Instanz so konfigurieren, dass eine spärliche Überprüfung verwendet wird, sodass nur die Dateien für die Beispiel-App „Object Detector“ vorhanden sind:

    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 zur Objekterkennung:

  • ObjectDetectorService.swift: Initialisiert den Detektor, verarbeitet die Modellauswahl und führt eine Inferenz auf den 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 Ihrer Entwicklungsumgebung und zum Erstellen von Codeprojekten für die Verwendung des Objekterkennungstools beschrieben. Allgemeine Informationen zum Einrichten Ihrer Entwicklungsumgebung für die Verwendung von MediaPipe-Aufgaben, einschließlich 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-Apps 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 einer Podfile mit den erforderlichen Pods für Ihre App finden Sie unter CocoaPods verwenden.

Fügen Sie den Pod „MediaPipeTasksVision“ in der Datei Podfile mit dem folgenden Code hinzu:

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

Wenn Ihre App Unit-Testziele enthält, finden Sie im Einrichtungsleitfaden für iOS weitere Informationen zur Einrichtung Ihrer Podfile.

Modell

Für die MediaPipe-Objekterkennungsaufgabe ist ein trainiertes Modell erforderlich, das mit dieser Aufgabe kompatibel ist. Weitere Informationen zu den verfügbaren trainierten Modellen für den 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 mit Xcode Ihrem Projektverzeichnis hinzu. Eine Anleitung zum Hinzufügen von Dateien zu Ihrem Xcode-Projekt finden Sie unter Dateien und Ordner in Ihrem 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 „Object Detector“ erstellen, indem Sie einen ihrer Initialisierer aufrufen. Mit dem ObjectDetector(options:)-Initialisierer werden Werte für Konfigurationsoptionen festgelegt, darunter der Ausführungsmodus, die Sprache für Anzeigenamen, die maximale Anzahl von Ergebnissen, der Konfidenzgrenzwert sowie die Zulassungs- und Sperrlisten für Kategorien.

Wenn Sie keinen Object Detection-Detektor mit benutzerdefinierten Konfigurationsoptionen benötigen, können Sie mit der ObjectDetector(modelPath:)-Initialisierung einen Object Detection-Detektor mit den Standardoptionen erstellen. Weitere Informationen zu den Konfigurationsoptionen finden Sie unter 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 Ihre Aufgabe für die Verarbeitung von Videodateien oder Live-Videostreams initialisiert wird, geben Sie mit ObjectDetector(options:) den Ausführungsmodus für Video oder Livestream an. Für den Livestream-Modus ist außerdem die zusätzliche Konfigurationsoption objectDetectorLiveStreamDelegate erforderlich, mit der der Objektdetektor die Erkennungsergebnisse asynchron an den Delegaten senden kann.

Wählen Sie den Tab für den aktuellen 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

Für diese Aufgabe stehen die folgenden Konfigurationsoptionen für iOS-Apps zur Verfügung:

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

IMAGE: Der Modus für Eingaben mit einem einzelnen Bild.

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

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

Livestreamkonfiguration

Wenn der Ausführungsmodus auf „Livestream“ festgelegt ist, benötigt der Objektdetektor die zusätzliche Konfigurationsoption objectDetectorLiveStreamDelegate. Dadurch kann der Detektor Erkennungsergebnisse asynchron liefern. Der Delegate implementiert die Methode objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:), die der Objekterkennungsdienst aufruft, nachdem das Erkennungsergebnis für jeden Frame verarbeitet wurde.

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

Daten vorbereiten

Sie müssen das Eingabebild oder den Frame in ein MPImage-Objekt konvertieren, bevor Sie es an den Objekt-Detektor übergeben. MPImage unterstützt verschiedene Arten von iOS-Bildformaten und kann sie in jedem Betriebsmodus für die Inferenz verwenden. Weitere Informationen zu MPImage finden Sie in der MPImage API.

Wählen Sie ein iOS-Bildformat entsprechend Ihrem Anwendungsfall und dem erforderlichen Ausführungsmodus Ihrer Anwendung aus.MPImage unterstützt die iOS-Bildformate UIImage, CVPixelBuffer und CMSampleBuffer.

UIImage

Das UIImage-Format eignet sich gut für die folgenden Laufmodi:

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

  • Videos: Extrahieren Sie mit AVAssetImageGenerator Videoframes in das CGImage-Format und konvertieren Sie sie 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 eine MPImage mit der Standardausrichtung UIImage.Orientation.Up initialisiert. Sie können ein MPImage mit einem beliebigen der unterstützten Werte von UIImage.Orientation initialisieren. Der Objektdetektor unterstützt keine gespiegelten Ausrichtungen wie .upMirrored, .downMirrored, .leftMirrored oder .rightMirrored.

Weitere Informationen zu UIImage finden Sie in der Apple Developer-Dokumentation zu UIImage.

CVPixelBuffer

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

Das CVPixelBuffer-Format eignet sich gut für die folgenden Laufmodi:

  • Bilder: Apps, die nach einer Verarbeitung mit dem CoreImage-Framework von iOS CVPixelBuffer-Bilder generieren, können im Modus „Bild ausführen“ an den Objektdetektor gesendet werden.

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

  • Livestream: Frames, die von Apps mit einer iOS-Kamera generiert werden, können zur Verarbeitung in das CVPixelBuffer-Format konvertiert werden, bevor sie im Livestream-Modus an die Objekterkennung 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 von Apple.

CMSampleBuffer

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

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 findest du in der CMSampleBuffer-Entwicklerdokumentation von Apple.

Aufgabe 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 zeigen grundlegende Beispiele für die Ausführung von Object Detector in diesen verschiedenen Ausführungsmodi:

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

Im Codebeispiel für den Objektdetektor werden die Implementierungen der einzelnen Modi detect(image:), detect(videoFrame:) und detectAsync(image:) genauer erläutert. Der Beispielcode ermöglicht Nutzern, zwischen Verarbeitungsmodi zu wechseln, was für Ihren Anwendungsfall möglicherweise nicht erforderlich ist.

Wichtige Hinweise:

  • Wenn Sie die Funktion im Video- oder Livestream-Modus ausführen, müssen Sie der Objekterkennungsaufgabe auch den Zeitstempel des Eingabeframes angeben.

  • Wenn die Ausführung im Bild- oder Videomodus erfolgt, blockiert die Aufgabe „Object Detector“ den aktuellen Thread, bis die Verarbeitung des Eingabebilds oder ‑frames abgeschlossen ist. Um das Blockieren des aktuellen Threads zu vermeiden, führen Sie die Verarbeitung in einem Hintergrund-Thread mithilfe der iOS-Frameworks Dispatch oder NSOperation aus.

  • Wenn die Ausführung im Livestream-Modus erfolgt, gibt die Objekterkennungsaufgabe sofort ein Ergebnis zurück und blockiert den aktuellen Thread nicht. Nach der Verarbeitung jedes Eingabeframes wird die Methode objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:) mit dem Erkennungsergebnis aufgerufen. Die Objekterkennung ruft diese Methode asynchron in einer dedizierten seriellen Weiterleitungswarteschlange auf. Wenn Sie Ergebnisse in der Benutzeroberfläche anzeigen möchten, senden Sie sie nach der Verarbeitung an die Hauptwarteschlange. 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

Nach der Ausführung der Inferenz gibt die Aufgabe „Object Detector“ ein ObjectDetectorResult-Objekt zurück, das die im Eingabebild gefundenen Objekte beschreibt.

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

Das folgende Bild zeigt eine Visualisierung der Aufgabenausgabe:

Der Beispielcode für die Objekterkennung veranschaulicht, wie die von der Aufgabe zurückgegebenen Erkennungsergebnisse angezeigt werden. Weitere Informationen finden Sie im Codebeispiel.