Bilder mit einem AutoML-trainierten Modell auf iOS-Geräten mit Labels versehen
Nachdem Sie Ihr eigenes Modell mit AutoML Vision Edge trainiert haben, können Sie es in Ihrer App verwenden, um Bilder zu labeln.
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 es dynamisch aus Firebase herunterladen.
Optionen für die Kombination von Modellen | |
---|---|
In Ihrer App gebündelt |
|
Mit Firebase gehostet |
|
Jetzt ausprobieren
- Beispiel-App ausprobieren, um ein Beispiel für die Verwendung dieser API zu sehen.
Hinweis
1. Fügen Sie die ML Kit-Bibliotheken in Ihr Podfile ein:So bündeln Sie ein Modell mit Ihrer App:
pod 'GoogleMLKit/ImageLabelingAutoML'
LinkFirebase
-Abhängigkeit hinzu:
pod 'GoogleMLKit/ImageLabelingAutoML' pod 'GoogleMLKit/LinkFirebase'
.xcworkspace
code>. ML Kit wird in Xcode-Version 13.2.1 oder höher unterstützt.
3. Wenn Sie ein Modell herunterladen möchten, müssen Sie Firebase zu Ihrem iOS-Projekt hinzufügen, sofern 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 aus 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 achten Sie darauf, dass Sie dabei Create folder references (Ordnerreferenzen erstellen) auswählen. Die Modelldatei und die Metadaten werden in das App-Bundle aufgenommen und sind für ML Kit verfügbar.
3. Erstellen Sie das
AutoMLImageLabelerLocalModel
-Objekt und geben Sie den Pfad zur Modellmanifestdatei 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];
Von Firebase gehostete Modellquelle konfigurieren
Wenn Sie das remote gehostete 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 Modell-Download und geben Sie die Bedingungen an, unter denen Sie das Herunterladen zulassen möchten. Wenn das Modell nicht auf dem Gerät vorhanden ist 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 Downloadvorgang in ihrem Initialisierungscode, aber Sie können dies jederzeit tun, bevor Sie das Modell verwenden müssen.
Image-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 erforderlichen Konfidenzwertschwellenwert (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 Modell haben, das auf einem Remote-Server gehostet wird, müssen Sie prüfen, ob es heruntergeladen wurde, bevor Sie es ausführen. Sie können den Status des Modelldownloads mit der Methode isModelDownloaded
(remoteModel:) des Modellmanagers prüfen.
Sie müssen dies zwar nur vor dem Ausführen des Labelers bestätigen, aber wenn Sie sowohl ein remote gehostetes als auch ein lokal gebündeltes Modell haben, kann es sinnvoll sein, diese Prüfung beim Instanziieren von 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. einen Teil der Benutzeroberfläche ausgrauen oder ausblenden, bis Sie bestätigen, dass das Modell heruntergeladen wurde.
Sie können den Downloadstatus des Modells abrufen, indem Sie Beobachter an das Standard-Notification Center anhängen. Verwenden Sie im Observer-Block unbedingt einen schwachen Verweis 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
. Achten Sie darauf, dass Sie die richtige.orientation
angeben.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Wenn Sie ein CMSampleBuffer
verwenden, gehen Sie 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; } }
- 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. Bildlabeler 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 gelabelten Objekten abrufen
Wenn die Bildkennzeichnung erfolgreich ist, wird ein Array vonImageLabel
zurückgegeben. Jedes ImageLabel
steht für etwas, das auf dem Bild gekennzeichnet wurde. Sie können die Textbeschreibung (falls in den Metadaten der TensorFlow Lite-Modelldatei verfügbar), den Konfidenzwert und den Index für jedes Label 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 labeln möchten, sollten Sie die folgenden Richtlinien beachten, um die besten Framerates zu erzielen:
- Verwenden Sie für die Verarbeitung von Videoframes die synchrone
results(in:)
-API des Detektors. Rufen Sie diese Methode aus der FunktioncaptureOutput(_, didOutput:from:)
desAVCaptureVideoDataOutputSampleBufferDelegate
auf, um synchron Ergebnisse aus dem angegebenen Videobild abzurufen. Behalten Sie diealwaysDiscardsLateVideoFrames
vonAVCaptureVideoDataOutput
alstrue
bei, um Aufrufe des Detektors zu drosseln. Wenn ein neuer Videoframes verfügbar wird, während der Detektor ausgeführt wird, wird er verworfen. - Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf dem Eingabebild zu überlagern, rufen Sie zuerst das Ergebnis von ML Kit ab und rendern Sie dann das Bild und die Überlagerung in einem einzigen Schritt. Dadurch wird für jeden verarbeiteten Eingabe-Frame nur einmal auf die Displayoberfläche gerendert. Ein Beispiel finden Sie in der updatePreviewOverlayViewWithLastFrame-Funktion im ML Kit-Schnellstartbeispiel.