ML Kit में, सेल्फ़ी को सेगमेंट में बांटने के लिए ऑप्टिमाइज़ किया गया SDK टूल दिया गया है. बिल्ड के दौरान, सेल्फ़ी सेगमेंटर की ऐसेट आपके ऐप्लिकेशन के साथ स्टैटिक रूप से लिंक होती हैं. इससे आपके ऐप्लिकेशन का साइज़ 24 एमबी तक बढ़ जाएगा. साथ ही, एपीआई के इंतज़ार का समय, इनपुट इमेज के साइज़ के हिसाब से ~7 मि॰से॰ से ~12 मि॰से॰ तक अलग-अलग हो सकता है. इसे iPhone X पर मापा जाता है.
इसे आज़माएं
- सैंपल वाले ऐप्लिकेशन को इस्तेमाल करके देखें, इस एपीआई के इस्तेमाल का एक उदाहरण देखें.
शुरू करने से पहले
अपनी Podfile में, नीचे दी गई ML Kit लाइब्रेरी शामिल करें:
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
प्रोजेक्ट के Pods को इंस्टॉल या अपडेट करने के बाद, Xcode प्रोजेक्ट में .
xcworkspace
का इस्तेमाल करके खोलें. ML Kit, Xcode के 13.2.1 या इसके बाद के वर्शन पर काम करता है.
1. सेगमेंटर का इंस्टेंस बनाना
सेल्फ़ी इमेज को सेगमेंट में बांटने के लिए, पहले 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. इनपुट इमेज तैयार करें
सेल्फ़ी को सेगमेंट में बांटने के लिए, वीडियो की हर इमेज या फ़्रेम के लिए यह तरीका अपनाएं.
अगर आपने स्ट्रीम मोड चालू किया है, तो आपको इससे VisionImage
ऑब्जेक्ट बनाने होंगे
CMSampleBuffer
.
एक VisionImage
ऑब्जेक्ट को UIImage
या
CMSampleBuffer
.
अगर 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; } }
- इसका इस्तेमाल करके एक
VisionImage
ऑब्जेक्ट बनाएंCMSampleBuffer
ऑब्जेक्ट और ओरिएंटेशन: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 से नतीजा पाएं. इसके बाद, एक ही चरण में इमेज और ओवरले को रेंडर करें. ऐसा करने पर, प्रोसेस किए गए हर इनपुट फ़्रेम के लिए, डिसप्ले सरफ़ेस पर सिर्फ़ एक बार रेंडर होता है. उदाहरण के लिए, एमएल किट क्विकस्टार्ट सैंपल में, previewOverlayView और CameraViewController क्लास देखें.