Guida alla segmentazione delle immagini per iOS

L'attività Segmentazione immagine ti consente di suddividere le immagini in regioni in base a categorie predefinite e di applicare effetti visivi come la sfocatura dello sfondo. Queste istruzioni mostrano come utilizzare lo strumento di segmentazione delle immagini con le app per iOS.

L'esempio di codice descritto in queste istruzioni è disponibile su GitHub.

Puoi vedere questa operazione in azione visualizzando la demo web. Per ulteriori informazioni sulle funzionalità, sui modelli e sulle opzioni di configurazione di questa attività, consulta la Panoramica.

Esempio di codice

L'esempio di codice MediaPipe Tasks contiene un'implementazione semplice di un'app di segmentazione delle immagini per iOS.

L'esempio implementa uno strumento di segmentazione delle immagini che restituisce maschere di categoria. Utilizza la videocamera di un dispositivo iOS fisico per eseguire la segmentazione delle immagini su un feed della videocamera in diretta o su immagini e video della galleria dei dispositivi.

Puoi utilizzare l'app come punto di partenza per la tua app per iOS o farvi riferimento quando modifichi un'app esistente. Il codice di esempio di Image Segmenter è ospitato su GitHub.

Scarica il codice

Le istruzioni riportate di seguito mostrano come creare una copia locale del codice di esempio utilizzando lo strumento a riga di comando git.

Per scaricare il codice di esempio:

  1. Clona il repository Git utilizzando il seguente comando:

    git clone https://github.com/google-ai-edge/mediapipe-samples/
    
  2. Se vuoi, configura l'istanza Git in modo da utilizzare il controllo sparse, in modo da avere solo i file per l'app di esempio Image Segmenter:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/ios/
    

Dopo aver creato una versione locale del codice di esempio, puoi installare la libreria di attività MediaPipe, aprire il progetto utilizzando Xcode ed eseguire l'app. Per le istruzioni, consulta la Guida alla configurazione per iOS.

Componenti chiave

I seguenti file contengono il codice fondamentale per l'applicazione di esempio di segmentazione delle immagini:

  • ImageSegmenterService.swift: inizializza lo strumento di segmentazione delle immagini, gestisce la selezione del modello ed esegue l'inferenza sui dati di input.
  • CameraViewController.swift: implementa l'interfaccia utente per la modalità di inserimento del feed videocamera in diretta e visualizza i risultati.
  • MediaLibraryViewController.swift Implementa l'interfaccia utente per la modalità di input di file di immagini statiche e video e visualizza i risultati.

Configurazione

Questa sezione descrive i passaggi chiave per configurare l'ambiente di sviluppo e i progetti di codice per utilizzare la segmentazione delle immagini. Per informazioni generali sulla configurazione dell'ambiente di sviluppo per l'utilizzo delle attività MediaPipe, inclusi i requisiti della versione della piattaforma, consulta la guida alla configurazione per iOS.

Dipendenze

Image Segmenter utilizza la libreria MediaPipeTasksVision, che deve essere installata utilizzando CocoaPods. La libreria è compatibile con le app Swift e Objective-C e non richiede alcuna configurazione aggiuntiva specifica per la lingua.

Per istruzioni su come installare CocoaPods su macOS, consulta la guida all'installazione di CocoaPods. Per istruzioni su come creare un Podfile con i pod necessari per la tua app, consulta Utilizzare CocoaPods.

Aggiungi il pod MediaPipeTasksVision in Podfile utilizzando il seguente codice:

target 'MyImageSegmenterApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

Se la tua app include target di test di unità, consulta la Guida alla configurazione per iOS per ulteriori informazioni sulla configurazione del tuo Podfile.

Modello

L'attività di segmentazione delle immagini MediaPipe richiede un modello addestrato compatibile con questa attività. Per ulteriori informazioni sui modelli addestrati disponibili per la segmentazione delle immagini, consulta la sezione Modelli della panoramica delle attività.

Seleziona e scarica un modello, quindi aggiungilo alla directory del progetto utilizzando Xcode. Per istruzioni su come aggiungere file al progetto Xcode, consulta Gestire file e cartelle nel progetto Xcode.

