ML Kit menyediakan SDK yang dioptimalkan untuk segmentasi selfie. Aset Selfie Segmenter ditautkan secara statis ke aplikasi Anda pada waktu build. Hal ini akan meningkatkan ukuran aplikasi Anda hingga 24 MB dan latensi API dapat bervariasi dari ~7 md hingga ~12 md, bergantung pada ukuran gambar input, seperti yang diukur di iPhone X.
Cobalah
- Coba aplikasi contoh untuk melihat contoh penggunaan API ini.
Sebelum memulai
Sertakan library ML Kit berikut di Podfile Anda:
pod 'GoogleMLKit/SegmentationSelfie', '7.0.0'
Setelah Anda menginstal atau mengupdate Pod project, buka project Xcode menggunakan .
xcworkspace
-nya. ML Kit didukung di Xcode versi 13.2.1 atau yang lebih baru.
1. Membuat instance Segmenter
Untuk melakukan segmentasi pada gambar selfie, pertama-tama buat instance Segmenter
dengan SelfieSegmenterOptions
dan secara opsional tentukan setelan segmentasi.
Opsi segmenter
Mode Segmenter
Segmenter
beroperasi dalam dua mode. Pastikan Anda memilih template yang cocok dengan kasus penggunaan Anda.
STREAM_MODE (default)
Mode ini dirancang untuk streaming frame dari video atau kamera. Dalam mode ini, segmenter akan memanfaatkan hasil dari frame sebelumnya untuk menampilkan hasil segmentasi yang lebih halus.
SINGLE_IMAGE_MODE (default)
Mode ini dirancang untuk gambar tunggal yang tidak terkait. Dalam mode ini, segmenter akan memproses setiap gambar secara independen, tanpa penghalusan pada frame.
Mengaktifkan mask ukuran mentah
Meminta segmenter untuk menampilkan mask ukuran mentah yang cocok dengan ukuran output model.
Ukuran mask mentah (misalnya 256x256) biasanya lebih kecil dari ukuran gambar input.
Tanpa menentukan opsi ini, segmenter akan menskalakan ulang mask mentah agar sesuai dengan ukuran gambar input. Pertimbangkan untuk menggunakan opsi ini jika Anda ingin menerapkan logika penskalaan ulang yang disesuaikan atau penskalaan ulang tidak diperlukan untuk kasus penggunaan Anda.
Tentukan opsi pemisah:
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
Terakhir, dapatkan instance Segmenter
. Teruskan opsi yang Anda tentukan:
let segmenter = Segmenter.segmenter(options: options)
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. Menyiapkan gambar input
Untuk menyegmentasikan selfie, lakukan hal berikut untuk setiap gambar atau frame video.
Jika mengaktifkan mode streaming, Anda harus membuat objek VisionImage
dari CMSampleBuffer
.
Buat objek VisionImage
menggunakan UIImage
atau
CMSampleBuffer
.
Jika Anda menggunakan UIImage
, ikuti langkah-langkah berikut:
- Buat objek
VisionImage
denganUIImage
. Pastikan untuk menentukan.orientation
yang benar.let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Jika Anda menggunakan CMSampleBuffer
, ikuti langkah-langkah berikut:
-
Tentukan orientasi data gambar yang terdapat dalam
CMSampleBuffer
.Untuk mendapatkan orientasi gambar:
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 } }
- (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; } }
- Buat objek
VisionImage
menggunakan objek dan orientasiCMSampleBuffer
:let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Memproses gambar
Teruskan objek VisionImage
ke salah satu metode pemrosesan gambar Segmenter
. Anda dapat menggunakan metode process(image:)
yang asinkron atau metode results(in:)
yang sinkron.
Untuk melakukan segmentasi pada gambar selfie secara sinkron:
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.
NSError *error; MLKSegmentationMask *mask = [segmenter resultsInImage:image error:&error]; if (error != nil) { // Error. return; } // Success. Get a segmentation mask here.
Untuk melakukan segmentasi pada gambar selfie secara asinkron:
segmenter.process(image) { mask, error in guard error == nil else { // Error. return } // Success. Get a segmentation mask here.
[segmenter processImage:image completion:^(MLKSegmentationMask * _Nullable mask, NSError * _Nullable error) { if (error != nil) { // Error. return; } // Success. Get a segmentation mask here. }];
4. Mendapatkan mask segmentasi
Anda bisa mendapatkan hasil segmentasi sebagai berikut:
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 }
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); }
Untuk mengetahui contoh lengkap cara menggunakan hasil segmentasi, lihat contoh quickstart ML Kit.
Tips untuk meningkatkan performa
Kualitas hasil Anda bergantung pada kualitas gambar input:
- Agar ML Kit mendapatkan hasil segmentasi yang akurat, gambar harus berukuran minimal 256x256 piksel.
- Jika Anda melakukan segmentasi selfie dalam aplikasi real-time, Anda mungkin perlu mempertimbangkan dimensi gambar input secara keseluruhan. Gambar yang lebih kecil dapat diproses lebih cepat. Jadi, untuk mengurangi latensi, ambil gambar dengan resolusi yang lebih rendah, tetapi perhatikan persyaratan resolusi di atas dan pastikan subjek menempati gambar seluas mungkin.
- Fokus gambar yang buruk juga dapat memengaruhi akurasi. Jika Anda tidak mendapatkan hasil yang dapat diterima, minta pengguna untuk mengambil ulang gambar.
Jika Anda ingin menggunakan segmentasi dalam aplikasi real-time, ikuti panduan ini untuk mencapai kecepatan frame terbaik:
- Gunakan mode segmenter
stream
. - Pertimbangkan untuk mengambil gambar dengan resolusi lebih rendah. Namun, perhatikan juga persyaratan dimensi gambar API ini.
- Untuk memproses frame video, gunakan API sinkron
results(in:)
dari segmenter. Panggil metode ini dari fungsi captureOutput(_, didOutput:from:) AVCaptureVideoDataOutputSampleBufferDelegate untuk mendapatkan hasil secara sinkron dari frame video yang diberikan. Tetapkan alwaysDiscardsLateVideoFrames AVCaptureVideoDataOutput ke benar untuk membatasi panggilan ke segmenter. Jika frame video baru tersedia saat pemisah sedang berjalan, frame tersebut akan dihapus. - Jika Anda menggunakan output pemisah untuk menempatkan grafis pada gambar input, pertama-tama dapatkan hasilnya dari ML Kit, lalu render gambar dan tempatkan grafis dalam satu langkah. Dengan demikian, Anda hanya merender ke platform tampilan sekali untuk setiap frame input yang diproses. Lihat class previewOverlayView dan CameraViewController di contoh quickstart ML Kit untuk mengetahui contohnya.