iOS के लिए, हैंड लैंडमार्क की पहचान करने वाली गाइड

MediaPipe के 'हाथ के लैंडमार्क' टास्क की मदद से, किसी इमेज में हाथ के लैंडमार्क का पता लगाया जा सकता है. इन निर्देशों में, iOS ऐप्लिकेशन के साथ हैंड लैंडमार्कर का इस्तेमाल करने का तरीका बताया गया है. इन निर्देशों में बताए गए कोड का सैंपल, GitHub पर उपलब्ध है.

इस टास्क की सुविधाओं, मॉडल, और कॉन्फ़िगरेशन के विकल्पों के बारे में ज़्यादा जानने के लिए, खास जानकारी देखें.

कोड का उदाहरण

MediaPipe Tasks का उदाहरण कोड, iOS के लिए हाथ के लैंडमार्क का पता लगाने वाले ऐप्लिकेशन को लागू करने का बुनियादी तरीका है. इस उदाहरण में, लगातार चल रही वीडियो स्ट्रीम में हाथ के लैंडमार्क का पता लगाने के लिए, किसी iOS डिवाइस के कैमरे का इस्तेमाल किया गया है. यह ऐप्लिकेशन, डिवाइस की गैलरी में मौजूद इमेज और वीडियो में हाथ के लैंडमार्क का पता लगा सकता है.

इस ऐप्लिकेशन का इस्तेमाल, अपने iOS ऐप्लिकेशन के लिए शुरुआती बिंदु के तौर पर किया जा सकता है. इसके अलावा, किसी मौजूदा ऐप्लिकेशन में बदलाव करते समय भी इसका इस्तेमाल किया जा सकता है. हाथ के लैंडमार्क का उदाहरण देने वाला कोड, GitHub पर होस्ट किया गया है.

कोड डाउनलोड करना

यहां दिए गए निर्देशों में, git कमांड-लाइन टूल का इस्तेमाल करके, उदाहरण के कोड की लोकल कॉपी बनाने का तरीका बताया गया है.

उदाहरण के तौर पर दिया गया कोड डाउनलोड करने के लिए:

  1. यहां दिए गए कमांड का इस्तेमाल करके, Git डेटा स्टोर करने की जगह को क्लोन करें:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. इसके अलावा, अपने git इंस्टेंस को स्पैर्स चेकआउट का इस्तेमाल करने के लिए कॉन्फ़िगर करें, ताकि आपके पास सिर्फ़ Hand Landmarker के उदाहरण वाले ऐप्लिकेशन की फ़ाइलें हों:

    cd mediapipe-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/hand_landmarker/ios/
    

उदाहरण के तौर पर दिए गए कोड का लोकल वर्शन बनाने के बाद, MediaPipe टास्क लाइब्रेरी इंस्टॉल की जा सकती है. इसके बाद, Xcode का इस्तेमाल करके प्रोजेक्ट खोलें और ऐप्लिकेशन चलाएं. निर्देशों के लिए, iOS के लिए सेटअप गाइड देखें.

मुख्य कॉम्पोनेंट

नीचे दी गई फ़ाइलों में, हाथ के लैंडमार्क के उदाहरण वाले ऐप्लिकेशन के लिए ज़रूरी कोड शामिल है:

  • HandLandmarkerService.swift: यह हैंड लैंडमार्कर को शुरू करता है, मॉडल चुनने की प्रोसेस को मैनेज करता है, और इनपुट डेटा पर अनुमान लगाता है.
  • CameraViewController.swift: यह लाइव कैमरा फ़ीड इनपुट मोड के लिए यूज़र इंटरफ़ेस (यूआई) लागू करता है और नतीजों को विज़ुअलाइज़ करता है.
  • MediaLibraryViewController.swift: इसमें स्टिल इमेज और वीडियो फ़ाइल के इनपुट मोड के लिए यूज़र इंटरफ़ेस (यूआई) लागू किया जाता है. साथ ही, नतीजों को विज़ुअलाइज़ किया जाता है.