Utilizza la proprietà BaseOptions.modelAssetPath per specificare il percorso del modello nel tuo app bundle. Per un esempio di codice, consulta la sezione successiva.

Crea l'attività

Puoi creare l'attività Image Segmenter chiamando uno dei relativi inizializzatori. L'inizializzatore ImageSegmenter(options:) accetta i valori per le opzioni di configurazione.

Se non hai bisogno di un segmentatore di immagini inizializzato con opzioni di configurazione personalizzate, puoi utilizzare l'inizializzatore ImageSegmenter(modelPath:) per creare un segmentatore di immagini con le opzioni predefinite. Per ulteriori informazioni sulle opzioni di configurazione, consulta Panoramica della configurazione.

L'attività Segmentazione delle immagini supporta tre tipi di dati di input: immagini fisse, file video e stream video in diretta. Per impostazione predefinita, ImageSegmenter(modelPath:) inizializza un'attività per le immagini fisse. Se vuoi che l'attività venga inizializzata per elaborare file video o stream video in diretta, utilizza ImageSegmenter(options:) per specificare la modalità di esecuzione del video o del live streaming. La modalità live streaming richiede anche l'opzione di configurazione imageSegmenterLiveStreamDelegate aggiuntiva, che consente allo strumento di segmentazione delle immagini di fornire al delegato i risultati di segmentazione delle immagini in modo asincrono.

Scegli la scheda corrispondente alla modalità di esecuzione per scoprire come creare il compito e eseguire l'inferenza.

Swift

Immagine

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

let imageSegmenter = try ImageSegmenter(options: options)
    

Video

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

let imageSegmenter = try ImageSegmenter(options: options)
    

Live streaming

import MediaPipeTasksVision

// Class that conforms to the `imageSegmenterLiveStreamDelegate` protocol and
// implements the method that the image segmenter calls once it finishes
// performing segmentation of each input frame.
class ImageSegmenterResultProcessor: NSObject, ImageSegmenterLiveStreamDelegate {

  func imageSegmenter(
    _ imageSegmenter: ImageSegmenter,
    didFinishSegmentation result: ImageSegmenterResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image segmentation result or errors here.

  }
}

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

// Set `imageSegmenterLiveStreamDelegate` to the object of the class that
// confirms to the `ImageSegmenterLiveStreamDelegate` protocol.
let processor = ImageSegmenterResultProcessor()
options.imageSegmenterLiveStreamDelegate = processor

let imageSegmenter = try ImageSegmenter(options: options)
    

Objective-C

Immagine

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

Video

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

Live streaming

