Attribuer des étiquettes aux images avec un modèle AutoML entraîné 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 étiqueter les images.

Avant que tu commences

  1. Si vous n'avez pas encore ajouté Firebase à votre application, faites-le en suivant les étapes du guide de démarrage .
  2. Incluez les bibliothèques ML Kit dans votre Podfile :
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionAutoML', '6.25.0'
    
    Après avoir installé ou mis à jour les pods de votre projet, assurez-vous d'ouvrir votre projet Xcode à l'aide de son .xcworkspace .
  3. Dans votre application, importez Firebase :

    Rapide

    import Firebase

    Objectif c

    @import Firebase;

1. Chargez le modèle

ML Kit exécute vos modèles générés par AutoML sur l'appareil. Cependant, vous pouvez configurer ML Kit pour charger votre modèle à distance depuis Firebase, depuis le stockage local, ou les deux.

En hébergeant le modèle sur Firebase, vous pouvez mettre à jour le modèle sans publier de nouvelle version de l'application, et vous pouvez utiliser la configuration à distance et les tests A/B pour proposer dynamiquement différents modèles à différents ensembles d'utilisateurs.

Si vous choisissez de fournir le modèle uniquement en l'hébergeant avec Firebase, et de ne pas le regrouper avec votre application, vous pouvez réduire la taille de téléchargement initiale de votre application. Gardez toutefois à l’esprit que si le modèle n’est pas fourni avec votre application, aucune fonctionnalité liée au modèle ne sera disponible tant que votre application n’aura pas téléchargé le modèle pour la première fois.

En regroupant votre modèle avec votre application, vous pouvez vous assurer que les fonctionnalités ML de votre application fonctionnent toujours lorsque le modèle hébergé par Firebase n'est pas disponible.

Configurer une source de modèle hébergée par Firebase

Pour utiliser le modèle hébergé à distance, créez un objet AutoMLRemoteModel , en spécifiant le nom que vous avez attribué au modèle lors de sa publication :

Rapide

let remoteModel = AutoMLRemoteModel(
    name: "your_remote_model"  // The name you assigned in the Firebase console.
)

Objectif c

FIRAutoMLRemoteModel *remoteModel = [[FIRAutoMLRemoteModel alloc]
    initWithName:@"your_remote_model"];  // The name you assigned in the Firebase console.

Ensuite, démarrez 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échargera le modèle de manière asynchrone depuis Firebase :

Rapide

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

Objectif c

FIRModelDownloadConditions *downloadConditions =
    [[FIRModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[FIRModelManager modelManager] downloadRemoteModel:remoteModel
                                             conditions:downloadConditions];

De nombreuses applications démarrent la tâche de téléchargement dans leur code d'initialisation, mais vous pouvez le faire à tout moment avant de devoir utiliser le modèle.

Configurer une source de modèle locale

Pour regrouper le modèle avec votre application :

  1. Extrayez le modèle et ses métadonnées de l'archive zip que vous avez téléchargée depuis la console Firebase dans un dossier :
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
    Les 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 modification (y compris les noms de fichiers).
  2. Copiez le dossier dans votre projet Xcode, en prenant soin de sélectionner Créer des références de dossier lorsque vous le faites. Le fichier modèle et les métadonnées seront inclus dans l'ensemble d'applications et disponibles pour ML Kit.
  3. Créez un objet AutoMLLocalModel en spécifiant le chemin d'accès au fichier manifeste du modèle :

    Rapide

    guard let manifestPath = Bundle.main.path(
        forResource: "manifest",
        ofType: "json",
        inDirectory: "your_model_directory"
    ) else { return true }
    let localModel = AutoMLLocalModel(manifestPath: manifestPath)
    

    Objectif c

    NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest"
                                                           ofType:@"json"
                                                      inDirectory:@"your_model_directory"];
    FIRAutoMLLocalModel *localModel = [[FIRAutoMLLocalModel alloc] initWithManifestPath:manifestPath];
    

Créez un étiqueteur d'image à partir de votre modèle

Après avoir configuré vos sources de modèle, créez un objet VisionImageLabeler à partir de l'une d'entre elles.

Si vous disposez uniquement d'un modèle regroupé localement, créez simplement un étiqueteur à partir de votre objet AutoMLLocalModel et configurez le seuil de score de confiance que vous souhaitez exiger (voir Évaluer votre modèle ) :

Rapide

let options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = 0  // Evaluate your model in the Firebase console
                                 // to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)

Objectif c

