Etichetta le immagini con un modello addestrato con AutoML su iOS

Dopo aver addestrato il tuo modello utilizzando AutoML Vision Edge, puoi utilizzarla nella tua app per etichettare le immagini.

Esistono due modi per integrare i modelli addestrati da AutoML Vision Edge. Puoi raggruppa il modello copiandone i file nel progetto Xcode oppure può scaricarlo dinamicamente da Firebase.

Opzioni di raggruppamento dei modelli
Raggruppati nella tua app
  • Il modello fa parte del bundle
  • Il modello è disponibile immediatamente, anche quando il dispositivo iOS è offline
  • Non è necessario un progetto Firebase
Ospitato con Firebase
  • Ospita il modello caricandolo Firebase Machine Learning
  • Riduce le dimensioni dell'app bundle
  • Il modello viene scaricato on demand
  • Esegui il push degli aggiornamenti del modello senza ripubblicare l'app
  • Test A/B semplici con Firebase Remote Config
  • Richiede un progetto Firebase

Prova

  • Prova l'app di esempio per per vedere un esempio di utilizzo di questa API.

Prima di iniziare

1. Includi le librerie ML Kit nel podfile:

Per raggruppare un modello con la tua app:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    
Per scaricare dinamicamente un modello da Firebase, aggiungi LinkFirebase :
    pod 'GoogleMLKit/ImageLabelingAutoML'
    pod 'GoogleMLKit/LinkFirebase'
    
2. Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando il proprio .xcworkspacecode>. ML Kit è supportato in Xcode versione 13.2.1 o successiva. 3. Se vuoi scaricare un modello, assicurati di aggiungi Firebase al tuo progetto iOS, se non l'hai già fatto. Questa operazione non è necessaria se includi un modello di machine learning.

1. Carica il modello

Configura un'origine del modello locale

Per raggruppare il modello con la tua app:

1. Estrai il modello e i relativi metadati dall'archivio ZIP che hai scaricato dalla console Firebase in una cartella:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
Tutti e tre i file devono trovarsi nella stessa cartella. Ti consigliamo di utilizzare i file così come li hai scaricati, senza modifiche (inclusi i nomi dei file).

2. Copia la cartella nel tuo progetto Xcode, assicurandoti di selezionare In questo caso, crea riferimenti alle cartelle. Il file e i metadati del modello saranno incluse nell'app bundle e saranno disponibili in ML Kit.

3. Crea l'oggetto AutoMLImageLabelerLocalModel, specificando il percorso dell'oggetto file manifest del modello:

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];

Configura l'origine di un modello ospitata da Firebase

Per utilizzare il modello ospitato in remoto, crea un AutoMLImageLabelerRemoteModel specificando il nome assegnato al modello al momento della pubblicazione:

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.

Poi, avvia l'attività di download del modello, specificando le condizioni in cui vuoi consentire il download. Se il modello non è presente sul dispositivo o se una versione più recente del modello, l'attività scaricherà in modo asincrono modello di 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];

Molte app avviano l'attività di download nel codice di inizializzazione, ma puoi farlo in qualsiasi momento, prima di utilizzare il modello.

Crea un etichettatore di immagini dal modello

Dopo aver configurato le origini del modello, crea un oggetto ImageLabeler da uno alcune.

Se hai solo un modello in bundle locale, crea un etichettatore dalla tua AutoMLImageLabelerLocalModel e configura il punteggio di confidenza la soglia che vuoi richiedere (vedi Valuta la modalità:

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];

Se il tuo modello è ospitato in remoto, dovrai verificare che sia stato scaricato prima di eseguirlo. Puoi controllare lo stato del download del modello utilizzando il metodo isModelDownloaded(remoteModel:) del gestore modelli.

Anche se devi solo confermare prima di eseguire l'etichettatore, se sia un modello ospitato in remoto sia uno in bundle locale, di eseguire questo controllo durante la creazione di un'istanza per ImageLabeler: etichettatore dal modello remoto, se è stato scaricato, e dal modello locale negli altri casi.

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];

Se disponi solo di un modello ospitato in remoto, devi disattivare le relative funzionalità, ad esempio rendere non selezionabile o nascondere parte dell'interfaccia utente, fino a quando confermi che il modello è stato scaricato.

Puoi ottenere lo stato di download del modello collegando gli osservatori all'impostazione predefinita Centro notifiche. Assicurati di utilizzare un riferimento debole a self nell'osservatore perché i download possono richiedere del tempo e l'oggetto di origine può essere verrà liberato al termine del download. Ad esempio:

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. Prepara l'immagine di input

Crea un oggetto VisionImage utilizzando un UIImage o un CMSampleBuffer.

Se usi un UIImage, segui questi passaggi:

  • Crea un oggetto VisionImage con UIImage. Assicurati di specificare il valore .orientation corretto.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Se usi un CMSampleBuffer, segui questi passaggi:

  • Specifica l'orientamento dei dati dell'immagine contenuti nei CMSampleBuffer.

    Per ottenere l'orientamento dell'immagine:

    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;
      }
    }
          
  • Crea un oggetto VisionImage utilizzando il metodo CMSampleBuffer oggetto e orientamento:

    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. Esegui l'etichettatore delle immagini

In modo asincrono:

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.
     }];

In modo sincrono:

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. Ottieni informazioni sugli oggetti etichettati

Se l'operazione di etichettatura delle immagini ha esito positivo, restituisce un array di ImageLabel Ciascun ImageLabel rappresenta qualcosa che era etichettate nell'immagine. Puoi visualizzare la descrizione testuale di ogni etichetta (se disponibile in i metadati del file del modello TensorFlow Lite), il punteggio di confidenza e l'indice. Ad esempio:

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;
}

Suggerimenti per migliorare il rendimento in tempo reale

Se vuoi etichettare le immagini in un'applicazione in tempo reale, segui questi passaggi: linee guida per ottenere le migliori frequenze fotogrammi:

  • Per elaborare i fotogrammi video, utilizza l'API sincrona results(in:) del rilevatore. Chiama questo metodo dal di AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) per ottenere in modo sincrono i risultati dal video specificato frame. Mantieni di AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames come true per limitare le chiamate al rilevatore. Se un nuovo il fotogramma video diventa disponibile mentre il rilevatore è in esecuzione, quindi verrà eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre elementi grafici l'immagine di input, occorre prima ottenere il risultato da ML Kit, quindi eseguire il rendering dell'immagine e la sovrapposizione in un solo passaggio. In questo modo, puoi visualizzare i contenuti solo una volta per ogni frame di input elaborato. Vedi la pagina updatePreviewOverlayViewWithLastFrame. nell'esempio della guida rapida di ML Kit.