Vous pouvez utiliser ML Kit pour reconnaître des entités dans une image et les étiqueter. Cette API est compatible avec un large éventail de modèles de classification d'images personnalisés. Consultez Modèles personnalisés avec ML Kit pour obtenir des conseils sur les exigences de compatibilité des modèles, où trouver des modèles pré-entraînés et comment entraîner vos propres modèles.
Il existe deux façons d'intégrer un modèle personnalisé : vous pouvez regrouper le modèle en le plaçant dans le dossier d'assets de votre application, ou vous pouvez le télécharger dynamiquement depuis Cloud Storage. Le tableau suivant compare les deux options.
| Modèle groupé | Modèle hébergé |
|---|---|
| Le modèle fait partie de l'APK de votre application, ce qui augmente sa taille. | Le modèle ne fait pas partie de votre fichier APK. Il est hébergé en étant importé dans Cloud Storage. Nous vous recommandons d'utiliser Cloud Storage pour Firebase. |
| Le modèle est disponible immédiatement, même lorsque l'appareil Android est hors connexion. | Votre application doit inclure du code pour télécharger le modèle à la demande. |
| Pas besoin de projet Firebase | Nécessite un projet Firebase (si vous utilisez Cloud Storage pour Firebase). |
| Vous devez republier votre application pour mettre à jour le modèle. | Déployer des mises à jour de modèle sans republier votre application |
| Pas de tests A/B intégrés | Tests A/B avec Firebase Remote Config |
Essayer
- Consultez l'application de démarrage rapide Vision pour obtenir un exemple d'utilisation du modèle fourni et l'application de démarrage rapide AutoML pour obtenir un exemple d'utilisation du modèle hébergé.
Avant de commencer
Incluez les bibliothèques ML Kit dans votre fichier Podfile :
pod 'GoogleMLKit/ImageLabelingCustom', '8.0.0'Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode à l'aide de son fichier
.xcworkspace. ML Kit est compatible avec Xcode version 13.2.1 ou ultérieure.Si vous souhaitez télécharger un modèle à l'aide de Cloud Storage for Firebase, assurez-vous d'ajouter Firebase à votre projet iOS, si vous ne l'avez pas déjà fait. Cette étape n'est pas nécessaire lorsque vous regroupez le modèle.
1. Charger le modèle
Configurer une source de modèle local
Pour regrouper le modèle avec votre application :
Copiez le fichier de modèle (qui se termine généralement par
.tfliteou.lite) dans votre projet Xcode, en veillant à sélectionnerCopy bundle resources. Le fichier de modèle sera inclus dans l'app bundle et disponible pour ML Kit.Créez un objet
LocalModelen spécifiant le chemin d'accès au fichier du modèle :Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Configurer une source de modèle hébergée à distance
Pour utiliser le modèle hébergé à distance, vous devez télécharger le fichier du modèle dans le stockage local de l'appareil à l'aide de votre propre logique d'application, puis le charger en tant que modèle local. Nous vous recommandons d'utiliser Cloud Storage pour Firebase pour héberger un modèle. Pour plus d'informations sur l'implémentation, consultez le guide de migration de Firebase ML vers Cloud Storage.
Configurer l'outil d'étiquetage d'images
Après avoir configuré vos sources de modèle, créez un objet ImageLabeler à partir de l'une d'elles.
Les options suivantes sont disponibles :
| Options | |
|---|---|
confidenceThreshold
|
Score de confiance minimal des libellés détectés. Si aucune valeur n'est définie, le seuil de classification spécifié par les métadonnées du modèle est utilisé. Si le modèle ne contient aucune métadonnée ou si les métadonnées ne spécifient pas de seuil de classification, un seuil par défaut de 0,0 sera utilisé. |
maxResultCount
|
Nombre maximal de libellés à renvoyer. Si elle n'est pas définie, la valeur par défaut de 10 sera utilisée. |
Si vous ne disposez que d'un modèle groupé localement, créez simplement un outil de libellisation à partir de votre objet LocalModel :
Swift
let options = CustomImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
Si vous disposez d'un modèle hébergé à distance, vous devrez vérifier qu'il a été téléchargé avant de l'exécuter.
Bien que vous n'ayez à confirmer cela qu'avant d'exécuter le labeler, si vous disposez à la fois d'un modèle hébergé à distance et d'un modèle fourni localement, il peut être judicieux d'effectuer cette vérification lors de l'instanciation de ImageLabeler : créez un labeler à partir du modèle distant s'il a été téléchargé, et à partir du modèle local dans le cas contraire.
Swift
// Path where your download logic saves the model let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite") let model: LocalModel if FileManager.default.fileExists(atPath: localModelURL.path) { // Use the downloaded model model = LocalModel(path: localModelURL.path) } else { // Fall back to bundled model guard let bundledModelPath = Bundle.main.path(forResource: "model", ofType: "tflite") else { return } model = LocalModel(path: bundledModelPath) } let options = CustomImageLabelerOptions(localModel: model) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"]; MLKLocalModel *model; if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) { // Use the downloaded model model = [[MLKLocalModel alloc] initWithPath:localModelPath]; } else { // Fall back to bundled model NSString *bundledModelPath = [NSBundle.mainBundle pathForResource:@"model" ofType:@"tflite"]; model = [[MLKLocalModel alloc] initWithPath:bundledModelPath]; } MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:model]; 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 votre UI) jusqu'à ce que vous confirmiez que le modèle a été téléchargé.
Swift
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite") if FileManager.default.fileExists(atPath: localModelURL.path) { // Model is already cached, initialize immediately self.initializeLabeler(with: localModelURL) } else { // Model is not yet available, show loading UI and start download self.showLoadingUI() let storage = Storage.storage() let modelRef = storage.reference(forURL: "gs://YOUR_BUCKET/path/to/model.tflite") modelRef.write(toFile: localModelURL) { url, error in self.hideLoadingUI() if let error = error { // Handle download error self.showErrorUI() } else if let modelURL = url { // Download success, initialize labeler self.initializeLabeler(with: modelURL) } } } func initializeLabeler(with modelURL: URL) { let localModel = LocalModel(path: modelURL.path) let options = CustomImageLabelerOptions(localModel: localModel) self.imageLabeler = ImageLabeler.imageLabeler(options: options) // Enable ML-related UI features here self.enableMLFeatures() }
Objective-C
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"]; NSURL *localModelURL = [NSURL fileURLWithPath:localModelPath]; if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) { // Model is already cached, initialize immediately [self initializeLabelerWithURL:localModelURL]; } else { // Model is not yet available, show loading UI and start download [self showLoadingUI]; FIRStorage *storage = [FIRStorage storage]; FIRStorageReference *modelRef = [storage referenceForURL:@"gs://YOUR_BUCKET/path/to/model.tflite"]; [modelRef writeToFile:localModelURL completion:^(NSURL * _Nullable URL, NSError * _Nullable error) { [self hideLoadingUI]; if (error != nil) { // Handle download error [self showErrorUI]; } else { // Download success, initialize labeler [self initializeLabelerWithURL:URL]; } }]; } - (void)initializeLabelerWithURL:(NSURL *)modelURL { MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:modelURL.path]; MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; self.imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options]; // Enable ML-related UI features here [self enableMLFeatures]; }
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
VisionImageavecUIImage. Veillez à spécifier le.orientationapproprié.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'objetCMSampleBufferet de l'orientation :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'outil d'étiquetage d'images
Pour libeller des objets dans une image, transmettez l'objet image à la méthode process() de ImageLabeler.
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 (label.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 entités libellées
Si l'opération d'étiquetage d'image réussit, elle renvoie un tableau deImageLabel. Chaque ImageLabel représente un élément identifié dans l'image. Vous pouvez obtenir la description textuelle de chaque libellé (si elle est disponible dans les métadonnées du fichier de modèle LiteRT), 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:)deAVCaptureVideoDataOutputSampleBufferDelegatepour obtenir de manière synchrone les résultats de la frame vidéo donnée. Conservez la valeurtruepouralwaysDiscardsLateVideoFramesdeAVCaptureVideoDataOutputafin de limiter les appels au détecteur. Si une nouvelle image vidéo devient disponible pendant l'exécution du détecteur, elle sera supprimée. - Si vous utilisez la sortie du détecteur pour superposer des éléments graphiques sur 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. Vous n'avez ainsi besoin d'effectuer le rendu sur la surface d'affichage qu'une seule fois pour chaque frame d'entrée traité. Pour obtenir un exemple, consultez updatePreviewOverlayViewWithLastFrame dans l'exemple de démarrage rapide de ML Kit.