iOS पर ML Kit की मदद से पोज़ का पता लगाएं

ML Kit, पोज़ का पता लगाने के लिए, ऑप्टिमाइज़ किए गए दो एसडीके टूल उपलब्ध कराता है.

एसडीके टूल का नामPoseDetectionPoseDetectionAccurate
लागू करनाबेस डिटेक्टर के लिए ऐसेट, बिल्ड के समय आपके ऐप्लिकेशन से स्टैटिक तौर पर लिंक होती हैं.सटीक डिटेक्टर के लिए ऐसेट, बिल्ड प्रोसेस में लगने वाले समय पर आपके ऐप्लिकेशन से स्टैटिक तौर पर लिंक होती हैं.
ऐप्लिकेशन का साइज़ज़्यादा से ज़्यादा 29.6 एमबीज़्यादा से ज़्यादा 33.2 एमबी
परफ़ॉर्मेंसiPhone X: ~45एफ़पीएसiPhone X: ~29एफ़पीएस

इसे आज़माएं

शुरू करने से पहले

  1. अपने Podfile में, ML Kit के ये पॉड शामिल करें:

    # If you want to use the base implementation:
    pod 'GoogleMLKit/PoseDetection', '8.0.0'
    
    # If you want to use the accurate implementation:
    pod 'GoogleMLKit/PoseDetectionAccurate', '8.0.0'
    
  2. अपने प्रोजेक्ट के पॉड इंस्टॉल या अपडेट करने के बाद, xcworkspace का इस्तेमाल करके अपना Xcode प्रोजेक्ट खोलें. ML Kit, Xcode के 13.2.1 या इसके बाद के वर्शन पर काम करता है.

1. PoseDetector का इंस्टेंस बनाएं

किसी इमेज में पोज़ का पता लगाने के लिए, सबसे पहले PoseDetector का इंस्टेंस बनाएं. इसके अलावा, डिटेक्टर की सेटिंग भी तय की जा सकती हैं.

PoseDetector के विकल्प

डिटेक्शन मोड

PoseDetector, दो डिटेक्शन मोड में काम करता है. पक्का करें कि आपने अपनी ज़रूरत के हिसाब से कोई मोड चुना हो.

stream (डिफ़ॉल्ट)
पोज़ डिटेक्टर, सबसे पहले इमेज में दिखने वाले मुख्य व्यक्ति का पता लगाएगा. इसके बाद, पोज़ का पता लगाएगा. इसके बाद के फ़्रेम में, व्यक्ति का पता लगाने वाला चरण तब तक नहीं चलेगा, जब तक व्यक्ति धुंधला न हो जाए या उसकी पहचान न हो पाए. पोज़ डिटेक्टर, मुख्य व्यक्ति को ट्रैक करने की कोशिश करेगा और हर अनुमान में उसका पोज़ दिखाएगा. इससे इंतज़ार का समय कम होता है और पोज़ का पता आसानी से लगाया जा सकता है. वीडियो स्ट्रीम में पोज़ का पता लगाने के लिए, इस मोड का इस्तेमाल करें.
singleImage
पोज़ डिटेक्टर, सबसे पहले व्यक्ति का पता लगाएगा. इसके बाद, पोज़ का पता लगाएगा. व्यक्ति का पता लगाने वाला चरण हर इमेज के लिए चलेगा. इसलिए, इंतज़ार का समय ज़्यादा होगा. साथ ही, व्यक्ति को ट्रैक नहीं किया जा सकेगा. स्टैटिक इमेज में पोज़ का पता लगाने या ट्रैक न करने के लिए, इस मोड का इस्तेमाल करें.

पोज़ डिटेक्टर के विकल्प तय करें:

Swift

// Base pose detector with streaming, when depending on the PoseDetection SDK
let options = PoseDetectorOptions()
options.detectorMode = .stream

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
let options = AccuratePoseDetectorOptions()
options.detectorMode = .singleImage

Objective-C

