ML Kit, selfie segmentasyonu için optimize edilmiş bir SDK sunar. Selfie Segmenter öğeleri, derleme sırasında uygulamanıza statik olarak bağlıdır. Bu işlem, uygulamanızın boyutunu 24 MB'a kadar artırır. iPhone X'te yapılan ölçümlere göre, giriş resminin boyutuna bağlı olarak API gecikmesi ~7 ms. ile ~12 ms. arasında değişebilir.
Deneyin
- Örnek uygulamayı kullanarak bu API'nin örnek kullanımını inceleyin.
Başlamadan önce
Aşağıdaki ML Kit kitaplıklarını Podfile'ınıza ekleyin:
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
Projenizin kapsüllerini yükledikten veya güncelledikten sonra .
xcworkspace
uzantısını kullanarak Xcode projenizi açın. Makine Öğrenimi Kiti, Xcode 13.2.1 veya üzeri sürümlerde desteklenir.
1. Segmenter örneği oluşturma
Bir selfie görüntüsünde segmentasyon yapmak için önce SelfieSegmenterOptions
ile 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 seçeneği seçtiğinizden emin olun.
STREAM_MODE (default)
Bu mod, video veya kameradan kare akışı gerçekleştirmek için tasarlanmıştır. Bu modda segmenter, daha yumuşak segmentasyon sonuçları döndürmek için önceki karelerin sonuçlarından yararlanır.
SINGLE_IMAGE_MODE (default)
Bu mod, alakalı olmayan tek resimler için tasarlanmıştır. Bu modda, segmentleyici her resmi kareler üzerinde yumuşatma olmadan bağımsız olarak işler.
Ham boyut maskesini etkinleştir
Segmenterden, model çıkış boyutuyla eşleşen işlenmemiş boyut maskesini döndürmesini ister.
İşlenmemiş maske boyutu (ör. 256x256) genellikle giriş resminin boyutundan küçüktür.
Bu seçenek belirtilmediğinde, 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
öğesinin bir ö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 resim veya video karesi için aşağıdakileri yapın.
Akış modunu etkinleştirdiyseniz şuradan VisionImage
nesne oluşturmanız gerekir:
CMSampleBuffer
sn.
Bir VisionImage
nesnesi oluşturmak için UIImage
veya
CMSampleBuffer
.
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:
-
Belgenin
CMSampleBuffer
Resmin 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; } }
- Şu komutu kullanarak bir
VisionImage
nesnesi oluşturun:CMSampleBuffer
nesne ve yön: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şleyin
VisionImage
nesnesini, Segmenter
öğesinin görüntü 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 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ünde 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 Kit hızlı başlangıç örneği.
Performansı artırmaya yönelik ipuçları
Sonuçlarınızın kalitesi, giriş resminin kalitesine bağlıdır:
- Makine Öğrenimi Kiti'nin doğru bir segmentasyon sonucu alabilmesi için görüntünün en az 256x256 piksel boyutunda olması gerekir.
- Gerçek zamanlı bir uygulamada selfie segmentasyonu yapıyorsanız, giriş görüntülerinin genel boyutlarını da göz önünde bulundurmak isteyebilirsiniz. Daha küçük resimler daha hızlı işlenebilir. Bu nedenle, gecikmeyi azaltmak için düşük çözünürlüklerde fotoğraf çekin. Ancak yukarıdaki çözünürlük gereksinimlerini göz önünde bulundurun ve objenin resmin olabildiğince büyük bir kısmını kapladığından emin olun.
- Kötü bir resim odağı, doğruluğu da etkileyebilir. Kabul edilebilir sonuçlar almıyorsanız kullanıcıdan resmi yeniden çekmesini isteyin.
Segmentasyonu gerçek zamanlı bir uygulamada kullanmak istiyorsanız en iyi kare hızlarına ulaşmak 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 düşünün. Ancak bu API'nin resim boyutu şartlarını da göz önünde bulundurun.
- Video karelerini işlemek için segmenterin
results(in:)
eşzamanlı API'sini kullanın. Belirli bir video karesinden sonuçları eşzamanlı olarak almak için AVCaptureVideoDataOutputSampleBufferDelegate'in captureOutput(_, didOutput:from:) fonksiyonundan bu yöntemi çağırın. Segmentere yapılan çağrıları kısmak için AVCaptureVideoDataOutput'ın alwaysDiscardsLateVideoFrames değerini doğru olarak bırakın. Segmenter çalışırken yeni bir video karesi kullanılabilir hale gelirse segment atlanır. - Giriş görüntüsünün üzerine grafik yerleştirmek için segmenterin çıkışını kullanırsanız önce ML Kit'ten sonucu alın, ardından tek bir adımda görüntüyü oluşturun ve bindirme kullanın. Böylece, işlenen her giriş karesi için görüntü yüzeyinde yalnızca bir kez oluşturma yaparsınız. Örnek için ML Kit hızlı başlangıç örneğindeki previewOverlayView ve CameraViewController sınıflarına bakın.