Bildern mit einem von AutoML trainierten Modell unter iOS Labels hinzufügen

Nachdem Sie Ihr eigenes Modell mit AutoML Vision Edge trainiert haben, können Sie es in Ihrer App verwenden, um Bilder mit Labels zu versehen.

Es gibt zwei Möglichkeiten, mit AutoML Vision Edge trainierte Modelle einzubinden. Sie können das Modell bündeln, indem Sie die Dateien des Modells in Ihr Xcode-Projekt kopieren, oder Sie können sie dynamisch von Firebase herunterladen.

Optionen für Modellbündelung
In deiner App gebündelt
  • Das Modell ist Teil des Bundles
  • Das Modell ist sofort verfügbar, auch wenn das iOS-Gerät offline ist
  • Kein Firebase-Projekt erforderlich
Mit Firebase gehostet
  • Hosten Sie das Modell, indem Sie es in Firebase Machine Learning hochladen.
  • Verringert die Größe des App-Bundles
  • Das Modell wird bei Bedarf heruntergeladen
  • Modellaktualisierungen übertragen, ohne die App noch einmal zu veröffentlichen
  • Einfache A/B-Tests mit Firebase Remote Config
  • Erfordert ein Firebase-Projekt

Ausprobieren

  • Probieren Sie die Beispiel-App aus, um ein Beispiel für die Verwendung dieser API zu sehen.

Hinweis

1. Nehmen Sie die ML Kit-Bibliotheken in Ihre Podfile-Datei auf:

So bündeln Sie ein Modell mit Ihrer App:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    
Fügen Sie zum dynamischen Herunterladen eines Modells aus Firebase die Abhängigkeit LinkFirebase hinzu:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    pod 'GoogleMLKit/LinkFirebase'
    
2. Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie Ihr Xcode-Projekt mit seinem .xcworkspace-Code. ML Kit wird ab Xcode-Version 13.2.1 unterstützt. 3. Wenn Sie ein Modell herunterladen möchten, müssen Sie Firebase zu Ihrem iOS-Projekt hinzufügen, falls Sie das noch nicht getan haben. Dies ist beim Bündeln des Modells nicht erforderlich.

1. Modell laden

Lokale Modellquelle konfigurieren

So bündeln Sie das Modell mit Ihrer Anwendung:

1. Extrahieren Sie das Modell und seine Metadaten aus dem ZIP-Archiv, das Sie aus der Firebase Console heruntergeladen haben, in einen Ordner:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
Alle drei Dateien müssen sich im selben Ordner befinden. Wir empfehlen Ihnen, die Dateien so zu verwenden, wie Sie sie heruntergeladen haben, ohne Änderungen (einschließlich der Dateinamen).

2. Kopieren Sie den Ordner in Ihr Xcode-Projekt und wählen Sie dabei Ordnerreferenzen erstellen aus. Die Modelldatei und die Metadaten sind im App Bundle enthalten und für ML Kit verfügbar.

3. Erstellen Sie ein AutoMLImageLabelerLocalModel-Objekt und geben Sie den Pfad zur Manifestdatei des Modells an:

Swift

guard let manifestPath = Bundle.main.path(
    forResource: "manifest",
    ofType: "json",
    inDirectory: "your_model_directory"
) else { return }
let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)

Objective-C

NSString *manifestPath =
    [NSBundle.mainBundle pathForResource:@"manifest"
                                  ofType:@"json"
                             inDirectory:@"your_model_directory"];
MLKAutoMLImageLabelerLocalModel *localModel =
    [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];

Eine von Firebase gehostete Modellquelle konfigurieren

Wenn Sie das extern gehostete Modell verwenden möchten, erstellen Sie ein AutoMLImageLabelerRemoteModel-Objekt und geben Sie den Namen an, den Sie dem Modell bei der Veröffentlichung zugewiesen haben:

Swift

let remoteModel = AutoMLImageLabelerRemoteModel(
    name: "your_remote_model"  // The name you assigned in
                               // the Firebase console.
)

Objective-C

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

Starten Sie dann die Aufgabe zum Herunterladen des Modells und geben Sie die Bedingungen an, unter denen Sie das Herunterladen zulassen möchten. Wenn sich das Modell nicht auf dem Gerät befindet oder eine neuere Version des Modells verfügbar ist, wird es von der Aufgabe asynchron von Firebase heruntergeladen:

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 Anwendungen starten die Downloadaufgabe im Initialisierungscode, aber Sie können dies jederzeit tun, bevor Sie das Modell verwenden müssen.

Bildlabelersteller aus dem Modell erstellen

Nachdem Sie die Modellquellen konfiguriert haben, erstellen Sie ein ImageLabeler-Objekt aus einer dieser Quellen.

