ML Kit bietet ein optimiertes SDK für die Segmentierung von Selfies. Die Assets des Selfie-Segmenters werden bei der Buildzeit statisch mit Ihrer App verknüpft. Dadurch erhöht sich die App-Größe um bis zu 24 MB und die API-Latenz kann je nach Größe des Eingabebilds von etwa 7 ms bis etwa 12 ms variieren, gemessen auf dem iPhone X.
Jetzt ausprobieren
- In der Beispielanwendung sehen Sie ein Beispiel für die Verwendung dieser API.
Hinweis
Fügen Sie Ihrer Podfile-Datei die folgenden ML Kit-Bibliotheken hinzu:
pod 'GoogleMLKit/SegmentationSelfie', '8.0.0'
Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie Ihr Xcode-Projekt mit der
xcworkspace
-Datei. ML Kit wird in Xcode-Version 13.2.1 oder höher unterstützt.
1. Instanz von Segmenter erstellen
Wenn Sie eine Segmentierung für ein Selfie-Bild ausführen möchten, erstellen Sie zuerst eine Instanz von Segmenter
mit SelfieSegmenterOptions
und geben Sie optional die Segmentierungseinstellungen an.
Segmentierungsoptionen
Segmentiermodus
Der Segmenter
kann in zwei Modi betrieben werden. Achten Sie darauf, die Option auszuwählen, die zu Ihrem Anwendungsfall passt.
STREAM_MODE (default)
Dieser Modus ist für das Streaming von Frames aus einem Video oder einer Kamera konzipiert. In diesem Modus nutzt der Segmentierungsalgorithmus Ergebnisse aus vorherigen Frames, um glattere Segmentierungsergebnisse zurückzugeben.
SINGLE_IMAGE_MODE (default)
Dieser Modus ist für einzelne Bilder gedacht, die nicht zusammenhängen. In diesem Modus verarbeitet der Segmenter jedes Bild unabhängig voneinander, ohne Glättung über Frames hinweg.
Maske für Rohgröße aktivieren
Der Segmentierer wird aufgefordert, die Rohgrößenmaske zurückzugeben, die der Modellausgabegröße entspricht.
Die Größe der Rohmaske (z.B. 256 x 256) ist in der Regel kleiner als die Größe des Eingabebilds.
Wenn Sie diese Option nicht angeben, skaliert der Segmentierungsalgorithmus die Rohmaske so, dass sie der Größe des Eingabebilds entspricht. Verwenden Sie diese Option, wenn Sie eine benutzerdefinierte Logik für die Neuberechnung anwenden möchten oder die Neuberechnung für Ihren Anwendungsfall nicht erforderlich ist.
Geben Sie die Segmentierungsoptionen an:
Swift
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Objective-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
Rufen Sie abschließend eine Instanz von Segmenter
ab. Übergeben Sie die von Ihnen angegebenen Optionen:
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Eingabebild vorbereiten
Wenn Sie Selfies segmentieren möchten, gehen Sie für jedes Bild oder jeden Videoframe so vor:
Wenn Sie den Stream-Modus aktiviert haben, müssen Sie VisionImage
-Objekte aus CMSampleBuffer
-Objekten erstellen.
Erstellen Sie ein VisionImage
-Objekt mit einem UIImage
oder einem CMSampleBuffer
.
Wenn Sie ein UIImage
verwenden, gehen Sie so vor:
- Erstellen Sie ein
VisionImage
-Objekt mit demUIImage
. Achten Sie darauf, die richtige.orientation
anzugeben.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Wenn Sie ein CMSampleBuffer
verwenden, gehen Sie so vor:
-
Geben Sie die Ausrichtung der Bilddaten an, die in
CMSampleBuffer
enthalten sind.So rufen Sie die Bildausrichtung auf:
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; } }
- Erstellen Sie ein
VisionImage
-Objekt mit demCMSampleBuffer
-Objekt und der Ausrichtung: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. Bild verarbeiten
Übergeben Sie das VisionImage
-Objekt an eine der Bildverarbeitungsmethoden von Segmenter
. Sie können entweder die asynchrone Methode process(image:)
oder die synchrone Methode results(in:)
verwenden.
So führen Sie eine synchrone Segmentierung für ein Selfie durch:
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.
So führen Sie eine asynchrone Segmentierung eines Selfies durch:
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. Segmentierungsmaske abrufen
So rufen Sie das Segmentierungsergebnis ab:
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); }
Ein vollständiges Beispiel für die Verwendung der Segmentierungsergebnisse finden Sie im Beispiel für die ML Kit-Kurzanleitung.
Tipps zur Leistungsverbesserung
Die Qualität der Ergebnisse hängt von der Qualität des Eingabebilds ab:
- Damit ML Kit ein genaues Segmentierungsergebnis liefern kann, muss das Bild mindestens 256 × 256 Pixel groß sein.
- Wenn Sie die Selfie-Segmentierung in einer Echtzeitanwendung ausführen, sollten Sie auch die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Um die Latenz zu verringern, sollten Sie Bilder mit niedrigerer Auflösung aufnehmen. Beachten Sie dabei jedoch die oben genannten Auflösungsanforderungen und achten Sie darauf, dass das Motiv möglichst viel Platz im Bild einnimmt.
- Auch ein unscharfer Bildfokus kann sich auf die Genauigkeit auswirken. Wenn Sie keine zufriedenstellenden Ergebnisse erhalten, bitten Sie den Nutzer, das Bild noch einmal aufzunehmen.
Wenn Sie die Segmentierung in einer Echtzeitanwendung verwenden möchten, beachten Sie die folgenden Richtlinien, um die besten Frameraten zu erzielen:
- Verwenden Sie den Segmentierungsmodus
stream
. - Sie können auch Bilder mit niedrigerer Auflösung aufnehmen. Beachten Sie jedoch auch die Anforderungen an die Bildabmessungen dieser API.
- Verwenden Sie für die Verarbeitung von Videoframes die synchrone
results(in:)
API des Segmentierungstools. Rufen Sie diese Methode über die Funktion captureOutput(_, didOutput:from:) des AVCaptureVideoDataOutputSampleBufferDelegate auf, um synchron Ergebnisse aus dem angegebenen Videoframe abzurufen. Lassen Sie alwaysDiscardsLateVideoFrames von AVCaptureVideoDataOutput auf „true“ gesetzt, um Aufrufe an den Segmenter zu drosseln. Wenn während der Ausführung des Segmentierungstools ein neuer Videoframe verfügbar wird, wird er verworfen. - Wenn Sie die Ausgabe des Segmentierungstools verwenden, um Grafiken auf das Eingabebild zu legen, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern Sie dann das Bild und das Overlay in einem einzigen Schritt. So wird für jeden verarbeiteten Eingabeframe nur einmal auf die Displayoberfläche gerendert. Ein Beispiel finden Sie in den Klassen previewOverlayView und CameraViewController im ML Kit-Beispiel für den Schnellstart.