FIRVisionOnDeviceAutoMLImageLabelerOptions *options =
    [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = 0;  // Evaluate your model in the Firebase console
                                  // to determine an appropriate value.
FIRVisionImageLabeler *labeler =
    [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions: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. Vous pouvez vérifier l'état de la tâche de téléchargement de modèle à l'aide de la méthode isModelDownloaded(remoteModel:) du gestionnaire de modèles.

Bien que vous n'ayez qu'à confirmer cela avant d'exécuter l'étiqueteur, 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 VisionImageLabeler : créez un étiqueteur à partir du modèle distant s'il est été téléchargé, et à partir du modèle local dans le cas contraire.

Rapide

var options: VisionOnDeviceAutoMLImageLabelerOptions?
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = VisionOnDeviceAutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = 0  // Evaluate your model in the Firebase console
                                 // to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)

Objectif c

VisionOnDeviceAutoMLImageLabelerOptions *options;
if ([[FIRModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = 0.0f;  // Evaluate your model in the Firebase console
                                     // to determine an appropriate value.
FIRVisionImageLabeler *labeler = [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];

Si vous disposez uniquement 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é.

Vous pouvez obtenir l'état de téléchargement du modèle en attachant des observateurs au centre de notifications par défaut. Assurez-vous d'utiliser une référence faible à self dans le bloc 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. Par exemple:

Rapide

NotificationCenter.default.addObserver(
    forName: .firebaseMLModelDownloadDidSucceed,
    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: .firebaseMLModelDownloadDidFail,
    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]
    // ...
}

Objectif c

__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:FIRModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              FIRRemoteModel *model = note.userInfo[FIRModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:FIRModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[FIRModelDownloadUserInfoKeyError];
            }];

2. Préparez l'image d'entrée

Ensuite, pour chaque image que vous souhaitez étiqueter, créez un objet VisionImage à l'aide de l'une des options décrites dans cette section et transmettez-le à une instance de VisionImageLabeler (décrite dans la section suivante).

Créez un objet VisionImage à l'aide d'un UIImage ou d'un CMSampleBufferRef .

Pour utiliser une UIImage :

  1. Si nécessaire, faites pivoter l'image pour que sa propriété imageOrientation soit .up .
  2. Créez un objet VisionImage à l'aide du UIImage correctement pivoté. Ne spécifiez aucune métadonnée de rotation : la valeur par défaut, .topLeft , doit être utilisée.

    Rapide

    let image = VisionImage(image: uiImage)

    Objectif c

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

Pour utiliser un CMSampleBufferRef :

  1. Créez un objet VisionImageMetadata qui spécifie l'orientation des données d'image contenues dans le tampon CMSampleBufferRef .

    Pour obtenir l'orientation de l'image :

    Rapide

    func imageOrientation(
        deviceOrientation: UIDeviceOrientation,
        cameraPosition: AVCaptureDevice.Position
        ) -> VisionDetectorImageOrientation {
        switch deviceOrientation {
        case .portrait:
            return cameraPosition == .front ? .leftTop : .rightTop
        case .landscapeLeft:
            return cameraPosition == .front ? .bottomLeft : .topLeft
        case .portraitUpsideDown:
            return cameraPosition == .front ? .rightBottom : .leftBottom
        case .landscapeRight:
            return cameraPosition == .front ? .topRight : .bottomRight
        case .faceDown, .faceUp, .unknown:
            return .leftTop
        }
    }

    Objectif c

    - (FIRVisionDetectorImageOrientation)
        imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                               cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationLeftTop;
          } else {
            return FIRVisionDetectorImageOrientationRightTop;
          }
        case UIDeviceOrientationLandscapeLeft:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationBottomLeft;
          } else {
            return FIRVisionDetectorImageOrientationTopLeft;
          }
        case UIDeviceOrientationPortraitUpsideDown:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationRightBottom;
          } else {
            return FIRVisionDetectorImageOrientationLeftBottom;
          }
        case UIDeviceOrientationLandscapeRight:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationTopRight;
          } else {
            return FIRVisionDetectorImageOrientationBottomRight;
          }
        default:
          return FIRVisionDetectorImageOrientationTopLeft;
      }
    }

    Ensuite, créez l'objet de métadonnées :

    Rapide

    let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
    let metadata = VisionImageMetadata()
    metadata.orientation = imageOrientation(
        deviceOrientation: UIDevice.current.orientation,
        cameraPosition: cameraPosition
    )

    Objectif c

    FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
    AVCaptureDevicePosition cameraPosition =
        AVCaptureDevicePositionBack;  // Set to the capture device you used.
    metadata.orientation =
        [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                     cameraPosition:cameraPosition];
  2. Créez un objet VisionImage à l'aide de l'objet CMSampleBufferRef et des métadonnées de rotation :

    Rapide

    let image = VisionImage(buffer: sampleBuffer)
    image.metadata = metadata

    Objectif c

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
    image.metadata = metadata;

3. Exécutez l'étiqueteur d'images

Pour étiqueter des objets dans une image, transmettez l'objet VisionImage à la méthode process() de VisionImageLabeler :

Rapide

labeler.process(image) { labels, error in
    guard error == nil, let labels = labels else { return }

    // Task succeeded.
    // ...
}

Objectif c

[labeler
    processImage:image
      completion:^(NSArray<FIRVisionImageLabel *> *_Nullable labels, NSError *_Nullable error) {
        if (error != nil || labels == nil) {
          return;
        }

        // Task succeeded.
        // ...
      }];

Si l’étiquetage de l’image réussit, un tableau d’objets VisionImageLabel sera transmis au gestionnaire d’achèvement. À partir de chaque objet, vous pouvez obtenir des informations sur une caractéristique reconnue dans l'image.

Par exemple:

Rapide

for label in labels {
    let labelText = label.text
    let confidence = label.confidence
}

Objectif c

for (FIRVisionImageLabel *label in labels) {
  NSString *labelText = label.text;
  NSNumber *confidence = label.confidence;
}

Conseils pour améliorer les performances en temps réel

  • Accélérez les appels au détecteur. Si une nouvelle image vidéo devient disponible pendant le fonctionnement du détecteur, supprimez l'image.
  • 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 la superposition en une seule étape. Ce faisant, vous effectuez le rendu sur la surface d'affichage une seule fois pour chaque image d'entrée. Consultez les classes previewOverlayView et FIRDetectionOverlayView dans l’exemple d’application de présentation pour un exemple.