Wenn Sie nur ein lokal gebündeltes Modell haben, erstellen Sie einfach einen Labelersteller aus Ihrem AutoMLImageLabelerLocalModel-Objekt und konfigurieren Sie den erforderlichen Konfidenzgrenzwert (siehe Modus bewerten:

Swift

let options = AutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKAutoMLImageLabelerOptions *options =
    [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

Wenn Sie ein extern gehostetes Modell haben, müssen Sie prüfen, ob es heruntergeladen wurde, bevor Sie es ausführen. Sie können den Status der Modelldownloadaufgabe mithilfe der Methode isModelDownloaded(remoteModel:) des Modellmanagers prüfen.

Sie müssen dies nur vor dem Ausführen des Labelerstellers prüfen. Wenn Sie sowohl ein extern gehostetes Modell als auch ein lokal gebündeltes Modell haben, kann es jedoch sinnvoll sein, diese Prüfung beim Instanziieren von ImageLabeler durchzuführen: Erstellen Sie einen Labelersteller aus dem Remote-Modell, wenn es heruntergeladen wurde, und andernfalls aus dem lokalen Modell.

Swift

var options: AutoMLImageLabelerOptions!
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = AutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = AutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKAutoMLImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

Wenn Sie nur ein extern gehostetes Modell haben, sollten Sie modellbezogene Funktionen deaktivieren und z. B. einen Teil Ihrer UI ausblenden oder ausblenden, bis Sie bestätigt haben, dass das Modell heruntergeladen wurde.

Sie können den Downloadstatus des Modells abrufen, indem Sie Beobachter an das standardmäßige Benachrichtigungscenter anhängen. Verwenden Sie im Beobachterblock einen schwachen Verweis auf self, da Downloads einige Zeit dauern können und das ursprüngliche Objekt bis zum Abschluss des Downloads freigegeben werden kann. 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];
            }];

2. Eingabebild vorbereiten

Erstellen Sie mit UIImage oder CMSampleBuffer ein VisionImage-Objekt.

Wenn du UIImage verwendest, gehe so vor:

  • Erstellen Sie mit der UIImage ein VisionImage-Objekt. Achte darauf, den richtigen .orientation anzugeben.

    Swift

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

    Objective-C

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

Wenn du CMSampleBuffer verwendest, gehe so vor:

  • Geben Sie die Ausrichtung der Bilddaten an, die in CMSampleBuffer enthalten sind.

    So rufen Sie die Bildausrichtung ab:

    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;
      }
    }
          
  • Erstelle mit dem Objekt CMSampleBuffer und der Ausrichtung ein VisionImage-Objekt:

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

3. Labelersteller für Bilder ausführen

Asynchron:

Swift

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

Objective-C

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

Synchron:

Swift

var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.

Objective-C

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

4. Informationen zu mit Labels versehenen Objekten abrufen

Wenn der Vorgang zum Beschriften von Bildern erfolgreich ist, wird ein Array von ImageLabel zurückgegeben. Jedes ImageLabel stellt etwas dar, das im Bild mit einem Label versehen wurde. Sie können die Textbeschreibung jedes Labels (falls in den Metadaten der TensorFlow Lite-Modelldatei verfügbar), den Konfidenzwert und den Index abrufen. Beispiel:

Swift

for label in labels {
  let labelText = label.text
  let confidence = label.confidence
  let index = label.index
}

Objective-C

for (MLKImageLabel *label in labels) {
  NSString *labelText = label.text;
  float confidence = label.confidence;
  NSInteger index = label.index;
}

Tipps zur Verbesserung der Echtzeitleistung

Wenn du Bilder in einer Echtzeitanwendung mit Labels versehen möchtest, beachte die folgenden Richtlinien, um die besten Framerates zu erzielen:

  • Verwenden Sie zum Verarbeiten von Videoframes die synchrone results(in:) API des Detektors. Rufen Sie diese Methode über die captureOutput(_, didOutput:from:)-Funktion von AVCaptureVideoDataOutputSampleBufferDelegate auf, um synchron Ergebnisse aus dem angegebenen Videoframe abzurufen. Behalten Sie die alwaysDiscardsLateVideoFrames von AVCaptureVideoDataOutput als true bei, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer Videoframe verfügbar wird, während der Detektor ausgeführt wird, wird er gelöscht.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken über das Eingabebild einzublenden, rufen Sie zuerst das Ergebnis aus dem ML Kit ab und rendern Sie dann das Bild und das Overlay in einem einzigen Schritt. Dadurch wird für jeden verarbeiteten Eingabeframe nur einmal ein Rendering auf der Anzeigeoberfläche ausgeführt. Ein entsprechendes Beispiel finden Sie im ML Kit-Schnellstartbeispiel unter updatePreviewOverlayViewWithLastFrame.