ML Kit, सेल्फ़ी सेगमेंटेशन के लिए ऑप्टिमाइज़ किया गया SDK टूल उपलब्ध कराता है. सेल्फ़ी सेगमेंटेशन की ऐसेट, बिल्ड टाइम पर आपके ऐप्लिकेशन से स्टैटिक तौर पर लिंक होती हैं. इससे आपके ऐप्लिकेशन का साइज़ 24 एमबी तक बढ़ जाएगा. साथ ही, एपीआई की लेटेन्सी, इनपुट इमेज के साइज़ के हिसाब से ~7 मि॰से॰ से ~12 मि॰से॰ तक हो सकती है. यह मेज़रमेंट, iPhone X पर किया गया है.
इसे आज़माएं
- इस एपीआई के इस्तेमाल का उदाहरण देखने के लिए, सैंपल ऐप्लिकेशन का इस्तेमाल करें.
शुरू करने से पहले
अपने Podfile में, ML Kit की इन लाइब्रेरी को शामिल करें:
pod 'GoogleMLKit/SegmentationSelfie', '8.0.0'
अपने प्रोजेक्ट के पॉड इंस्टॉल या अपडेट करने के बाद, Xcode प्रोजेक्ट को .
xcworkspace
का इस्तेमाल करके खोलें. ML Kit, Xcode के 13.2.1 या इसके बाद के वर्शन पर काम करता है.
1. Segmenter का इंस्टेंस बनाना
सेल्फ़ी इमेज पर सेगमेंटेशन करने के लिए, सबसे पहले Segmenter
का एक इंस्टेंस बनाएं. इसके लिए, SelfieSegmenterOptions
का इस्तेमाल करें. इसके अलावा, सेगमेंटेशन की सेटिंग भी तय की जा सकती हैं.
Segmenter के विकल्प
सेगमेंट करने वाला मोड
Segmenter
दो मोड में काम करता है. पक्का करें कि आपने वह विकल्प चुना हो जो आपके इस्तेमाल के उदाहरण से मेल खाता हो.
STREAM_MODE (default)
इस मोड को वीडियो या कैमरे से फ़्रेम स्ट्रीम करने के लिए डिज़ाइन किया गया है. इस मोड में, सेगमेंट करने वाला टूल पिछले फ़्रेम के नतीजों का इस्तेमाल करेगा, ताकि सेगमेंटेशन के बेहतर नतीजे मिल सकें.
SINGLE_IMAGE_MODE (default)
इस मोड को ऐसी अलग-अलग इमेज के लिए डिज़ाइन किया गया है जो एक-दूसरे से जुड़ी नहीं हैं. इस मोड में, सेगमेंट करने वाला टूल हर इमेज को अलग-अलग प्रोसेस करेगा. इसमें फ़्रेम को स्मूथ नहीं किया जाएगा.
रॉ साइज़ मास्क चालू करें
यह विकल्प, सेगमेंटेशन करने वाले टूल से मॉडल के आउटपुट साइज़ से मेल खाने वाला रॉ साइज़ मास्क दिखाने के लिए कहता है.
रॉ मास्क का साइज़ (जैसे, 256x256) आम तौर पर इनपुट इमेज के साइज़ से कम होता है.
इस विकल्प को तय किए बिना, सेगमेंट करने वाला टूल रॉ मास्क को इनपुट इमेज के साइज़ के हिसाब से फिर से स्केल करेगा. अगर आपको अपने हिसाब से रीस्केलिंग लॉजिक लागू करना है या आपके इस्तेमाल के उदाहरण के लिए रीस्केलिंग की ज़रूरत नहीं है, तो इस विकल्प का इस्तेमाल करें.
सेगमेंट करने वाले के विकल्प तय करें:
Swift
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Objective-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
आखिर में, Segmenter
का इंस्टेंस पाएं. आपने जो विकल्प दिए हैं उन्हें पास करें:
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. इनपुट इमेज तैयार करना
सेल्फ़ी को सेगमेंट करने के लिए, वीडियो की हर इमेज या फ़्रेम के लिए यह तरीका अपनाएं.
अगर आपने स्ट्रीम मोड चालू किया है, तो आपको CMSampleBuffer
से VisionImage
ऑब्जेक्ट बनाने होंगे.
UIImage
या CMSampleBuffer
का इस्तेमाल करके, VisionImage
ऑब्जेक्ट बनाएं.
अगर UIImage
का इस्तेमाल किया जाता है, तो यह तरीका अपनाएं:
UIImage
का इस्तेमाल करके,VisionImage
ऑब्जेक्ट बनाएं. पक्का करें कि आपने सही.orientation
डाला हो.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
अगर CMSampleBuffer
का इस्तेमाल किया जाता है, तो यह तरीका अपनाएं:
-
CMSampleBuffer
में मौजूद इमेज डेटा का ओरिएंटेशन बताएं.इमेज का ओरिएंटेशन पाने के लिए:
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
ऑब्जेक्ट और ओरिएंटेशन का इस्तेमाल करके,VisionImage
ऑब्जेक्ट बनाएं: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. इमेज को प्रोसेस करना
VisionImage
ऑब्जेक्ट को Segmenter
के इमेज प्रोसेसिंग के किसी एक तरीके में पास करें. एसिंक्रोनस process(image:)
या सिंक्रोनस results(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.
सेल्फ़ी वाली इमेज पर एसिंक्रोनस तरीके से सेगमेंटेशन करने के लिए:
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. सेगमेंटेशन मास्क पाना
सेगमेंटेशन का नतीजा इस तरह पाया जा सकता है:
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); }
सेगमेंटेशन के नतीजों का इस्तेमाल करने के तरीके का पूरा उदाहरण देखने के लिए, कृपया ML Kit का क्विकस्टार्ट सैंपल देखें.
परफ़ॉर्मेंस को बेहतर बनाने के लिए सुझाव
नतीजों की क्वालिटी, इनपुट इमेज की क्वालिटी पर निर्भर करती है:
- सेगमेंटेशन का सटीक नतीजा पाने के लिए, इमेज कम से कम 256x256 पिक्सल की होनी चाहिए.
- अगर आपको रीयल-टाइम ऐप्लिकेशन में सेल्फ़ी सेगमेंटेशन करना है, तो आपको इनपुट इमेज के कुल डाइमेंशन पर भी ध्यान देना चाहिए. छोटी इमेज को तेज़ी से प्रोसेस किया जा सकता है. इसलिए, इमेज को कम रिज़ॉल्यूशन पर कैप्चर करें, ताकि इमेज को प्रोसेस करने में कम समय लगे. हालांकि, ऊपर बताई गई रिज़ॉल्यूशन से जुड़ी ज़रूरी शर्तों को ध्यान में रखें. साथ ही, यह पक्का करें कि इमेज में ज़्यादा से ज़्यादा जगह पर विषय मौजूद हो.
- इमेज के फ़ोकस में गड़बड़ी होने पर भी, सटीक नतीजे नहीं मिलते. अगर आपको सही नतीजे नहीं मिलते हैं, तो उपयोगकर्ता से इमेज को फिर से कैप्चर करने के लिए कहें.
अगर आपको रीयल-टाइम ऐप्लिकेशन में सेगमेंटेशन का इस्तेमाल करना है, तो सबसे अच्छी फ़्रेम रेट पाने के लिए, इन दिशा-निर्देशों का पालन करें:
stream
सेगमेंटेशन मोड का इस्तेमाल करें.- इमेज को कम रिज़ॉल्यूशन में कैप्चर करें. हालांकि, इस एपीआई के लिए इमेज के डाइमेंशन से जुड़ी ज़रूरी शर्तों का भी ध्यान रखें.
- वीडियो फ़्रेम प्रोसेस करने के लिए, सेगमेंट करने वाले टूल के
results(in:)
सिंक्रोनस एपीआई का इस्तेमाल करें. दिए गए वीडियो फ़्रेम से नतीजे पाने के लिए, इस तरीके को AVCaptureVideoDataOutputSampleBufferDelegate के captureOutput(_, didOutput:from:) फ़ंक्शन से कॉल करें. सेगमेंट करने वाले को कॉल थ्रॉटल करने के लिए, AVCaptureVideoDataOutput के alwaysDiscardsLateVideoFrames को सही के तौर पर सेट करें. अगर सेगमेंटेशन की प्रोसेस के दौरान कोई नया वीडियो फ़्रेम उपलब्ध होता है, तो उसे छोड़ दिया जाएगा. - अगर आपको सेगमेंटेशन की सुविधा का इस्तेमाल करके, इनपुट इमेज पर ग्राफ़िक ओवरले करने हैं, तो पहले ML Kit से नतीजे पाएं. इसके बाद, इमेज को रेंडर करें और एक ही चरण में ओवरले करें. ऐसा करने से, हर प्रोसेस किए गए इनपुट फ़्रेम के लिए, डिसप्ले सर्फ़ेस पर सिर्फ़ एक बार रेंडर किया जाता है. उदाहरण के लिए, ML Kit के क्विकस्टार्ट सैंपल में previewOverlayView और CameraViewController क्लास देखें.