सेटअप

इस सेक्शन में, डेवलपमेंट एनवायरमेंट और कोड प्रोजेक्ट सेट अप करने के मुख्य चरणों के बारे में बताया गया है, ताकि हैंड लैंडमार्कर का इस्तेमाल किया जा सके. MediaPipe Tasks का इस्तेमाल करने के लिए, डेवलपमेंट एनवायरमेंट सेट अप करने के बारे में सामान्य जानकारी पाने के लिए, iOS के लिए सेटअप गाइड देखें. इसमें, प्लैटफ़ॉर्म के वर्शन से जुड़ी ज़रूरी शर्तें भी शामिल हैं.

डिपेंडेंसी

Hand Landmarker, MediaPipeTasksVision लाइब्रेरी का इस्तेमाल करता है. इसे CocoaPods का इस्तेमाल करके इंस्टॉल करना ज़रूरी है. यह लाइब्रेरी, Swift और Objective-C, दोनों तरह के ऐप्लिकेशन के साथ काम करती है. साथ ही, इसके लिए भाषा के हिसाब से किसी अन्य सेटअप की ज़रूरत नहीं होती.

macOS पर CocoaPods इंस्टॉल करने के निर्देशों के लिए, CocoaPods को इंस्टॉल करने की गाइड देखें. अपने ऐप्लिकेशन के लिए ज़रूरी पॉड के साथ Podfile बनाने का तरीका जानने के लिए, CocoaPods का इस्तेमाल करना लेख पढ़ें.

नीचे दिए गए कोड का इस्तेमाल करके, Podfile में MediaPipeTasksVision पॉड जोड़ें:

target 'MyHandLandmarkerApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

अगर आपके ऐप्लिकेशन में यूनिट टेस्ट टारगेट शामिल हैं, तो Podfile को सेट अप करने के बारे में ज़्यादा जानकारी के लिए, iOS के लिए सेट अप करने की गाइड देखें.

मॉडल

MediaPipe के हाथ के लैंडमार्क का पता लगाने वाले टूल के लिए, ऐसा मॉडल ज़रूरी है जिसे इस टास्क के लिए ट्रेन किया गया हो. हाथ के लैंडमार्क के लिए, पहले से ट्रेन किए गए मॉडल के बारे में ज़्यादा जानकारी पाने के लिए, टास्क की खास जानकारी वाला मॉडल सेक्शन देखें.

कोई मॉडल चुनें और डाउनलोड करें. इसके बाद, Xcode का इस्तेमाल करके उसे अपनी प्रोजेक्ट डायरेक्ट्री में जोड़ें. अपने Xcode प्रोजेक्ट में फ़ाइलें जोड़ने का तरीका जानने के लिए, अपने Xcode प्रोजेक्ट में फ़ाइलों और फ़ोल्डर को मैनेज करना लेख पढ़ें.

अपने ऐप्लिकेशन बंडल में मॉडल का पाथ बताने के लिए, BaseOptions.modelAssetPath प्रॉपर्टी का इस्तेमाल करें. कोड का उदाहरण देखने के लिए, अगला सेक्शन देखें.

टास्क बनाना

इसके किसी एक इनिशलाइज़र को कॉल करके, हाथ के लैंडमार्क का टास्क बनाया जा सकता है. HandLandmarker(options:) initializer, कॉन्फ़िगरेशन के विकल्पों के लिए वैल्यू स्वीकार करता है.

अगर आपको पसंद के मुताबिक कॉन्फ़िगरेशन के विकल्पों के साथ शुरू किए गए हैंड लैंडमार्कर की ज़रूरत नहीं है, तो डिफ़ॉल्ट विकल्पों के साथ हैंड लैंडमार्कर बनाने के लिए, HandLandmarker(modelPath:) आइनिलाइज़र का इस्तेमाल किया जा सकता है. कॉन्फ़िगरेशन के विकल्पों के बारे में ज़्यादा जानने के लिए, कॉन्फ़िगरेशन की खास जानकारी देखें.

