ML Kit, selfie segmentasyonu için optimize edilmiş bir SDK sunar. Selfie Segmenter öğeleri, derleme sırasında statik olarak uygulamanıza bağlıdır. Bu işlem, uygulamanızın boyutunu 24 MB'a kadar artırır. iPhone X'te yapılan ölçüme göre giriş görüntüsü boyutuna bağlı olarak API gecikmesi yaklaşık 7 ms ile ~12 ms. arasında değişebilir.
Deneyin
- Bu API'nin örnek bir kullanımını görmek için örnek uygulamayı inceleyin.
Başlamadan önce
Aşağıdaki ML Kit kitaplıklarını Podfile dosyanıza ekleyin:
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
Projenizin Kapsüllerini yükledikten veya güncelledikten sonra Xcode projenizi .
xcworkspace
ile açın. ML Kit, Xcode sürüm 13.2.1 veya üzeri sürümlerde desteklenir.
1. Segmenter örneği oluşturma
Selfie görüntüsü üzerinde segmentasyon yapmak için önce SelfieSegmenterOptions
ile bir Segmenter
örneği oluşturun ve isteğe bağlı olarak segmentasyon ayarlarını belirtin.
Segmenter seçenekleri
Segmenter Modu
Segmenter
iki modda çalışır. Kullanım alanınıza uygun olanı seçtiğinizden emin olun.
STREAM_MODE (default)
Bu mod, video veya kameradan kare akışı gerçekleştirmek için tasarlanmıştır. Segmenter, bu modda daha düzgün segmentasyon sonuçları döndürmek için önceki karelerden elde edilen sonuçlardan yararlanır.
SINGLE_IMAGE_MODE (default)
Bu mod, birbiriyle alakalı olmayan tek resimler için tasarlanmıştır. Bu modda segmentleyici, kareler üzerinde yumuşatma olmadan her resmi bağımsız olarak işler.
Ham boyut maskesini etkinleştir
Segmentleyiciden, model çıktı boyutuyla eşleşen ham boyut maskesini döndürmesini ister.
İşlenmemiş maske boyutu (ör. 256x256) genellikle giriş resmi boyutundan daha küçüktür.
Bu seçeneği belirtmezseniz segmentleyici, ham maskeyi giriş resmi boyutuyla eşleşecek şekilde yeniden ölçeklendirir. Özelleştirilmiş yeniden ölçeklendirme mantığı uygulamak istiyorsanız veya kullanım alanınız için yeniden ölçeklendirme gerekmiyorsa bu seçeneği kullanabilirsiniz.
Segmenter seçeneklerini belirtin:
Swift
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Objective-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
Son olarak, Segmenter
örneği alın. Belirttiğiniz seçenekleri iletin:
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Giriş görüntüsünü hazırlama
Selfie'leri segmentlere ayırmak için her bir resim veya video karesinde aşağıdakileri yapın.
Akış modunu etkinleştirdiyseniz CMSampleBuffer
kaynağından VisionImage
nesne oluşturmanız gerekir.
UIImage
veya CMSampleBuffer
kullanarak VisionImage
nesnesi oluşturun.
UIImage
kullanıyorsanız şu adımları uygulayın:
UIImage
ile birVisionImage
nesnesi oluşturun. Doğru.orientation
değerini belirttiğinizden emin olun.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
CMSampleBuffer
kullanıyorsanız şu adımları uygulayın:
-
CMSampleBuffer
içinde yer alan resim verilerinin yönünü belirtin.Resmin yönünü belirlemek için:
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; } }
CMSampleBuffer
nesnesini ve yönünü kullanarak birVisionImage
nesnesi oluşturun: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. Resmi işle
VisionImage
nesnesini, Segmenter
öğesinin resim işleme yöntemlerinden birine geçirin. Eşzamansız process(image:)
yöntemini veya eşzamanlı results(in:)
yöntemini kullanabilirsiniz.
Bir selfie görüntüsü üzerinde eşzamanlı olarak segmentasyon yapmak için:
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.
Bir selfie görüntüsü üzerinde eşzamansız olarak segmentasyon yapmak için:
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. Segmentasyon maskesini alın
Segmentasyon sonucunu aşağıdaki şekilde alabilirsiniz:
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); }
Segmentasyon sonuçlarının nasıl kullanılacağına dair tam bir örnek için lütfen ML Kit hızlı başlangıç örneğine bakın.
Performansı artırmaya yönelik ipuçları
Sonuçlarınızın kalitesi, giriş görüntüsünün kalitesine bağlıdır:
- ML Kit'in doğru bir segmentasyon sonucu alabilmesi için görüntü en az 256x256 piksel olmalıdır.
- Selfie segmentasyonunu gerçek zamanlı bir uygulamada gerçekleştiriyorsanız, giriş resimlerinin genel boyutlarını da göz önünde bulundurmak isteyebilirsiniz. Küçük resimler daha hızlı işlenebilir, bu nedenle gecikmeyi azaltmak için düşük çözünürlüklerde görüntü yakalayın ancak yukarıdaki çözünürlük gereksinimlerini göz önünde bulundurun ve öznenin, resmi olabildiğince çok kapladığından emin olun.
- Kötü resim odağı, doğruluğu da etkileyebilir. Kabul edilebilir sonuçlar alamazsanız kullanıcıdan resmi yeniden çekmesini isteyin.
Segmentasyonu gerçek zamanlı bir uygulamada kullanmak istiyorsanız en iyi kare hızlarını elde etmek için şu yönergeleri uygulayın:
stream
segmenter modunu kullanın.- Daha düşük çözünürlükte resimler çekmeyi deneyin. Ancak, bu API'nin resim boyutu koşullarını da göz önünde bulundurun.
- Video karelerini işlemek için segmentleyicinin
results(in:)
eşzamanlı API'sini kullanın. Belirli bir video karesinden eşzamanlı olarak sonuçlar almak için AVCaptureVideoDataOutputSampleBufferDelegate'in captureOutput(_, didOutput:from:) işlevinden bu yöntemi çağırın. Segmente çağrılarını kısıtlamak için AVCaptureVideoDataOutput'ın alwaysDiscardsLateVideoFrames öğelerini doğru tutun. Segmenter çalışırken yeni bir video karesi kullanılabilir hale gelirse atlanır. - Segmentörün çıktısını giriş görüntüsündeki grafikleri bindirmek için kullanıyorsanız önce ML Kit'ten sonucu alın, ardından görüntüyü ve bindirmeyi tek bir adımda oluşturun. Böylece, işlenen her giriş çerçevesi için görüntü yüzeyinde yalnızca bir kez görüntü oluşturursunuz. Örnek için ML Kit hızlı başlangıç örneğindeki previewOverlayView ve CameraViewController sınıflarına bakın.