ML Kit fournit un SDK optimisé pour la segmentation par selfie. Les composants du segment de selfie sont associés de manière statique à votre application au moment de la compilation. La taille de votre application peut atteindre 24 Mo. La latence de l'API peut varier d'environ 7 ms à 12 ms en fonction de la taille de l'image d'entrée (mesurée sur l'iPhone X).
Essayer
- Testez l'application exemple pour : consultez un exemple d'utilisation de cette API.
Avant de commencer
Incluez les bibliothèques ML Kit suivantes dans votre Podfile:
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode à l'aide du fichier .
xcworkspace
. ML Kit est compatible avec Xcode 13.2.1 ou version ultérieure.
1. Créer une instance de Segmenter
Pour effectuer une segmentation sur une image de selfie, créez d'abord une instance de Segmenter
avec SelfieSegmenterOptions
. Vous pouvez également spécifier les paramètres de segmentation.
Options du segmenteur
Mode Segmenter
Segmenter
fonctionne dans deux modes. Veillez à choisir celle qui correspond à votre cas d'utilisation.
STREAM_MODE (default)
Ce mode est conçu pour diffuser les images de la vidéo ou de la caméra. Dans ce mode, le segmenteur exploite les résultats des frames précédents pour renvoyer des résultats de segmentation plus fluides.
SINGLE_IMAGE_MODE (default)
Ce mode est conçu pour les images uniques qui ne sont pas liées. Dans ce mode, le segmenteur traite chaque image indépendamment, sans lissage sur les images.
Activer le masque de taille brute
Il demande au segmenteur de renvoyer le masque de taille brute qui correspond à la taille de sortie du modèle.
La taille du masque brut (par exemple, 256 x 256) est généralement inférieure à la taille de l'image d'entrée.
Si vous ne spécifiez pas cette option, le segmenteur redimensionne le masque brut pour qu'il corresponde à la taille de l'image d'entrée. Utilisez cette option si vous souhaitez appliquer une logique de rescaling personnalisée ou si le redimensionnement n'est pas nécessaire pour votre cas d'utilisation.
Spécifiez les options du segmenteur:
Swift
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Objective-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
Enfin, récupérez une instance de Segmenter
. Transmettez les options que vous avez spécifiées:
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Préparer l'image d'entrée
Pour segmenter des selfies, procédez comme suit pour chaque image ou cadre de la vidéo.
Si vous avez activé le mode de traitement par flux, vous devez créer des objets VisionImage
à partir de
CMSampleBuffer
.
Créez un objet VisionImage
à l'aide d'un UIImage
ou d'un
CMSampleBuffer
Si vous utilisez un UIImage
, procédez comme suit:
- Créez un objet
VisionImage
avecUIImage
. Veillez à spécifier le bon.orientation
.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 la méthode ObjetCMSampleBuffer
et 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];
3. Traiter l'image
Transmettez l'objet VisionImage
à l'une des méthodes de traitement d'image de Segmenter
. Vous pouvez utiliser la méthode process(image:)
asynchrone ou la méthode results(in:)
synchrone.
Pour effectuer la segmentation d'une image de selfie de manière synchrone:
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.
Pour segmenter une image de selfie de manière asynchrone:
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. Obtenir le masque de segmentation
Vous pouvez obtenir le résultat de la segmentation comme suit:
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); }
Pour obtenir un exemple complet d'utilisation des résultats de segmentation, consultez la Exemple de démarrage rapide avec ML Kit
Conseils pour améliorer les performances
La qualité des résultats dépend de la qualité de l'image d'entrée:
- Pour que ML Kit obtienne un résultat de segmentation précis, l'image doit faire au moins 256 x 256 pixels.
- Si vous effectuez une segmentation par selfie dans une application en temps réel, vous pouvez également tenir compte des dimensions globales des images d'entrée. Les images de petite taille peuvent être traitées plus rapidement. Par conséquent, pour réduire la latence, capturez des images à des résolutions inférieures, mais gardez à l'esprit les exigences de résolution ci-dessus et assurez-vous que le sujet occupe le plus de place possible dans l'image.
- Une mauvaise mise au point de l'image peut également nuire à sa précision. Si les résultats ne sont pas satisfaisants, demandez à l'utilisateur de reprendre l'image.
Si vous souhaitez utiliser la segmentation dans une application en temps réel, suivez ces consignes pour obtenir les meilleures fréquences d'images:
- Utilisez le mode segmenteur
stream
. - Envisagez de capturer des images à une résolution plus faible. Cependant, gardez également à l'esprit les exigences de cette API concernant les dimensions de l'image.
- Pour traiter les images vidéo, utilisez l'API synchrone
results(in:)
du segmenteur. Appelez cette méthode depuis la fonction AVCaptureVideoDataOutputSampleBufferDelegate de captureOutput(_, didOutput:from:) pour obtenir des résultats de manière synchrone à partir de l'image vidéo donnée. Laissez la valeur alwaysDiscardsLateVideoFrames de AVCaptureVideoDataOutput définie sur "true" afin de limiter les appels au segmenteur. Si une nouvelle image vidéo devient disponible pendant que le segmenteur s'exécute, elle sera ignorée. - Si vous utilisez la sortie du segmenteur 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. Ainsi, vous n'effectuez le rendu sur la surface d'affichage qu'une seule fois pour chaque image d'entrée traitée. Consultez les classes previewOverlayView et CameraViewController dans l'exemple de démarrage rapide de ML Kit pour obtenir un exemple.