हाथ के लैंडमार्क का पता लगाने वाले टास्क में, इनपुट डेटा के तीन टाइप इस्तेमाल किए जा सकते हैं: स्टिल इमेज, वीडियो फ़ाइलें, और लाइव वीडियो स्ट्रीम. डिफ़ॉल्ट रूप से, HandLandmarker(modelPath:) स्टिल इमेज के लिए एक टास्क शुरू करता है. अगर आपको वीडियो फ़ाइलों या लाइव वीडियो स्ट्रीम को प्रोसेस करने के लिए, अपना टास्क शुरू करना है, तो वीडियो या लाइव स्ट्रीम के चलने के मोड की जानकारी देने के लिए HandLandmarker(options:) का इस्तेमाल करें. लाइव स्ट्रीम मोड के लिए, handLandmarkerLiveStreamDelegate कॉन्फ़िगरेशन के एक और विकल्प की ज़रूरत होती है. इससे, हाथ के लैंडमार्क की सुविधा, डेलिगेट को हाथ के लैंडमार्क के नतीजे असिंक्रोनस तरीके से डिलीवर कर पाती है.

टास्क बनाने और अनुमान लगाने का तरीका जानने के लिए, अपने रनिंग मोड से जुड़ा टैब चुनें.

Swift

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "hand_landmarker",
                                      ofType: "task")

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let handLandmarker = try HandLandmarker(options: options)
    
import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "hand_landmarker",
                                      ofType: "task")

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

let handLandmarker = try HandLandmarker(options: options)
    
import MediaPipeTasksVision

// Class that conforms to the `HandLandmarkerLiveStreamDelegate` protocol and
// implements the method that the hand landmarker calls once it finishes
// performing landmarks detection in each input frame.
class HandLandmarkerResultProcessor: NSObject, HandLandmarkerLiveStreamDelegate {

  func handLandmarker(
    _ handLandmarker: HandLandmarker,
    didFinishDetection result: HandLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the hand landmarker result or errors here.

  }
}

let modelPath = Bundle.main.path(
  forResource: "hand_landmarker",
  ofType: "task")

let options = HandLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minHandDetectionConfidence = minHandDetectionConfidence
options.minHandPresenceConfidence = minHandPresenceConfidence
options.minTrackingConfidence = minHandTrackingConfidence
options.numHands = numHands

// Assign an object of the class to the `handLandmarkerLiveStreamDelegate`
// property.
let processor = HandLandmarkerResultProcessor()
options.handLandmarkerLiveStreamDelegate = processor

let handLandmarker = try HandLandmarker(options: options)
    

Objective-C

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"hand_landmarker"
                                                      ofType:@"task"];

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    
@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"hand_landmarker"
                                                      ofType:@"task"];

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    
@import MediaPipeTasksVision;

// Class that conforms to the `MPPHandLandmarkerLiveStreamDelegate` protocol
// and implements the method that the hand landmarker calls once it finishes
// performing landmarks detection in each input frame.

@interface APPHandLandmarkerResultProcessor : NSObject 

@end

@implementation APPHandLandmarkerResultProcessor

-   (void)handLandmarker:(MPPHandLandmarker *)handLandmarker
    didFinishDetectionWithResult:(MPPHandLandmarkerResult *)handLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the hand landmarker result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"hand_landmarker"
                                                      ofType:@"task"];

