Objekte mit einem benutzerdefinierten Klassifizierungsmodell unter iOS erkennen, verfolgen und klassifizieren

Sie können ML Kit verwenden, um Objekte in aufeinanderfolgenden Videoframes zu erkennen und zu verfolgen.

Wenn Sie ein Bild an ML Kit übergeben, werden bis zu fünf Objekte im Bild erkannt sowie die Position jedes Objekts im Bild. Bei der Erkennung von Objekten Video-Streams hat jedes Objekt eine eindeutige ID, mit der Sie das Objekt von Frame zu Frame.

Sie können ein benutzerdefiniertes Bildklassifizierungsmodell verwenden, um Objekte zu klassifizieren, erkannt. Weitere Informationen finden Sie unter Benutzerdefinierte Modelle mit ML Kit für zu den Anforderungen an die Modellkompatibilität, wo Sie vortrainierte Modelle finden, und wie Sie eigene Modelle trainieren.

Es gibt zwei Möglichkeiten, ein benutzerdefiniertes Modell zu integrieren. Sie können das Modell nach in den Asset-Ordner Ihrer App verschieben oder dynamisch herunterladen, von Firebase. In der folgenden Tabelle werden die beiden Optionen verglichen.

Gebündeltes Modell Gehostetes Modell
Das Modell ist Teil der Datei .ipa Ihrer App, die um die Größe zu erhöhen. Das Modell ist nicht Teil der .ipa-Datei Ihrer App. Es ist gehostet durch Hochladen auf Firebase Machine Learning.
Das Modell ist sofort verfügbar, auch wenn das Android-Gerät offline ist Das Modell wird on demand heruntergeladen
Kein Firebase-Projekt erforderlich Firebase-Projekt erforderlich
Du musst deine App noch einmal veröffentlichen, um das Modell zu aktualisieren Modellaktualisierungen senden, ohne die App neu zu veröffentlichen
Keine integrierten A/B-Tests Einfache A/B-Tests mit Firebase Remote Config

Jetzt ausprobieren

Hinweis

  1. Fügen Sie die ML Kit-Bibliotheken in Ihre Podfile-Datei ein:

    So bündeln Sie ein Modell mit Ihrer App:

    pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
    

    Fügen Sie zum dynamischen Herunterladen eines Modells aus Firebase den LinkFirebase hinzu. Abhängigkeit:

    pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
    pod 'GoogleMLKit/LinkFirebase', '3.2.0'
    
  2. Öffnen Sie nach der Installation oder Aktualisierung der Pods Ihres Projekts das Xcode-Projekt. mit .xcworkspace. ML Kit wird in Xcode-Version 13.2.1 unterstützt oder höher.

  3. Wenn Sie ein Modell herunterladen möchten, müssen Sie Firebase zu Ihrem iOS-Projekt hinzufügen, falls noch nicht geschehen. Dies ist nicht erforderlich, wenn Sie modellieren.

1. Modell laden

Lokale Modellquelle konfigurieren

So bündeln Sie das Modell mit Ihrer App:

  1. Kopieren Sie die Modelldatei (in der Regel mit der Endung .tflite oder .lite) in Xcode. Projekt und wählen Sie dabei Copy bundle resources aus. Die Modelldatei ist im App Bundle enthalten und für ML Kit verfügbar.

  2. Erstellen Sie das Objekt LocalModel und geben Sie den Pfad zur Modelldatei an:

    Swift

    let localModel = LocalModel(path: localModelFilePath)

    Objective-C

    MLKLocalModel *localModel =
        [[MLKLocalModel alloc] initWithPath:localModelFilePath];

Von Firebase gehostete Modellquelle konfigurieren

Erstellen Sie ein CustomRemoteModel-Objekt, um das remote gehostete Modell zu verwenden. Geben Sie den Namen an, den Sie dem Modell bei der Veröffentlichung zugewiesen haben:

Swift

let firebaseModelSource = FirebaseModelSource(
    name: "your_remote_model") // The name you assigned in
                               // the Firebase console.
let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)

Objective-C

MLKFirebaseModelSource *firebaseModelSource =
    [[MLKFirebaseModelSource alloc]
        initWithName:@"your_remote_model"]; // The name you assigned in
                                            // the Firebase console.
