ML Kiti, selfie segmentasyonu için optimize edilmiş bir SDK sunar. Selfie Segmenter öğeleri, derleme sırasında uygulamanıza statik olarak bağlanır. Bu işlem, uygulamanızın boyutunu 24 MB'a kadar artırır ve API gecikmesi, iPhone X'te ölçüldüğü üzere giriş resminin boyutuna bağlı olarak yaklaşık 7 ms ile yaklaşık 12 ms arasında değişebilir.
Deneyin
- Bu API'nin örnek kullanımını görmek için örnek uygulamayı deneyin.
Başlamadan önce
Podfile'ınıza aşağıdaki ML Kiti kitaplıklarını ekleyin:
pod 'GoogleMLKit/SegmentationSelfie', '8.0.0'Projenizin Pod'larını yükledikten veya güncelledikten sonra .
xcworkspacekullanarak Xcode projenizi açın. ML Kiti, Xcode 13.2.1 veya sonraki sürümlerde desteklenir.
1. Segmenter örneği oluşturma
Selfie resminde segmentasyon yapmak için önce SelfieSegmenterOptions ile bir Segmenter örneği oluşturun ve isteğe bağlı olarak segmentasyon ayarlarını belirtin.
Segmentasyon aracı 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ışı yapmak için tasarlanmıştır. Bu modda segmenter, daha akıcı segmentasyon sonuçları döndürmek için önceki karelerden elde edilen sonuçlardan yararlanır.
SINGLE_IMAGE_MODE (default)
Bu mod, birbiriyle ilişkili olmayan tekli resimler için tasarlanmıştır. Bu modda segmenter, her resmi bağımsız olarak işler ve kareler üzerinde yumuşatma yapmaz.
Ham boyut maskesini etkinleştirme
Segmentasyon aracından, model çıkış boyutuyla eşleşen ham boyut maskesini döndürmesini ister.
Ham maske boyutu (ör. 256x256) genellikle giriş resmi boyutundan daha küçüktür.
Bu seçenek belirtilmezse segmenter, 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.
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 resim veya video karesinde aşağıdaki işlemleri yapın.
Akış modunu etkinleştirdiyseniz CMSampleBuffer'lerden VisionImage nesneleri oluşturmanız gerekir.
UIImage veya CMSampleBuffer kullanarak bir VisionImage nesnesi oluşturun.
UIImage kullanıyorsanız aşağıdaki adımları uygulayın:
UIImageile birVisionImagenesnesi oluşturun. Doğru.orientationdeğ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 aşağıdaki adımları uygulayın:
-
CMSampleBufferiçinde bulunan resim verilerinin yönünü belirtin.Resim yönünü öğrenmek 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; } }
CMSampleBuffernesnesini ve yönü kullanarak birVisionImagenesnesi 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 sınıfının görüntü işleme yöntemlerinden birine iletin. Eşzamansız process(image:) yöntemini veya eşzamanlı results(in:) yöntemini kullanabilirsiniz.
Selfie resminde 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.
Selfie resminde 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 alma
Segmentasyon sonucunu aşağıdaki gibi 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 Kiti 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 edebilmesi için resmin en az 256x256 piksel olması gerekir.
- Selfie segmentasyonunu gerçek zamanlı bir uygulamada gerçekleştiriyorsanız giriş resimlerinin genel boyutlarını da göz önünde bulundurmanız önerilir. Daha küçük resimler daha hızlı işlenebilir. Bu nedenle, gecikmeyi azaltmak için resimleri daha düşük çözünürlüklerde ç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 kısmını kapladığından emin olun.
- Resim odağının kötü olması da doğruluğu 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 aşağıdaki yönergeleri uygulayın:
streamsegmenter modunu kullanın.- Görüntüleri daha düşük çözünürlükte yakalamayı 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:)eşzamanlı API'sini kullanın. Belirli bir video karesinden eşzamanlı olarak sonuç almak için bu yöntemi AVCaptureVideoDataOutputSampleBufferDelegate'in captureOutput(_, didOutput:from:) işlevinden çağırın. Segmenter çağrılarını kısıtlamak için AVCaptureVideoDataOutput'un alwaysDiscardsLateVideoFrames değerini doğru olarak ayarlayın. Segmenter çalışırken yeni bir video karesi kullanılabilir hale gelirse bu kare silinir. - Segmentasyon aracının çıkışını, giriş görüntüsünün üzerine grafik yerleştirmek için kullanıyorsanız önce ML Kit'ten sonucu alın, ardından görüntüyü ve yer paylaşımını tek bir adımda oluşturun. Böylece, işlenen her giriş karesi için görüntüleme yüzeyine yalnızca bir kez 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.