MPPHandLandmarkerOptions *options = [[MPPHandLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minHandDetectionConfidence = minHandDetectionConfidence;
options.minHandPresenceConfidence = minHandPresenceConfidence;
options.minTrackingConfidence = minHandTrackingConfidence;
options.numHands = numHands;

// Assign an object of the class to the `handLandmarkerLiveStreamDelegate`
// property.
APPHandLandmarkerResultProcessor *processor =
  [APPHandLandmarkerResultProcessor new];
options.handLandmarkerLiveStreamDelegate = processor;

MPPHandLandmarker *handLandmarker =
  [[MPPHandLandmarker alloc] initWithOptions:options error:nil];
    

कॉन्फ़िगरेशन विकल्प

इस टास्क में, iOS ऐप्लिकेशन के लिए ये कॉन्फ़िगरेशन विकल्प हैं:

विकल्प का नाम ब्यौरा वैल्यू की रेंज डिफ़ॉल्ट मान
running_mode टास्क के लिए रनिंग मोड सेट करता है. इसके तीन मोड हैं:

IMAGE: एक इमेज इनपुट के लिए मोड.

वीडियो: किसी वीडियो के डिकोड किए गए फ़्रेम के लिए मोड.

LIVE_STREAM: कैमरे से मिले इनपुट डेटा की लाइव स्ट्रीम के लिए मोड. इस मोड में, नतीजे असींक्रोनस तरीके से पाने के लिए, एक listener सेट अप करने के लिए, resultListener को कॉल करना होगा. इस मोड में, handLandmarkerLiveStreamDelegate को किसी ऐसी क्लास के इंस्टेंस पर सेट करना होगा जो HandLandmarkerLiveStreamDelegate को लागू करती है. इससे, हाथ के लैंडमार्क का पता लगाने के नतीजे, एक साथ मिलने के बजाय अलग-अलग समय पर मिलते हैं.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
numHands हाथ के लैंडमार्क डिटेक्टर की मदद से, ज़्यादा से ज़्यादा कितने हाथों की पहचान की जा सकती है. Any integer > 0 1
minHandDetectionConfidence हाथ की पहचान करने के लिए, कम से कम इतना कॉन्फ़िडेंस स्कोर होना चाहिए, ताकि उसे हथेली की पहचान करने वाले मॉडल में सफल माना जा सके. 0.0 - 1.0 0.5
minHandPresenceConfidence हाथ के मौजूद होने के स्कोर के लिए, कम से कम कॉन्फ़िडेंस स्कोर. यह स्कोर, हाथ के लैंडमार्क का पता लगाने वाले मॉडल में दिखता है. वीडियो मोड और लाइव स्ट्रीम मोड में, अगर हाथ के लैंडमार्क मॉडल से हाथ की मौजूदगी का कॉन्फ़िडेंस स्कोर इस थ्रेशोल्ड से कम है, तो हाथ के लैंडमार्क की पहचान करने वाला टूल, हथेली की पहचान करने वाले मॉडल को ट्रिगर करता है. अगर ऐसा नहीं होता है, तो लैंडमार्क का पता लगाने के लिए, हाथ को ट्रैक करने वाला एक आसान एल्गोरिदम, हाथ की जगह का पता लगाता है. 0.0 - 1.0 0.5
minTrackingConfidence हाथ की ट्रैकिंग को कामयाब माना जा सके, इसके लिए कम से कम कॉन्फ़िडेंस स्कोर. यह मौजूदा फ़्रेम और आखिरी फ़्रेम में, हाथों के बीच के बॉउंडिंग बॉक्स का IoU थ्रेशोल्ड है. अगर हाथ के लैंडमार्क की सुविधा के वीडियो मोड और स्ट्रीम मोड में ट्रैकिंग नहीं हो पाती है, तो हाथ के लैंडमार्क की सुविधा, हाथ का पता लगाने की सुविधा को ट्रिगर करती है. ऐसा न करने पर, हाथ का पता लगाने की सुविधा काम नहीं करती. 0.0 - 1.0 0.5
result_listener जब हाथ का लैंडमार्कर लाइव स्ट्रीम मोड में हो, तो पहचान के नतीजे पाने के लिए रिज़ल्ट लिसनर को असिंक्रोनस तरीके से सेट करता है. यह सिर्फ़ तब लागू होता है, जब रनिंग मोड को LIVE_STREAM पर सेट किया गया हो लागू नहीं लागू नहीं

जब रनिंग मोड को लाइव स्ट्रीम पर सेट किया जाता है, तो हैंड लैंडमार्कर के लिए handLandmarkerLiveStreamDelegate कॉन्फ़िगरेशन का एक और विकल्प ज़रूरी होता है. इस विकल्प की मदद से, हैंड लैंडमार्कर, हाथ के लैंडमार्क का पता लगाने के नतीजे, एक साथ नहीं दिखाता. डेलिगेट को handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) तरीका लागू करना होगा. हर फ़्रेम के लिए, हाथ के लैंडमार्क का पता लगाने के नतीजों को प्रोसेस करने के बाद, Hand Landmarker इस तरीके को कॉल करता है.

विकल्प का नाम ब्यौरा वैल्यू की रेंज डिफ़ॉल्ट मान
handLandmarkerLiveStreamDelegate इससे, लाइव स्ट्रीम मोड में, हाथ के लैंडमार्क का पता लगाने के नतीजे, एसिंक्रोनस तरीके से मिलते हैं. जिस क्लास का इंस्टेंस इस प्रॉपर्टी पर सेट है उसे handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) तरीका लागू करना होगा. लागू नहीं सेट नहीं है

