ML Kit fornisce un SDK ottimizzato per la segmentazione dei selfie. Gli asset di segmentazione dei selfie sono collegati in modo statico alla tua app al momento della creazione. Ciò aumenterà le dimensioni dell'app fino a 24 MB e la latenza dell'API può variare da ~7 ms a ~12 ms a seconda delle dimensioni dell'immagine di input, misurata su iPhone X.
Prova
- Prova l'app di esempio per per vedere un esempio di utilizzo di questa API.
Prima di iniziare
Includi le seguenti librerie di ML Kit nel podfile:
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando il file .
xcworkspace
. ML Kit è supportato in Xcode versione 13.2.1 o successiva.
1. Crea un'istanza dello strumento di segmentazione
Per eseguire la segmentazione su un'immagine selfie, crea prima un'istanza di Segmenter
con SelfieSegmenterOptions
e, facoltativamente, specifica le impostazioni di segmentazione.
Opzioni di segmentazione
Modalità di segmentazione
Il Segmenter
funziona in due modalità. Assicurati di scegliere quello adatto al tuo caso d'uso.
STREAM_MODE (default)
Questa modalità è progettata per lo streaming di fotogrammi da video o dalla videocamera. In questa modalità, lo strumento di segmentazione sfrutta i risultati dei frame precedenti per restituire risultati di segmentazione più fluidi.
SINGLE_IMAGE_MODE (default)
Questa modalità è progettata per singole immagini non correlate. In questa modalità, il segmentatore elabora ogni immagine in modo indipendente, senza smussare i fotogrammi.
Attiva maschera dimensioni non elaborate
Chiede al segmentatore di restituire la maschera delle dimensioni non elaborate che corrisponde alla dimensione di output del modello.
Le dimensioni della maschera non elaborata (ad es. 256 x 256) sono generalmente inferiori a quelle dell'immagine di input.
Senza specificare questa opzione, il segmentatore ridimensiona la maschera non elaborata per corrispondere alle dimensioni dell'immagine di input. Valuta la possibilità di utilizzare questa opzione se vuoi applicare una logica di ridimensionamento personalizzata o se il ridimensionamento non è necessario per il tuo caso d'uso.
Specifica le opzioni dello strumento di segmentazione:
Swift
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Objective-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
Infine, ottieni un'istanza di Segmenter
. Trasmetti le opzioni che hai specificato:
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Prepara l'immagine di input
Per segmentare i selfie, procedi nel seguente modo per ogni immagine o fotogramma del video.
Se hai abilitato la modalità flusso di dati, devi creare VisionImage
oggetti da
CMSampleBuffer
Crea un oggetto VisionImage
utilizzando un UIImage
o un
CMSampleBuffer
.
Se usi un UIImage
, segui questi passaggi:
- Crea un oggetto
VisionImage
conUIImage
. 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 metodoCMSampleBuffer
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. Elabora l'immagine
Passa l'oggetto VisionImage
a uno dei metodi di elaborazione delle immagini di Segmenter
. Puoi utilizzare il metodo process(image:)
asincrono o il metodo sincrono results(in:)
.
Per eseguire la segmentazione su un'immagine selfie in modo sincrono:
Swift
var mask: [SegmentationMask] do { mask = try segmenter.results(in: image) } catch let error { print("Failed to perform segmentation with error: \(error.localizedDescription).") return } // Success. Get a segmentation mask here.
Objective-C
NSError *error; MLKSegmentationMask *mask = [segmenter resultsInImage:image error:&error]; if (error != nil) { // Error. return; } // Success. Get a segmentation mask here.
Per eseguire la segmentazione su un'immagine selfie in modo asincrono:
Swift
segmenter.process(image) { mask, error in guard error == nil else { // Error. return } // Success. Get a segmentation mask here.
Objective-C
[segmenter processImage:image completion:^(MLKSegmentationMask * _Nullable mask, NSError * _Nullable error) { if (error != nil) { // Error. return; } // Success. Get a segmentation mask here. }];
4. Ottieni la maschera di segmentazione
Ecco i risultati della segmentazione:
Swift
let maskWidth = CVPixelBufferGetWidth(mask.buffer) let maskHeight = CVPixelBufferGetHeight(mask.buffer) CVPixelBufferLockBaseAddress(mask.buffer, CVPixelBufferLockFlags.readOnly) let maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer) var maskAddress = CVPixelBufferGetBaseAddress(mask.buffer)!.bindMemory( to: Float32.self, capacity: maskBytesPerRow * maskHeight) for _ in 0...(maskHeight - 1) { for col in 0...(maskWidth - 1) { // Gets the confidence of the pixel in the mask being in the foreground. let foregroundConfidence: Float32 = maskAddress[col] } maskAddress += maskBytesPerRow / MemoryLayout<Float32>.size }
Objective-C
size_t width = CVPixelBufferGetWidth(mask.buffer); size_t height = CVPixelBufferGetHeight(mask.buffer); CVPixelBufferLockBaseAddress(mask.buffer, kCVPixelBufferLock_ReadOnly); size_t maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer); float *maskAddress = (float *)CVPixelBufferGetBaseAddress(mask.buffer); for (int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { // Gets the confidence of the pixel in the mask being in the foreground. float foregroundConfidence = maskAddress[col]; } maskAddress += maskBytesPerRow / sizeof(float); }
Per un esempio completo di come utilizzare i risultati della segmentazione, consulta la Esempio di guida rapida di ML Kit.
Suggerimenti per migliorare il rendimento
La qualità dei risultati dipende dalla qualità dell'immagine di input:
- Affinché ML Kit ottenga un risultato di segmentazione accurato, l'immagine deve essere di almeno 256 x 256 pixel.
- Se esegui la segmentazione selfie in un'applicazione in tempo reale, potresti anche prendere in considerazione le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più velocemente. Di conseguenza, per ridurre la latenza, acquisisci immagini a risoluzioni più basse, ma tieni presente i requisiti di risoluzione di cui sopra e assicurati che il soggetto occupi la maggior quantità possibile di immagini.
- Anche una scarsa messa a fuoco dell'immagine può influire sulla precisione. Se non ottieni risultati accettabili, chiedi all'utente di recuperare l'immagine.
Se vuoi utilizzare la segmentazione in un'applicazione in tempo reale, segui queste linee guida per ottenere le migliori frequenze fotogrammi:
- Usa la modalità di segmentazione
stream
. - Prova ad acquisire immagini a una risoluzione inferiore. Tuttavia, tieni presente anche i requisiti relativi alle dimensioni immagine di questa API.
- Per elaborare i fotogrammi video, utilizza l'API sincrona
results(in:)
dello strumento di segmentazione. Richiama questo metodo dalla funzione captureOutput(_, didOutput:from:) di AVCaptureVideoDataOutputSampleBufferDelegate per ottenere in modo sincrono i risultati dal frame video specificato. Mantieni l'elemento alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput per limitare le chiamate al segmentatore. Se diventa disponibile un nuovo fotogramma video mentre lo strumento di segmentazione è in esecuzione, questo verrà eliminato. - Se utilizzi l'output dello strumento di segmentazione per sovrapporre elementi grafici all'immagine di input, ottieni il risultato da ML Kit, quindi esegui il rendering dell'immagine e della sovrapposizione in un unico passaggio. In questo modo, il rendering sulla superficie di visualizzazione viene eseguito una sola volta per ogni frame di input elaborato. Per un esempio, vedi le classi previewOverlayView e CameraViewController nell'esempio della guida rapida di ML Kit.