// Base pose detector with streaming, when depending on the PoseDetection SDK
MLKPoseDetectorOptions *options = [[MLKPoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeStream;

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
MLKAccuratePoseDetectorOptions *options =
    [[MLKAccuratePoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeSingleImage;

आखिर में, PoseDetector का इंस्टेंस पाएं. आपने जो विकल्प तय किए हैं उन्हें पास करें:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. इनपुट इमेज तैयार करना

पोज़ का पता लगाने के लिए, वीडियो की हर इमेज या फ़्रेम के लिए यह तरीका अपनाएं. अगर आपने स्ट्रीम मोड चालू किया है, तो आपको CMSampleBuffer से VisionImage ऑब्जेक्ट बनाने होंगे.

VisionImage ऑब्जेक्ट बनाने के लिए, UIImage या CMSampleBuffer का इस्तेमाल करें.

अगर UIImage का इस्तेमाल किया जाता है, तो यह तरीका अपनाएं:

  • VisionImage ऑब्जेक्ट, UIImage की मदद से बनाएं. पक्का करें कि .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 को, पोज़ डिटेक्टर की इमेज प्रोसेसिंग के किसी एक तरीके में पास करें. एसिंक्रोनस process(image:) या सिंक्रोनस results() तरीके का इस्तेमाल किया जा सकता है.

ऑब्जेक्ट का पता सिंक्रोनस तरीके से लगाने के लिए:

Swift

var results: [Pose]
do {
  results = try poseDetector.results(in: image)
} catch let error {
  print("Failed to detect pose with error: \(error.localizedDescription).")
  return
}
guard let detectedPoses = results, !detectedPoses.isEmpty else {
  print("Pose detector returned no results.")
  return
}

// Success. Get pose landmarks here.

Objective-C

NSError *error;
NSArray *poses = [poseDetector resultsInImage:image error:&error];
if (error != nil) {
  // Error.
  return;
}
if (poses.count == 0) {
  // No pose detected.
  return;
}

// Success. Get pose landmarks here.

ऑब्जेक्ट का पता एसिंक्रोनस तरीके से लगाने के लिए:

Swift

poseDetector.process(image) { detectedPoses, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !detectedPoses.isEmpty else {
    // No pose detected.
    return
  }

  // Success. Get pose landmarks here.
}

Objective-C

[poseDetector processImage:image
                completion:^(NSArray * _Nullable poses,
                             NSError * _Nullable error) {
                    if (error != nil) {
                      // Error.
                      return;
                    }
                    if (poses.count == 0) {
                      // No pose detected.
                      return;
                    }

                    // Success. Get pose landmarks here.
                  }];

4. पोज़ का पता लगने के बाद, उससे जुड़ी जानकारी पाना

अगर इमेज में किसी व्यक्ति का पता चलता है, तो पोज़ का पता लगाने वाला एपीआई, कंप्लीशन हैंडलर को Pose ऑब्जेक्ट की एक कलेक्शन पास करता है. इसके अलावा, कलेक्शन को वापस भी करता है. यह इस बात पर निर्भर करता है कि आपने एसिंक्रोनस या सिंक्रोनस तरीके को कॉल किया है या नहीं.

अगर व्यक्ति पूरी तरह से इमेज में नहीं था, तो मॉडल, फ़्रेम के बाहर के मिसिंग लैंडमार्क के कोऑर्डिनेट असाइन करता है. साथ ही, उन्हें InFrameConfidence की कम वैल्यू देता है.

अगर किसी व्यक्ति का पता नहीं चला, तो कलेक्शन खाली होता है.

Swift

for pose in detectedPoses {
  let leftAnkleLandmark = pose.landmark(ofType: .leftAnkle)
  if leftAnkleLandmark.inFrameLikelihood > 0.5 {
    let position = leftAnkleLandmark.position
  }
}

Objective-C

for (MLKPose *pose in detectedPoses) {
  MLKPoseLandmark *leftAnkleLandmark =
      [pose landmarkOfType:MLKPoseLandmarkTypeLeftAnkle];
  if (leftAnkleLandmark.inFrameLikelihood > 0.5) {
    MLKVision3DPoint *position = leftAnkleLandmark.position;
  }
}

परफ़ॉर्मेंस बेहतर करने के लिए सलाह

नतीजों की क्वालिटी, इनपुट इमेज की क्वालिटी पर निर्भर करती है:

  • ML Kit को पोज़ का सटीक पता लगाने के लिए, इमेज में मौजूद व्यक्ति को पिक्सल डेटा के ज़रिए दिखाया जाना चाहिए. बेहतर परफ़ॉर्मेंस के लिए, विषय कम से कम 256x256 पिक्सल का होना चाहिए.
  • अगर रीयल-टाइम ऐप्लिकेशन में पोज़ का पता लगाया जाता है, तो इनपुट इमेज के कुल डाइमेंशन पर भी ध्यान दिया जा सकता है. छोटी इमेज को तेज़ी से प्रोसेस किया जा सकता है. इसलिए, इंतज़ार का समय कम करने के लिए, कम रिज़ॉल्यूशन पर इमेज कैप्चर करें. हालांकि, रिज़ॉल्यूशन से जुड़ी ऊपर बताई गई ज़रूरी शर्तों को ध्यान में रखें. साथ ही, पक्का करें कि विषय, इमेज के ज़्यादा से ज़्यादा हिस्से में दिखे.
  • इमेज का फ़ोकस खराब होने पर भी, सटीक नतीजे नहीं मिलते. अगर आपको सही नतीजे नहीं मिलते हैं, तो उपयोगकर्ता से इमेज को फिर से कैप्चर करने के लिए कहें.

अगर रीयल-टाइम ऐप्लिकेशन में पोज़ का पता लगाने की सुविधा का इस्तेमाल करना है, तो बेहतर फ़्रेमरेट पाने के लिए, इन दिशा-निर्देशों का पालन करें:

  • PoseDetection के बेस एसडीके टूल और stream डिटेक्शन मोड का इस्तेमाल करें.
  • कम रिज़ॉल्यूशन पर इमेज कैप्चर करने पर विचार करें. हालांकि, इस एपीआई के इमेज डाइमेंशन से जुड़ी ज़रूरी शर्तों को भी ध्यान में रखें.
  • वीडियो फ़्रेम को प्रोसेस करने के लिए, डिटेक्टर के results(in:) सिंक्रोनस एपीआई का इस्तेमाल करें. दिए गए वीडियो फ़्रेम से सिंक्रोनस तरीके से नतीजे पाने के लिए, AVCaptureVideoDataOutputSampleBufferDelegate's captureOutput(_, didOutput:from:) फ़ंक्शन से इस तरीके को कॉल करें. डिटेक्टर को कॉल करने की संख्या कम करने के लिए, AVCaptureVideoDataOutput के alwaysDiscardsLateVideoFrames को हमेशा 'सही' पर सेट करें. अगर डिटेक्टर के चालू रहने के दौरान, वीडियो का कोई नया फ़्रेम उपलब्ध होता है, तो उसे छोड़ दिया जाएगा.
  • अगर इनपुट इमेज पर ग्राफ़िक ओवरले करने के लिए, डिटेक्टर के आउटपुट का इस्तेमाल किया जाता है, तो सबसे पहले ML Kit से नतीजे पाएं. इसके बाद, इमेज रेंडर करें और एक ही चरण में ओवरले करें. ऐसा करने से, प्रोसेस किए गए हर इनपुट फ़्रेम के लिए, डिसप्ले सर्फ़ेस पर सिर्फ़ एक बार रेंडर किया जाता है. उदाहरण के लिए, शोकेस सैंपल ऐप्लिकेशन में previewOverlayView और MLKDetectionOverlayView क्लास देखें.

अगले चरण