डेटा तैयार करना

इनपुट इमेज या फ़्रेम को हाथ के लैंडमार्क की सुविधा को पास करने से पहले, MPImage ऑब्जेक्ट में बदलना होगा. MPImage, iOS इमेज के अलग-अलग फ़ॉर्मैट के साथ काम करता है. साथ ही, इनका इस्तेमाल अनुमान लगाने के लिए, किसी भी रनिंग मोड में किया जा सकता है. MPImage के बारे में ज़्यादा जानकारी के लिए, MPImage API देखें.

अपने इस्तेमाल के उदाहरण और ऐप्लिकेशन के लिए ज़रूरी रनिंग मोड के आधार पर, iOS इमेज फ़ॉर्मैट चुनें.MPImage, UIImage, CVPixelBuffer, और CMSampleBuffer iOS इमेज फ़ॉर्मैट स्वीकार करता है.

UIImage

UIImage फ़ॉर्मैट, इन रनिंग मोड के लिए सबसे सही है:

  • इमेज: ऐप्लिकेशन बंडल, उपयोगकर्ता की गैलरी या फ़ाइल सिस्टम में मौजूद इमेज को MPImage ऑब्जेक्ट में बदला जा सकता है. हालांकि, इसके लिए ज़रूरी है कि इमेज को UIImage फ़ॉर्मैट में फ़ॉर्मैट किया गया हो.

  • वीडियो: AVAssetImageGenerator का इस्तेमाल करके, वीडियो फ़्रेम को CGImage फ़ॉर्मैट में निकालें. इसके बाद, उन्हें UIImage इमेज में बदलें.

SwiftObjective-C
// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    
// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

इस उदाहरण में, डिफ़ॉल्ट UIImage.Orientation.Up ओरिएंटेशन के साथ MPImage को शुरू किया गया है. MPImage को इस्तेमाल की जा सकने वाली किसी भी UIImage.Orientation वैल्यू के साथ शुरू किया जा सकता है. हाथ के लैंडमार्क की सुविधा, .upMirrored, .downMirrored, .leftMirrored, .rightMirrored जैसे मिरर किए गए ओरिएंटेशन के साथ काम नहीं करती.

UIImage के बारे में ज़्यादा जानकारी के लिए, UIImage Apple Developer के दस्तावेज़ देखें.

CVPixelBuffer

CVPixelBuffer फ़ॉर्मैट, उन ऐप्लिकेशन के लिए सबसे सही है जो फ़्रेम जनरेट करते हैं और प्रोसेसिंग के लिए iOS CoreImage फ़्रेमवर्क का इस्तेमाल करते हैं.