MLKCustomRemoteModel *remoteModel =
    [[MLKCustomRemoteModel alloc]
        initWithRemoteModelSource:firebaseModelSource];

Starten Sie dann den Modelldownload und geben Sie die Bedingungen an, unter denen Sie Downloads zulassen möchten. Wenn das Modell nicht auf dem Gerät installiert ist oder ein neueres Modell Version des Modells verfügbar ist, lädt die Aufgabe asynchron das aus Firebase verwenden:

Swift

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

Objective-C

MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[MLKModelManager modelManager] downloadModel:remoteModel
                                       conditions:downloadConditions];

Viele Apps starten die Download-Aufgabe im Initialisierungscode, aber Sie können jederzeit tun, bevor Sie das Modell verwenden müssen.

2. Objektdetektor konfigurieren

Nachdem Sie die Modellquellen konfiguriert haben, konfigurieren Sie den Objektdetektor für Ihr Anwendungsfall mit einem CustomObjectDetectorOptions-Objekt. Sie können die folgenden Einstellungen:

Einstellungen für Objektdetektoren
Erkennungsmodus STREAM_MODE (Standard) | SINGLE_IMAGE_MODE

In STREAM_MODE (Standardeinstellung) wird der Objektdetektor ausgeführt mit niedriger Latenz, führt aber möglicherweise zu unvollständigen Ergebnissen (z. B. nicht spezifizierten Begrenzungsrahmen oder Kategorielabels) Aufrufe des Detektors. Außerdem gibt es in STREAM_MODE weist der Detektor Objekten Tracking-IDs zu, mit denen Sie um Objekte über Frames hinweg zu verfolgen. Verwenden Sie diesen Modus, wenn Sie oder wenn eine niedrige Latenz wichtig ist, z. B. bei der Verarbeitung Videostreams in Echtzeit.

In SINGLE_IMAGE_MODE gibt der Objektdetektor das Ergebnis nach der Festlegung des Markierungsrahmens des Objekts. Wenn Sie Aktivieren Sie auch die Klassifizierung. Es wird das Ergebnis nach der Begrenzung zurückgegeben. Feld und Kategorielabel sind verfügbar. Infolgedessen ist potenziell höher. Außerdem können Sie in SINGLE_IMAGE_MODE, Tracking-IDs sind nicht zugewiesen. Verwenden Sie wenn die Latenz nicht kritisch ist und Sie sich Teilergebnisse.

Mehrere Objekte erkennen und verfolgen false (Standard) | true

Erkennung und Verfolgung von bis zu fünf Objekten oder nur den auffälliges Objekt (Standardeinstellung).

Objekte klassifizieren false (Standard) | true

Gibt an, ob erkannte Objekte mithilfe der bereitgestellten ein benutzerdefiniertes Klassifikatormodell. So verwenden Sie Ihre benutzerdefinierte Klassifizierung: müssen Sie dies auf true festlegen.

Klassifizierungskonfidenzgrenzwert

Minimaler Konfidenzwert erkannter Labels. Wenn nicht festgelegt, alle Der in den Metadaten des Modells angegebene Klassifikator-Schwellenwert wird verwendet. Wenn das Modell keine Metadaten enthält oder die Metadaten keine für den Klassifikator einen Standardgrenzwert von 0, 0 verwendet.

Maximale Anzahl von Labels pro Objekt

Maximale Anzahl von Labels pro Objekt, die der Detektor verwenden soll zurückgeben. Wenn die Richtlinie nicht konfiguriert ist, wird der Standardwert 10 verwendet.

Wenn Sie nur ein lokal gebündeltes Modell haben, erstellen Sie einfach einen Objektdetektor aus Ihr LocalModel-Objekt:

Swift

let options = CustomObjectDetectorOptions(localModel: localModel)
options.detectorMode = .singleImage
options.shouldEnableClassification = true
options.shouldEnableMultipleObjects = true
options.classificationConfidenceThreshold = NSNumber(value: 0.5)
options.maxPerObjectLabelCount = 3

Objective-C

