ML Kit, selfie segmentasyonu için optimize edilmiş bir SDK sağlar. Selfie Segmenter öğeleri, derleme sırasında uygulamanıza statik olarak bağlanır. Bu işlem, uygulama boyutunuzu 24 MB'a kadar artırır. API gecikmesi, iPhone X'te ölçüldüğü üzere giriş resminin boyutuna bağlı olarak yaklaşık 7 ms ile 12 ms arasında değişebilir.
Deneyin
- Bu API'nin kullanımına dair bir örnek görmek için örnek uygulamayı inceleyin.
Başlamadan önce
Podfile'ınıza aşağıdaki ML Kit kitaplıklarını ekleyin:
pod 'GoogleMLKit/SegmentationSelfie', '8.0.0'
Projenizin Pod'larını yükledikten veya güncelledikten sonra, .
xcworkspace
uzantılı dosyayı kullanarak Xcode projenizi açın. ML Kit, Xcode 13.2.1 veya sonraki sürümlerinde desteklenir.
1. Segmenter örneği oluşturma
Bir selfie resminde segmentasyon gerçekleştirmek için önce Segmenter
ile SelfieSegmenterOptions
örneğini 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, videodan veya kameradan kareler yayınlamak için tasarlanmıştır. Bu modda, segmentleyici daha sorunsuz segmentasyon sonuçları döndürmek için önceki karelerdeki sonuçlardan yararlanır.
SINGLE_IMAGE_MODE (default)
Bu mod, birbiriyle ilişkili olmayan tek resimler için tasarlanmıştır. Bu modda segmentleyici, her resmi bağımsız olarak işler ve kareler arasında yumuşatma yapmaz.
Ham boyut maskesini etkinleştirme
Segmenter'dan, model çıkış boyutuyla eşleşen ham boyut maskesini döndürmesini ister.
Ham maske boyutu (ör. 256x256) genellikle giriş resmi boyutundan küçüktür.
Bu seçenek belirtilmediğinde, segmentleyici ham maskeyi giriş resmi boyutuna uyacak ş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.
Segmentleyici 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ğini alın. Belirttiğiniz seçenekleri iletin:
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Giriş resmini hazırlama
Selfie'leri segmentlere ayırmak için her görüntü veya video karesi için aşağıdakileri yapın.
Akış modunu etkinleştirdiyseniz CMSampleBuffer
öğelerinden VisionImage
nesneleri oluşturmanız gerekir.
UIImage
veya CMSampleBuffer
kullanarak VisionImage
nesnesi oluşturun.
UIImage
kullanıyorsanız şu adımları uygulayın:
UIImage
ileVisionImage
nesnesi oluşturun. Doğru.orientation
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.Resim yönünü almak 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ü kullanarakVisionImage
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şleme
VisionImage
nesnesini Segmenter
'nin resim işleme yöntemlerinden birine iletin. Eşzamansız process(image:)
yöntemini veya eşzamanlı results(in:)
yöntemini kullanabilirsiniz.
Bir selfie görüntüsünde segmentasyonu eşzamanlı olarak gerçekleştirmek 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ünde segmentasyonu eşzamansız olarak gerçekleştirmek 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 alma
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ş resminin kalitesine bağlıdır:
- ML Kit'in doğru bir segmentasyon sonucu elde etmesi için resim en az 256x256 piksel olmalıdır.
- Gerçek zamanlı bir uygulamada özne segmentasyonu yapıyorsanız giriş resimlerinin genel boyutlarını da göz önünde bulundurmanız gerekebilir. Daha küçük resimler daha hızlı işlenebilir. Bu nedenle, gecikmeyi azaltmak için daha düşük çözünürlüklerde resim çekin ancak yukarıdaki çözünürlük şartlarını göz önünde bulundurun ve öznenin resmin mümkün olduğunca büyük bir bölümünü kapladığından emin olun.
- Resmin iyi odaklanmaması da doğruluğu etkileyebilir. Kabul edilebilir sonuçlar almazsanı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 aşağıdaki yönergeleri uygulayın:
stream
segmentleyici modunu kullanın.- Görüntüleri daha düşük çözünürlükte çekmeyi deneyin. Ancak bu API'nin resim boyutu koşullarını da göz önünde bulundurun.
- Video karelerini işlemek için segmenter'ın
results(in:)
senkron API'sini kullanın. Belirli bir video karesinden sonuçları senkron olarak almak için bu yöntemi AVCaptureVideoDataOutputSampleBufferDelegate'in captureOutput(_, didOutput:from:) işlevinden çağırın. Segmentleyiciye yapılan çağrıları sınırlamak için AVCaptureVideoDataOutput'un alwaysDiscardsLateVideoFrames özelliğini true olarak tutun. Segmentleyici çalışırken yeni bir video karesi kullanıma sunulursa bu kare bırakılır. - Giriş resmine grafik yerleştirmek için segmenter'ın çıkışını kullanıyorsanız önce ML Kit'ten sonucu alın, ardından resmi ve yerleşimi tek adımda oluşturun. Bunu yaparak, işlenen her giriş karesi için yalnızca bir kez görüntüleme yüzeyine oluşturma işlemi yaparsınız. Örnek için ML Kit hızlı başlangıç örneğindeki previewOverlayView ve CameraViewController sınıflarına bakın.