CVPixelBuffer फ़ॉर्मैट, इन रनिंग मोड के लिए सबसे सही है:

  • इमेज: iOS के CoreImage फ़्रेमवर्क का इस्तेमाल करके, कुछ प्रोसेसिंग के बाद CVPixelBuffer इमेज जनरेट करने वाले ऐप्लिकेशन को इमेज रनिंग मोड में, हाथ के लैंडमार्क की जानकारी देने वाले टूल को भेजा जा सकता है.

  • वीडियो: वीडियो फ़्रेम को प्रोसेस करने के लिए, CVPixelBuffer फ़ॉर्मैट में बदला जा सकता है. इसके बाद, उन्हें वीडियो मोड में हैंड लैंडमार्कर को भेजा जा सकता है.

  • लाइव स्ट्रीम: फ़्रेम जनरेट करने के लिए iOS कैमरे का इस्तेमाल करने वाले ऐप्लिकेशन, लाइव स्ट्रीम मोड में, हाथ के लैंडमार्कर को भेजे जाने से पहले, प्रोसेसिंग के लिए CVPixelBuffer फ़ॉर्मैट में बदले जा सकते हैं.

SwiftObjective-C
// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    
// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

CVPixelBuffer के बारे में ज़्यादा जानकारी के लिए, CVPixelBuffer Apple Developer दस्तावेज़ देखें.

CMSampleBuffer

CMSampleBuffer फ़ॉर्मैट, एक जैसे मीडिया टाइप के मीडिया सैंपल को सेव करता है. साथ ही, यह लाइव स्ट्रीम के रनिंग मोड के लिए काफ़ी सही है. iOS कैमरों से लाइव फ़्रेम, iOS AVCaptureVideoDataOutput की मदद से, CMSampleBuffer फ़ॉर्मैट में अलग-अलग डिलीवर किए जाते हैं.

SwiftObjective-C
// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    
// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

CMSampleBuffer के बारे में ज़्यादा जानकारी के लिए, CMSampleBuffer Apple के डेवलपर के दस्तावेज़ देखें.

टास्क चलाना

हैंड लैंडमार्कर को चलाने के लिए, असाइन किए गए रनिंग मोड के हिसाब से detect() तरीके का इस्तेमाल करें:

  • स्टिल इमेज: detect(image:)
  • वीडियो: detect(videoFrame:timestampInMilliseconds:)
  • लाइवस्ट्रीम: detectAsync(image:timestampInMilliseconds:)

Swift

let result = try handLandmarker.detect(image: image)
    
let result = try handLandmarker.detect(
    videoFrame: image,
    timestampInMilliseconds: timestamp)
    
try handLandmarker.detectAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

MPPHandLandmarkerResult *result =
  [handLandmarker detectInImage:image error:nil];
    
MPPHandLandmarkerResult *result =
  [handLandmarker detectInVideoFrame:image
             timestampInMilliseconds:timestamp
                               error:nil];
    
BOOL success =
  [handLandmarker detectAsyncInImage:image
             timestampInMilliseconds:timestamp
                               error:nil];
    

हाथ के लैंडमार्क कोड के उदाहरण में, इनमें से हर मोड को लागू करने के बारे में ज़्यादा जानकारी दी गई है. उदाहरण के तौर पर दिए गए कोड की मदद से, उपयोगकर्ता डेटा प्रोसेस करने के एक मोड से दूसरे मोड पर स्विच कर सकता है. हालांकि, ऐसा आपके इस्तेमाल के उदाहरण के लिए ज़रूरी नहीं है.