MLKCustomObjectDetectorOptions *options =
    [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableClassification = YES;
options.shouldEnableMultipleObjects = YES;
options.classificationConfidenceThreshold = @(0.5);
options.maxPerObjectLabelCount = 3;

Wenn Sie ein extern gehostetes Modell haben, müssen Sie prüfen, die Sie vor der Ausführung heruntergeladen haben. Sie können den Status des Modelldownloads mit der Methode isModelDownloaded(remoteModel:) des Modellmanagers.

Obwohl Sie dies nur vor der Ausführung des Objektdetektors bestätigen müssen, ein remote gehostetes und ein lokal gebündeltes Modell haben, sinnvoll, diese Prüfung bei der Instanziierung von ObjectDetector auszuführen: Detektor vom Remote-Modell, falls es heruntergeladen wurde, und vom lokalen Modell sonst.

Swift

var options: CustomObjectDetectorOptions!
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = CustomObjectDetectorOptions(remoteModel: remoteModel)
} else {
  options = CustomObjectDetectorOptions(localModel: localModel)
}
options.detectorMode = .singleImage
options.shouldEnableClassification = true
options.shouldEnableMultipleObjects = true
options.classificationConfidenceThreshold = NSNumber(value: 0.5)
options.maxPerObjectLabelCount = 3

Objective-C

MLKCustomObjectDetectorOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKCustomObjectDetectorOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
}
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableClassification = YES;
options.shouldEnableMultipleObjects = YES;
options.classificationConfidenceThreshold = @(0.5);
options.maxPerObjectLabelCount = 3;

Wenn Sie nur ein remote gehostetes Modell haben, sollten Sie die modellbezogenen wie z. B. das Ausgrauen oder Ausblenden eines Teils der Benutzeroberfläche, bis bestätigen Sie, dass das Modell heruntergeladen wurde.

Sie können den Downloadstatus des Modells abrufen, indem Sie Beobachter an die Standardeinstellung anhängen Benachrichtigungscenter. Achten Sie darauf, im Beobachter einen schwachen Verweis auf self zu verwenden -Block, da Downloads einige Zeit in Anspruch nehmen können und das ursprüngliche Objekt wird erst wieder freigegeben, wenn der Download abgeschlossen ist. Beispiel:

Swift

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidSucceed,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel,
        model.name == "your_remote_model"
        else { return }
    // The model was downloaded and is available on the device
}

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidFail,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel
        else { return }
    let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
    // ...
}

Objective-C

__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
            }];

Die Objekterkennungs- und -verfolgungs-API ist für diese beiden Hauptzwecke optimiert. Cases:

  • Live-Erkennung und Verfolgung des auffälligsten Objekts in der Kamera Sucher.
  • Erkennung mehrerer Objekte in einem statischen Bild.

So konfigurieren Sie die API für diese Anwendungsfälle:

Swift

// Live detection and tracking
let options = CustomObjectDetectorOptions(localModel: localModel)
options.shouldEnableClassification = true
options.maxPerObjectLabelCount = 3

// Multiple object detection in static images
let options = CustomObjectDetectorOptions(localModel: localModel)
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true
options.maxPerObjectLabelCount = 3

Objective-C

