Bilder mit einem von AutoML trainierten Modell auf iOS mit Labels versehen
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, Modelle einzubinden, die mit AutoML Vision Edge trainiert wurden. Sie können das Modell bündeln, indem Sie die Dateien des Modells in Ihr Xcode-Projekt kopieren, oder Sie können es dynamisch von Firebase herunterladen.
| Optionen für das Bündeln von Modellen | |
|---|---|
| In Ihrer App gebündelt |
|
| Mit Firebase gehostet |
|
Jetzt ausprobieren
- Probieren Sie die Beispiel-App aus, um ein Anwendungsbeispiel für diese API zu sehen.
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/ImageLabelingAutoML'
LinkFirebase
Abhängigkeit hinzu:
pod 'GoogleMLKit/ImageLabelingAutoML'
pod 'GoogleMLKit/LinkFirebase'
.xcworkspacecode>. ML Kit wird in Xcode
Version 13.2.1 oder höher unterstützt.
3. Wenn Sie ein Modell herunterladen möchten, stellen Sie sicher, dass Sie
Firebase zu Ihrem iOS-Projekt hinzufügen,
falls Sie das noch nicht getan haben. Das ist nicht erforderlich, wenn Sie das
Modell bündeln.
1. Modell laden
Lokale Modellquelle konfigurieren
So bündeln Sie das Modell mit Ihrer App:1. Extrahieren Sie das Modell und seine Metadaten aus dem ZIP-Archiv, das Sie in der Firebase Console heruntergeladen haben in einen Ordner:
your_model_directory
|____dict.txt
|____manifest.json
|____model.tflite
2. Kopieren Sie den Ordner in Ihr Xcode-Projekt und wählen Sie dabei Ordnerreferenzen erstellen aus. Die Modelldatei und die Metadaten werden in das App-Bundle aufgenommen und sind für ML Kit verfügbar.
3. Erstellen Sie das Objekt
AutoMLImageLabelerLocalModel 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];
In Firebase gehostete Modellquelle konfigurieren
Wenn Sie das Remote-Modell verwenden möchten, erstellen Sie ein AutoMLImageLabelerRemoteModel-Objekt und geben Sie den Namen an, den Sie dem Modell beim Veröffentlichen 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 den Download des Modells und geben Sie die Bedingungen an, unter denen der Download zulässig sein soll. Wenn sich das Modell nicht auf dem Gerät befindet oder eine neuere Version des Modells verfügbar ist, wird das Modell 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 Apps starten den Download im Initialisierungscode, Sie können das aber auch jederzeit tun, bevor Sie das Modell verwenden müssen.
Bild-Labeler aus Ihrem Modell erstellen
Nachdem Sie Ihre Modellquellen konfiguriert haben, erstellen Sie ein ImageLabeler-Objekt aus einer der Quellen.
Wenn Sie nur ein lokal gebündeltes Modell haben, erstellen Sie einfach einen Labeler aus Ihrem
AutoMLImageLabelerLocalModel Objekt und konfigurieren Sie den Konfidenzwert
Schwellenwert, der erforderlich sein soll (siehe Modell 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 Remote-Modell haben, müssen Sie prüfen, ob es heruntergeladen wurde, bevor Sie es ausführen. Sie können den Status des Downloads des Modells mit der Methode isModelDownloaded(remoteModel:) des Modellmanagers prüfen.
Sie müssen das nur bestätigen, bevor Sie den Labeler ausführen. Wenn Sie sowohl ein Remote-Modell als auch ein lokal gebündeltes Modell haben, kann es sinnvoll sein, diese Prüfung beim Instanziieren des ImageLabeler durchzuführen: Erstellen Sie einen Labeler 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 Remote-Modell haben, sollten Sie modellbezogene Funktionen deaktivieren, z. B. Teile der Benutzeroberfläche ausgrauen 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 Standardbenachrichtigungscenter anhängen. Verwenden Sie im Beobachterblock eine schwache Referenz auf self, da Downloads einige Zeit dauern können und das ursprüngliche Objekt möglicherweise freigegeben wird, bevor 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]; }];
2. Eingabebild vorbereiten
Erstellen Sie ein VisionImage-Objekt mit einem UIImage oder einem
CMSampleBuffer.
Wenn Sie ein UIImage verwenden, gehen Sie so vor:
- Erstellen Sie ein
VisionImage-Objekt mit demUIImage. Geben Sie die richtige.orientationan.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Wenn Sie einen CMSampleBuffer verwenden, gehen Sie so vor:
-
Geben Sie die Ausrichtung der Bilddaten im
CMSampleBufferan.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; } }
- Erstellen Sie ein
VisionImage-Objekt mit demCMSampleBuffer-Objekt und der 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];
3. Bild-Labeler 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 Labeln von Bildern erfolgreich ist, wird ein Array vonImageLabel zurückgegeben. Jedes ImageLabel steht für etwas, das im Bild mit einem Label versehen wurde. Sie können die Textbeschreibung (falls in den Metadaten der TensorFlow Lite-Modelldatei verfügbar), den Konfidenzwert und den Index jedes Labels 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 Sie Bilder in einer Echtzeitanwendung mit Labels versehen möchten, folgen Sie diesen Richtlinien, um die besten Frameraten zu erzielen:
- Verwenden Sie für die Verarbeitung von Videoframes die synchrone API
results(in:)des Detektors. Rufen Sie diese Methode in der FunktioncaptureOutput(_, didOutput:from:)desAVCaptureVideoDataOutputSampleBufferDelegate's auf, um synchron Ergebnisse aus dem angegebenen Video frame abzurufen. Lassen SieAVCaptureVideoDataOutput'salwaysDiscardsLateVideoFramesauftruegesetzt, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer Videoframe verfügbar wird, während der Detektor ausgeführt wird, wird er verworfen. - Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf das Eingabebild zu legen, rufen Sie zuerst das Ergebnis von ML Kit ab und rendern Sie dann das Bild und die Überlagerung in einem Schritt. So rendern Sie die Anzeigeoberfläche nur einmal für jeden verarbeiteten Eingabeframe. Ein Beispiel finden Sie unter updatePreviewOverlayViewWithLastFrame im ML Kit-Schnellstartbeispiel.