निम्न पर ध्यान दें:

  • वीडियो मोड या लाइव स्ट्रीम मोड में चलाने पर, आपको हाथ के लैंडमार्क करने वाले टास्क के लिए, इनपुट फ़्रेम का टाइमस्टैंप भी देना होगा.

  • इमेज या वीडियो मोड में चलने पर, हाथ के लैंडमार्क का पता लगाने वाला टास्क, मौजूदा थ्रेड को तब तक ब्लॉक करता है, जब तक वह इनपुट इमेज या फ़्रेम को प्रोसेस नहीं कर लेता. मौजूदा थ्रेड को ब्लॉक होने से बचाने के लिए, iOS के Dispatch या NSOperation फ़्रेमवर्क का इस्तेमाल करके, बैकग्राउंड थ्रेड में प्रोसेसिंग को पूरा करें.

  • लाइव स्ट्रीम मोड में चलने पर, हाथ के लैंडमार्क का टास्क तुरंत रिटर्न करता है और मौजूदा थ्रेड को ब्लॉक नहीं करता. यह हर इनपुट फ़्रेम को प्रोसेस करने के बाद, हाथ के लैंडमार्कर के नतीजे के साथ handLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) तरीका शुरू करता है. हाथ के लैंडमार्कर, इस तरीके को किसी खास सीरियल डिस्पैच कतार पर एसिंक्रोनस तरीके से लागू करते हैं. यूज़र इंटरफ़ेस पर नतीजे दिखाने के लिए, नतीजों को प्रोसेस करने के बाद, उन्हें मुख्य सूची में भेजें. अगर detectAsync फ़ंक्शन को तब कॉल किया जाता है, जब हाथ के लैंडमार्क का पता लगाने वाला टास्क किसी दूसरे फ़्रेम को प्रोसेस कर रहा हो, तो हाथ के लैंडमार्क का पता लगाने वाला टूल, नए इनपुट फ़्रेम को अनदेखा कर देता है.

नतीजों को मैनेज और दिखाना

अनुमान लगाने के बाद, हाथ के लैंडमार्क का पता लगाने वाला टास्क एक HandLandmarkerResult दिखाता है. इसमें इमेज के निर्देशांक में हाथ के लैंडमार्क, दुनिया के निर्देशांक में हाथ के लैंडमार्क, और हाथ के बाएं/दाएं होने की जानकारी होती है.

यहां इस टास्क के आउटपुट डेटा का उदाहरण दिया गया है:

HandLandmarkerResult आउटपुट में तीन कॉम्पोनेंट होते हैं. हर कॉम्पोनेंट एक कलेक्शन होता है. इसमें हर एलिमेंट में, पहचाने गए एक हाथ के लिए ये नतीजे होते हैं:

  • किसी खास हाथ का इस्तेमाल

    इस एट्रिब्यूट से पता चलता है कि पहचाने गए हाथ बाएं हैं या दाएं.

  • लैंडमार्क

    हाथ के 21 लैंडमार्क हैं. हर लैंडमार्क में x, y, और z कोऑर्डिनेट होते हैं. x और y निर्देशांक को इमेज की चौड़ाई और ऊंचाई के हिसाब से, [0.0, 1.0] पर नॉर्मलाइज़ किया जाता है. z निर्देशांक, लैंडमार्क की गहराई दिखाता है. इसमें कलाई की गहराई को ऑरिजिन माना जाता है. वैल्यू जितनी कम होगी, लैंडमार्क कैमरे के उतना ही करीब होगा. z के मैग्नीट्यूड के लिए, x के स्केल का इस्तेमाल किया जाता है.

  • विश्व भू-स्थल

    हाथ के 21 लैंडमार्क, वर्ल्ड कोऑर्डिनेट में भी दिखाए जाते हैं. हर लैंडमार्क, x, y, और z से बना होता है. यह मीटर में, असल दुनिया के 3D कोऑर्डिनेट दिखाता है. इसमें हाथ के ज्यामितीय केंद्र को ऑरिजिन माना जाता है.

HandLandmarkerResult:
  Handedness:
    Categories #0:
      index        : 0
      score        : 0.98396
      categoryName : Left
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : -3.41E-7
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
    ... (21 landmarks for a hand)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
    ... (21 world landmarks for a hand)

नीचे दी गई इमेज में, टास्क के आउटपुट को विज़ुअलाइज़ किया गया है:

थंब्स अप का इशारा करते हुए हाथ की इमेज, जिसमें हाथ की हड्डियों की संरचना को मैप किया गया है