Ajouter une étiquette à des images avec un modèle entraîné par AutoML sur iOS
Après avoir entraîné votre propre modèle à l'aide d'AutoML Vision Edge, vous pouvez l'utiliser dans votre application pour ajouter des étiquettes aux images.
Il existe deux façons d'intégrer des modèles entraînés à partir d'AutoML Vision Edge. Vous pouvez regrouper le modèle en copiant ses fichiers dans votre projet Xcode ou le télécharger de manière dynamique à partir de Firebase.
Options de regroupement de modèles | |
---|---|
Regroupé dans votre application |
|
Hébergé avec Firebase |
|
Essayer
- Jouez avec l'application exemple pour voir un exemple d'utilisation de cette API.
Avant de commencer
1. Incluez les bibliothèques ML Kit dans votre Podfile:Pour regrouper un modèle avec votre application :
pod 'GoogleMLKit/ImageLabelingAutoML'Pour télécharger un modèle de manière dynamique depuis Firebase, ajoutez la dépendance
LinkFirebase
:
pod 'GoogleMLKit/ImageLabelingAutoML' pod 'GoogleMLKit/LinkFirebase'2. Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode en utilisant son code
.xcworkspace
code>. ML Kit est compatible avec Xcode version 13.2.1 ou ultérieure.
3. Si vous souhaitez télécharger un modèle, veillez à ajouter Firebase à votre projet iOS, si ce n'est pas déjà fait. Cela n'est pas nécessaire lorsque vous regroupez le modèle.
1. Charger le modèle
Configurer une source de modèle locale
Pour grouper le modèle avec votre application:1. Extrayez le modèle et ses métadonnées dans un dossier de l'archive ZIP que vous avez téléchargée depuis la console Firebase :
your_model_directory |____dict.txt |____manifest.json |____model.tfliteLes trois fichiers doivent se trouver dans le même dossier. Nous vous recommandons d'utiliser les fichiers tels que vous les avez téléchargés, sans les modifier (y compris leurs noms).
2. Copiez le dossier dans votre projet Xcode, en sélectionnant Créer des références de dossier. Le fichier de modèle et les métadonnées seront inclus dans l'app bundle et seront disponibles pour ML Kit.
3. Créez un objet
AutoMLImageLabelerLocalModel
en spécifiant le chemin d'accès au fichier manifeste du modèle:
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];
Configurer une source de modèle hébergée sur Firebase
Pour utiliser le modèle hébergé à distance, créez un objet AutoMLImageLabelerRemoteModel
en spécifiant le nom que vous avez attribué au modèle lorsque vous l'avez publié:
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.
Démarrez ensuite la tâche de téléchargement du modèle en spécifiant les conditions dans lesquelles vous souhaitez autoriser le téléchargement. Si le modèle n'est pas sur l'appareil ou si une version plus récente du modèle est disponible, la tâche télécharge le modèle de manière asynchrone à partir de Firebase:
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];
De nombreuses applications commencent la tâche de téléchargement dans leur code d'initialisation, mais vous pouvez le faire à tout moment avant d'avoir besoin d'utiliser le modèle.
Créer un étiqueteur d'images à partir de votre modèle
Après avoir configuré les sources de votre modèle, créez un objet ImageLabeler
à partir de l'une d'entre elles.
Si vous ne disposez que d'un modèle groupé localement, il vous suffit de créer un étiqueteur à partir de votre objet AutoMLImageLabelerLocalModel
et de configurer le seuil de score de confiance que vous souhaitez exiger (voir Évaluer votre mode:
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];
Si vous disposez d'un modèle hébergé à distance, vous devez vérifier qu'il a été téléchargé avant de l'exécuter. Vous pouvez vérifier l'état de la tâche de téléchargement du modèle à l'aide de la méthode isModelDownloaded
(remoteModel:) du gestionnaire de modèles.
Bien que vous n'ayez qu'à vérifier cela avant d'exécuter l'étiqueteur, si vous disposez à la fois d'un modèle hébergé à distance et d'un modèle groupé localement, il peut être judicieux d'effectuer cette vérification lors de l'instanciation de ImageLabeler
: créez un étiqueteur à partir du modèle distant s'il a été téléchargé, et à partir du modèle local.
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];
Si vous ne disposez que d'un modèle hébergé à distance, vous devez désactiver les fonctionnalités liées au modèle (par exemple, griser ou masquer une partie de l'interface utilisateur) jusqu'à ce que vous confirmiez que le modèle a été téléchargé.
Vous pouvez obtenir l'état de téléchargement du modèle en associant des observateurs au centre de notifications par défaut. Veillez à utiliser une référence faible à self
dans le bloc d'observateur, car les téléchargements peuvent prendre un certain temps et l'objet d'origine peut être libéré à la fin du téléchargement. Exemple :
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. Préparer l'image d'entrée
Créez un objet VisionImage
à l'aide d'un UIImage
ou d'un CMSampleBuffer
.
Si vous utilisez un UIImage
, procédez comme suit:
- Créez un objet
VisionImage
avecUIImage
. Veillez à spécifier le bon.orientation
.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Si vous utilisez un CMSampleBuffer
, procédez comme suit:
-
Spécifiez l'orientation des données d'image contenues dans
CMSampleBuffer
.Pour obtenir l'orientation de l'image:
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; } }
- Créez un objet
VisionImage
à l'aide de l'objet et de l'orientationCMSampleBuffer
: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. Exécuter l'étiqueteur d'images
De manière asynchrone:
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. }];
De manière synchrone:
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. Obtenir des informations sur les objets étiquetés
Si l'opération d'ajout d'étiquettes à l'image réussit, elle renvoie un tableau deImageLabel
. Chaque ImageLabel
représente un élément étiqueté dans l'image. Vous pouvez obtenir la description textuelle de chaque libellé (si disponible dans les métadonnées du fichier de modèle TensorFlow Lite), le score de confiance et l'index.
Exemple :
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; }
Conseils pour améliorer les performances en temps réel
Si vous souhaitez étiqueter des images dans une application en temps réel, suivez ces consignes pour obtenir les meilleures fréquences d'images:
- Pour traiter les images vidéo, utilisez l'API synchrone
results(in:)
du détecteur. Appelez cette méthode à partir de la fonctioncaptureOutput(_, didOutput:from:)
deAVCaptureVideoDataOutputSampleBufferDelegate
pour obtenir les résultats de manière synchrone à partir de l'image vidéo donnée. Conservez lealwaysDiscardsLateVideoFrames
deAVCaptureVideoDataOutput
défini surtrue
pour limiter les appels au détecteur. Si une nouvelle image vidéo devient disponible pendant que le détecteur est en cours d'exécution, elle sera ignorée. - Si vous utilisez la sortie du détecteur pour superposer des éléments graphiques à l'image d'entrée, obtenez d'abord le résultat de ML Kit, puis affichez l'image et la superposition en une seule étape. Ainsi, vous n'effectuez le rendu sur la surface d'affichage qu'une seule fois pour chaque trame d'entrée traitée. Consultez la section updatePreviewOverlayViewWithLastFrame dans l'exemple de démarrage rapide de ML Kit.