@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageSegmenterLiveStreamDelegate` protocol
// and implements the method that the image segmenter calls once it finishes
// performing segmentation of each input frame.

@interface APPImageSegmenterResultProcessor : NSObject 

@end

@implementation APPImageSegmenterResultProcessor

-   (void)imageSegmenter:(MPPImageSegmenter *)imageSegmenter
    didFinishSegmentationWithResult:(MPPImageSegmenterResult *)imageSegmenterResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the image segmentation result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

// Set `imageSegmenterLiveStreamDelegate` to the object of the class that
// confirms to the `MPPImageSegmenterLiveStreamDelegate` protocol.
APPImageSegmenterResultProcessor *processor =
  [APPImageSegmenterResultProcessor new];
options.imageSegmenterLiveStreamDelegate = processor;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

L'implementazione del codice di esempio di Image Segmenter consente all'utente di passare da una modalità di elaborazione all'altra. L'approccio rende il codice di creazione delle attività più complicato e potrebbe non essere appropriato per il tuo caso d'uso.

Opzioni di configurazione

Questa attività offre le seguenti opzioni di configurazione per le app per iOS:

Nome opzione Descrizione Intervallo di valori Valore predefinito
runningMode Imposta la modalità di esecuzione dell'attività. Esistono tre modalità:

IMMAGINE: la modalità per l'inserimento di singole immagini.

VIDEO: la modalità per i fotogrammi decodificati di un video.

LIVE_STREAM: la modalità per un live streaming di dati di input, ad esempio da una videocamera. In questa modalità, ImageSegmenterLiveStreamDelegate debe essere impostato su un'istanza di una classe che implementa ImageSegmenterLiveStreamDelegate per ricevere i risultati della segmentazione in modo asincrono.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
shouldOutputCategoryMask Se impostato su True, l'output include una maschera di segmentazione come immagine uint8, in cui ogni valore di pixel indica il valore della categoria vincente. {True, False} False
shouldOutputConfidenceMasks Se impostato su True, l'output include una maschera di segmentazione come immagine con valore float, in cui ogni valore float rappresenta la mappa del punteggio di confidenza della categoria. {True, False} True
displayNamesLocale Imposta la lingua delle etichette da utilizzare per i nomi visualizzati forniti nei metadati del modello dell'attività, se disponibile. Il valore predefinito è en per l'inglese. Puoi aggiungere etichette localizzate ai metadati di un modello personalizzato utilizzando l'API TensorFlow Lite Metadata Writer Codice delle impostazioni internazionali it
result_callback Imposta il listener dei risultati in modo da ricevere i risultati della segmentazione in modo asincrono quando il segmento di pubblico delle immagini è in modalità LIVE_STREAM. Può essere utilizzato solo quando la modalità di esecuzione è impostata su LIVE_STREAM N/D N/D

Quando la modalità di esecuzione è impostata su LIVE_STREAM, la segmentazione delle immagini richiede l'opzione di configurazione imageSegmenterLiveStreamDelegate aggiuntiva, che consente alla segmentazione delle immagini di fornire risultati di segmentazione delle immagini in modo asincrono. Il delegato deve implementare il metodo imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:), chiamato dall'Image Segmenter dopo l'elaborazione dei risultati dell'esecuzione della segmentazione su ogni frame.

Nome opzione Descrizione Intervallo di valori Valore predefinito
imageSegmenterLiveStreamDelegate Consente a Image Segmenter di ricevere i risultati dell'esecuzione della segmentazione delle immagini in modo asincrono in modalità live streaming. La classe di cui è impostata l'istanza su questa proprietà deve implementare il metodo imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:). Non applicabile Non impostato

Preparazione dei dati

Devi convertire l'immagine o il frame di input in un oggetto MPImage prima di passarli al Segmenter di immagini. MPImage supporta diversi tipi di formati di immagine iOS e può utilizzarli in qualsiasi modalità di esecuzione per l'inferenza. Per ulteriori informazioni su MPImage, consulta l'API MPImage.

Scegli un formato di immagine iOS in base al tuo caso d'uso e alla modalità di esecuzione richiesta dalla tua applicazione.MPImage accetta i formati di immagine iOS UIImage, CVPixelBuffer e CMSampleBuffer.

UIImage

Il formato UIImage è adatto per le seguenti modalità di esecuzione:

  • Immagini: le immagini di un app bundle, della galleria dell'utente o del file system formattate come immagini UIImage possono essere convertite in un oggetto MPImage.

  • Video: utilizza AVAssetImageGenerator per estrarre i frame video nel formato CGImage, quindi convertili in immagini UIImage.

Swift

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Objective-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

L'esempio inizializza un MPImage con l'orientamento predefinito UIImage.Orientation.Up. Puoi inizializzare un MPImage con uno dei valori supportati di UIImage.Orientation. Lo strumento di segmentazione delle immagini non supporta orientamenti speculari come .upMirrored, .downMirrored, .leftMirrored, .rightMirrored.

Per ulteriori informazioni su UIImage, consulta la documentazione per sviluppatori Apple su UIImage.

CVPixelBuffer

Il formato CVPixelBuffer è adatto per le applicazioni che generano frame e utilizzano il framework CoreImage di iOS per l'elaborazione.

Il formato CVPixelBuffer è adatto alle seguenti modalità di corsa:

  • Immagini: le app che generano immagini CVPixelBuffer dopo un po' di elaborazione utilizzando il framework CVPixelBuffer di iOS possono essere inviate a Image Segmenter in modalità di esecuzione dell'immagine.CoreImage

  • Video: i fotogrammi video possono essere convertiti nel formato CVPixelBuffer per l'elaborazione e poi inviati al segmento di immagini in modalità video.

  • live streaming: le app che utilizzano una fotocamera iOS per generare frame possono essere convertite in formato CVPixelBuffer per l'elaborazione prima di essere inviate al segmentatore di immagini in modalità live streaming.

Swift

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Objective-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

Per ulteriori informazioni su CVPixelBuffer, consulta la documentazione per sviluppatori Apple su CVPixelBuffer.

CMSampleBuffer

Il formato CMSampleBuffer memorizza i sample di media di un tipo uniforme ed è adatto alla modalità di esecuzione del live streaming. I frame in tempo reale delle videocamere iOS vengono caricati in modo asincrono nel formato CMSampleBuffer da AVCaptureVideoDataOutput di iOS.

Swift

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Objective-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

Per ulteriori informazioni su CMSampleBuffer, consulta la documentazione per sviluppatori Apple su CMSampleBuffer.

Esegui l'attività

Per eseguire lo strumento di segmentazione delle immagini, utilizza il metodo segment() specifico per la modalità di esecuzione assegnata:

  • Immagine statica: segment(image:)
  • Video: segment(videoFrame:timestampInMilliseconds:)
  • Live streaming: segmentAsync(image:timestampInMilliseconds:)

I seguenti esempi di codice mostrano esempi semplici di come eseguire Image Segmenter in queste diverse modalità di esecuzione:

Swift

Immagine

let result = try imageSegmenter.segment(image: image)
    

Video

let result = try imageSegmenter.segment(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

Live streaming

try imageSegmenter.segmentAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

Immagine

MPPImageSegmenterResult *result =
  [imageSegmenter segmentImage:image error:nil];
    

Video

MPPImageSegmenterResult *result =
  [imageSegmenter segmentVideoFrame:image
            timestampInMilliseconds:timestamp
                              error:nil];
    

Live streaming

BOOL success =
  [imageSegmenter segmentAsyncImage:image
            timestampInMilliseconds:timestamp
                              error:nil];
    

L'esempio di codice di Image Segmenter mostra le implementazioni di ciascuna di queste modalità in modo più dettagliato segment(image:),segment(videoFrame:timestampInMilliseconds:) esegmentAsync(image:timestampInMilliseconds:).

Tieni presente quanto segue:

  • Quando esegui l'operazione in modalità video o live streaming, devi anche fornire il timestamp del frame di input all'attività di segmentazione delle immagini.

  • Quando è in esecuzione in modalità immagine o video, l'attività Segmentazione delle immagini blocca il thread corrente finché non termina l'elaborazione dell'immagine o del frame di input. Per evitare di bloccare il thread corrente, esegui l'elaborazione in un thread in background utilizzando i framework iOS Dispatch o NSOperation.

  • Quando è in esecuzione in modalità live streaming, l'attività Segmentazione delle immagini restituisce immediatamente e non blocca il thread corrente. Richiama il metodo imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) con il segmentatore di immagini dopo aver elaborato ogni frame di input. Lo strumento di segmentazione delle immagini richiama questo metodo in modo asincrono in una coda di invio seriale dedicata. Per visualizzare i risultati nell'interfaccia utente, inviali alla coda principale dopo averli elaborati. Se la funzione segmentAsync viene chiamata quando l'attività Segmentazione delle immagini è impegnata a elaborare un altro frame, il Segmentatore di immagini ignora il nuovo frame di input.

Gestire e visualizzare i risultati

Dopo l'esecuzione dell'inferenza, l'attività di segmentazione delle immagini restituisce un oggetto ImageSegmenterResult che contiene i risultati dell'attività di segmentazione. I contenuti dell'output dipendono dal tipo di output impostato durante la configurazione dell'attività.

Le seguenti immagini mostrano una visualizzazione dell'output dell'attività per una maschera di valore della categoria. L'intervallo della maschera di categoria è [0, 255] e ogni valore di pixel rappresenta l'indice della categoria vincente dell'output del modello. L'indice della categoria vincente ha il punteggio più alto tra le categorie che il modello può riconoscere.

Output dell'immagine originale e della maschera della categoria. Immagine di origine del set di dati Pascal VOC 2012.

Il codice di esempio di Image Segmenter mostra come visualizzare i risultati di Image Segmenter. Per maggiori dettagli, consulta l'esempio di codice.