// Live detection and tracking
MLKCustomObjectDetectorOptions *options =
    [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
options.shouldEnableClassification = YES;
options.maxPerObjectLabelCount = 3;

// Multiple object detection in static images
MLKCustomObjectDetectorOptions *options =
    [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
options.maxPerObjectLabelCount = 3;

3. Eingabebild vorbereiten

Erstellen Sie ein VisionImage-Objekt mithilfe von UIImage oder einem CMSampleBuffer

Wenn du ein UIImage verwendest, gehe so vor:

  • Erstellen Sie ein VisionImage-Objekt mit der UIImage. Geben Sie die richtige .orientation an.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Wenn du ein CMSampleBuffer verwendest, gehe so vor:

  • Geben Sie die Ausrichtung der Bilddaten an, die in der CMSampleBuffer

    So ermitteln Sie die Bildausrichtung:

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • Erstellen Sie ein VisionImage-Objekt mithilfe der CMSampleBuffer-Objekt und Ausrichtung:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

4. Objektdetektor erstellen und ausführen

  1. Erstellen Sie einen neuen Objektdetektor:

    Swift

    let objectDetector = ObjectDetector.objectDetector(options: options)

    Objective-C

    MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
  2. Verwenden Sie dann den Detektor:

    Asynchron:

    Swift

    objectDetector.process(image) { objects, error in
        guard error == nil, let objects = objects, !objects.isEmpty else {
            // Handle the error.
            return
        }
        // Show results.
    }

    Objective-C

    [objectDetector
        processImage:image
          completion:^(NSArray *_Nullable objects,
                       NSError *_Nullable error) {
            if (objects.count == 0) {
                // Handle the error.
                return;
            }
            // Show results.
         }];

    Synchron:

    Swift

    var objects: [Object]
    do {
        objects = try objectDetector.results(in: image)
    } catch let error {
        // Handle the error.
        return
    }
    // Show results.

    Objective-C

    NSError *error;
    NSArray *objects =
        [objectDetector resultsInImage:image error:&error];
    // Show results or handle the error.

5. Informationen zu Objekten mit Label abrufen

Wenn der Aufruf an den Bildprozessor erfolgreich ist, wird entweder eine Liste mit Objects an den Abschluss-Handler oder gibt die Liste zurück, je nachdem, unabhängig davon, ob Sie die asynchrone oder die synchrone Methode aufgerufen haben.

Jedes Object enthält die folgenden Attribute:

frame Ein CGRect, der die Position des Objekts im Bild.
trackingID Ganzzahl, die das Objekt in Bildern identifiziert, oder "nil" in SINGLE_IMAGE_MODE
labels
label.text Die Textbeschreibung des Labels. Wird nur zurückgegeben, wenn die TensorFlow- Die Metadaten des Lite-Modells enthalten Labelbeschreibungen.
label.index Der Index des Labels unter allen Labels, die vom Klassifikator.
label.confidence Der Konfidenzwert der Objektklassifizierung.

Swift

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence), \(label.index)"
  }.joined(separator: "\n")
}

Objective-C

// The list of detected objects contains one item if multiple object detection
// wasn't enabled.
for (MLKObject *object in objects) {
  CGRect frame = object.frame;
  NSNumber *trackingID = object.trackingID;
  for (MLKObjectLabel *label in object.labels) {
    NSString *labelString =
        [NSString stringWithFormat:@"%@, %f, %lu",
                                   label.text,
                                   label.confidence,
                                   (unsigned long)label.index];
  }
}

Für eine hervorragende Nutzererfahrung sorgen

Beachten Sie für eine optimale Nutzererfahrung in Ihrer App die folgenden Richtlinien:

  • Die erfolgreiche Objekterkennung hängt von der visuellen Komplexität des Objekts ab. In müssen Objekte mit einer geringen Anzahl visueller Merkmale einen größeren Teil des Bildes einnehmen. Sie sollten Nutzenden dabei helfen, Eingabedaten erfassen, die mit der Art von Objekten, die Sie erkennen möchten, gut funktionieren.
  • Wenn Sie bei der Klassifizierung Objekte erkennen möchten, die nicht fallen in die unterstützten Kategorien einzuordnen, spezielle Behandlungen für unbekannte Objekte.

Sehen Sie sich auch die [ML Kit Material Design Showcase-App][showcase-link]{: .external } und die Material Design Sammlung Muster für Funktionen, die auf maschinellem Lernen basieren

Leistungsoptimierung

Wenn Sie die Objekterkennung in einer Echtzeitanwendung verwenden möchten, gehen Sie so vor: um optimale Framerates zu erzielen:

  • Wenn Sie den Streamingmodus in einer Echtzeitanwendung nutzen, sollten Sie nicht mehrere Objekterkennung zu erkennen, da die meisten Geräte keine angemessenen Framerates liefern können.

  • Verwende zum Verarbeiten von Videoframes die synchrone results(in:) API des Detektors. Anruf diese Methode aus dem AVCaptureVideoDataOutputSampleBufferDelegate <ph type="x-smartling-placeholder"></ph> captureOutput(_, didOutput:from:)-Funktion, um synchron Ergebnisse aus dem angegebenen Video abzurufen Frame. beibehalten von AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames als true, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer verfügbar wird, während der Detektor läuft, wird er verworfen.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken Eingabebild, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern Sie das Bild in einem Schritt übereinanderlegen. Dadurch rendern Sie auf der Anzeigeoberfläche pro verarbeitetem Eingabeframe nur einmal. Weitere Informationen finden Sie im Abschnitt updatePreviewOverlayViewWithLastFrame. im Beispiel der ML Kit-Kurzanleitung finden Sie ein Beispiel.