Lorsque vous transmettez une image à ML Kit, il détecte jusqu'à cinq objets dans l'image, ainsi que la position de chaque objet dans l'image. Lors de la détection d'objets dans des flux vidéo, chaque objet possède un ID unique que vous pouvez utiliser pour suivre l'objet d'une image à l'autre.
Vous pouvez utiliser un modèle de classification d'images personnalisé pour classer les objets détectés. Consultez la section Modèles personnalisés avec ML Kit pour obtenir des conseils sur les exigences de compatibilité des modèles, l'emplacement des modèles pré-entraînés et la façon d'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 des éléments de votre application ou le télécharger de manière dynamique depuis Cloud Storage. Le tableau suivant compare les deux options.
| Modèle regroupé | Modèle hébergé |
|---|---|
Le modèle fait partie du fichier .ipa de votre application, ce qui
augmente sa taille. |
Le modèle ne fait pas partie du fichier .ipa de votre application. Il est
hébergé en étant importé dans Cloud Storage. Nous vous recommandons d'utiliser
Cloud Storage for
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. |
| Aucun projet Firebase n'est nécessaire. | Nécessite un projet Firebase (si vous utilisez Cloud Storage for Firebase). |
| Vous devez republier votre application pour mettre à jour le modèle. | Envoyez les mises à jour du modèle sans republier votre application. |
| Aucun test A/B intégré | 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 regroupé et l' application de démarrage rapide AutoML pour obtenir un exemple d'utilisation du modèle hébergé.
- Consultez l'application de démonstration Material Design pour obtenir une implémentation de bout en bout de cette API.
Avant de commencer
Incluez les bibliothèques ML Kit dans votre Podfile :
pod 'GoogleMLKit/ObjectDetectionCustom', '8.0.0'Une fois les pods de votre projet installés ou mis à jour, 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 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 local
Pour regrouper le modèle avec votre application :
Copiez le fichier de modèle (se terminant généralement par
.tfliteou.lite) dans votre projet Xcode, en veillant à sélectionnerCopy bundle resources(Copier les ressources du bundle) lorsque vous le faites. 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 de modèle :Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Configurer une source de modèle hébergé à distance
Pour utiliser le modèle hébergé à distance, vous devez télécharger le fichier de 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 for Firebase pour héberger un modèle. Pour en savoir plus sur l' implémentation, consultez le guide de migration de Firebase ML vers Cloud Storage.
2. Configurer le détecteur d'objets
Une fois que vous avez configuré vos sources de modèle, configurez le détecteur d'objets pour votre cas d'utilisation avec un objet CustomObjectDetectorOptions. Vous pouvez modifier les paramètres suivants :
| Paramètres du détecteur d'objets | |
|---|---|
| Mode de détection |
STREAM_MODE (par défaut) | SINGLE_IMAGE_MODE
En En |
| Détecter et suivre plusieurs objets |
false (par défaut) | true
Indique si vous souhaitez détecter et suivre jusqu'à cinq objets ou uniquement l'objet le plus visible (par défaut). |
| Classer des objets |
false (par défaut) | true
Indique si vous souhaitez classer ou non les objets détectés à l'aide du modèle de classificateur personnalisé fourni. Pour utiliser votre modèle de classification personnalisé, vous devez définir cette valeur sur |
| Seuil de confiance de la classification |
Score de confiance minimal des libellés détectés. Si ce paramètre n'est pas défini, tout seuil de classificateur spécifié par les métadonnées du modèle sera utilisé. Si le modèle ne contient aucune métadonnée ou si les métadonnées ne spécifient pas de seuil de classificateur, un seuil par défaut de 0,0 sera utilisé. |
| Nombre maximal de libellés par objet |
Nombre maximal de libellés par objet que le détecteur renverra. Si ce paramètre n'est pas défini, la valeur par défaut de 10 sera utilisée. |
Si vous ne disposez que d'un modèle regroupé localement, créez simplement un détecteur d'objets à partir de votre objet LocalModel :
Swift
let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
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 détecteur d'objets, si vous disposez à la fois d'un modèle hébergé à distance et d'un modèle regroupé localement, il peut être judicieux d'effectuer cette vérification lors de l'instanciation de l'ObjectDetector : créez un détecteur à 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 = CustomObjectDetectorOptions(localModel: model) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3 let objectDetector = ObjectDetector.objectDetector(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]; } MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:model]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3; MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions: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 interface utilisateur) 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.initializeDetector(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 detector self.initializeDetector(with: modelURL) } } } func initializeDetector(with modelURL: URL) { let localModel = LocalModel(path: modelURL.path) let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true self.objectDetector = ObjectDetector.objectDetector(options: options) // Enable ML features in UI 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 initializeDetectorWithURL: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 detector [self initializeDetectorWithURL:URL]; } }]; } - (void)initializeDetectorWithURL:(NSURL *)modelURL { MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:modelURL.path]; MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; self.objectDetector = [MLKObjectDetector objectDetectorWithOptions:options]; // Enable ML features in UI [self enableMLFeatures]; }
L'API de détection et de suivi d'objets est optimisée pour ces deux cas d'utilisation principaux :
- Détection et suivi en direct de l'objet le plus visible dans le viseur de l'appareil photo.
- Détection de plusieurs objets à partir d'une image statique.
Pour configurer l'API pour ces cas d'utilisation :
Swift
// Live detection and tracking let options = CustomObjectDetectorOptions(localModel: localModel) options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3 // Multiple object detection in static images let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3
Objective-C
// Live detection and tracking MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3; // Multiple object detection in static images MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3;
3. Préparer l'image d'entrée
Créez un VisionImage objet à l'aide d'un UIImage ou d'un
CMSampleBuffer.
Si vous utilisez un UIImage, procédez comme suit :
- Créez un
VisionImageobjet avec leUIImage. Veillez à spécifier le.orientationcorrect.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 le
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'CMSampleBufferobjet et 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];
4. Créer et exécuter le détecteur d'objets
Créez un détecteur d'objets :
Swift
let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Ensuite, utilisez le détecteur :
De manière asynchrone :
Swift
objectDetector.process(image) { objects, error in guard error == nil, let objects = objects, !objects.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[objectDetector processImage:image completion:^(NSArray
*_Nullable objects, NSError *_Nullable error) { if (objects.count == 0) { // Handle the error. return; } // Show results. }]; De manière synchrone :
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray
*objects = [objectDetector resultsInImage:image error:&error]; // Show results or handle the error.
5. Obtenir des informations sur les objets étiquetés
Si l'appel au processeur d'images réussit, il transmet une liste d'Object au gestionnaire de saisie semi-automatique ou renvoie la liste, selon que vous avez appelé la méthode asynchrone ou synchrone.
Chaque Object contient les propriétés suivantes :
frame |
Un CGRect indiquant la position de l'objet dans l'
image. |
||||||
trackingID |
Un entier qui identifie l'objet dans les images, ou `nil` en SINGLE_IMAGE_MODE. | ||||||
labels |
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence), \(label.index)" }.joined(separator: "\n") }
Objective-C
// The list of detected objects contains one item if multiple object detection // wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat:@"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; } }
Garantir une expérience utilisateur optimale
Pour une expérience utilisateur optimale, suivez ces consignes dans votre application :
- La réussite de la détection d'objets dépend de la complexité visuelle de l'objet. Pour être détectés, les objets comportant peu de caractéristiques visuelles peuvent avoir besoin d'occuper une plus grande partie de l'image. Vous devez fournir aux utilisateurs des conseils sur la capture d'entrées qui fonctionnent bien avec le type d'objets que vous souhaitez détecter.
- Lorsque vous utilisez la classification, si vous souhaitez détecter des objets qui ne correspondent pas clairement aux catégories compatibles, implémentez une gestion spéciale pour les objets inconnus.
Consultez également l'application de démonstration ML Kit Material Design et la collection de modèles Material Design pour les fonctionnalités basées sur le machine learning.
Amélioration des performances
Si vous souhaitez utiliser la détection d'objets dans une application en temps réel, suivez ces consignes pour obtenir les meilleures fréquences d'images :Lorsque vous utilisez le mode streaming dans une application en temps réel, n'utilisez pas la détection de plusieurs objets, car la plupart des appareils ne pourront pas produire des fréquences d'images adéquates.
- Pour traiter les images vidéo, utilisez l'API synchrone
results(in:)du détecteur. Appelez cette méthode à partir de laAVCaptureVideoDataOutputSampleBufferDelegatecaptureOutput(_, didOutput:from:)fonction pour obtenir de manière synchrone les résultats de l'image vidéo donnée. ConservezAVCaptureVideoDataOutputdealwaysDiscardsLateVideoFramescommetruepour 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 graphiques sur l'image d'entrée, obtenez d'abord le résultat de ML Kit, puis effectuez le rendu de l'image et de la superposition en une seule étape. Ce faisant, vous n'effectuez le rendu sur la surface d'affichage qu'une seule fois pour chaque image d'entrée traitée. Pour obtenir un exemple, consultez updatePreviewOverlayViewWithLastFrame dans l'exemple de démarrage rapide ML Kit.