Android के लिए लैंडमार्क का पता लगाने की गाइड

MediaPipe Pose लैंडमार्क टास्क की मदद से, किसी इमेज या वीडियो में मानव शरीर की लैंडमार्क का पता लगाया जा सकता है. इस टास्क का इस्तेमाल, शरीर के मुख्य जगहों की पहचान करने, पॉस्चर का विश्लेषण करने, और शरीर की गतिविधियों को कैटगरी में बांटने के लिए किया जा सकता है. यह टास्क मशीन लर्निंग (एमएल) मॉडल का इस्तेमाल करता है, जो एक इमेज या वीडियो के साथ काम करता है. इस टास्क में, इमेज को निर्देशांकों और 3-डाइमेंशन वाले दुनिया के निर्देशांकों में शरीर की जगहों को दिखाने की सुविधा मिलती है.

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

कोड का उदाहरण

MediaPipe Tasks का उदाहरण कोड, Android के लिए पोज़ लैंडमार्कर ऐप्लिकेशन को आसानी से लागू करने का तरीका है. इस उदाहरण में, Android डिवाइस के कैमरे का इस्तेमाल किया गया है, ताकि लगातार वीडियो स्ट्रीम में अलग-अलग पोज़ का पता लगाया जा सके. ऐप, डिवाइस की गैलरी से इमेज और वीडियो में मौजूद पोज़ का भी पता लगा सकता है.

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

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

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

उदाहरण कोड डाउनलोड करने के लिए:

  1. नीचे दिए गए निर्देश का इस्तेमाल करके, गिट रिपॉज़िटरी का क्लोन बनाएं:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. इसके अलावा, स्पार्स चेकआउट का इस्तेमाल करने के लिए अपने git इंस्टेंस को कॉन्फ़िगर करें. ऐसा करने से, आपके पास सिर्फ़ 'पोज़ लैंडमार्कर के उदाहरण वाले ऐप्लिकेशन' की फ़ाइलें रहेंगी:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/pose_landmarker/android
    

उदाहरण कोड का स्थानीय वर्शन बनाने के बाद, प्रोजेक्ट को Android Studio में इंपोर्ट किया जा सकता है. इसके बाद, ऐप्लिकेशन को चलाया जा सकता है. निर्देशों के लिए, Android के लिए सेटअप गाइड देखें.

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

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

  • PoseLandmarkerHelper.kt - पोज़ लैंडमार्कर को शुरू करता है और मॉडल और डेलिगेट को चुनने का काम मैनेज करता है.
  • CameraFragment.kt - डिवाइस के कैमरे को हैंडल करता है और इमेज और वीडियो के इनपुट डेटा को प्रोसेस करता है.
  • GalleryFragment.kt - आउटपुट इमेज या वीडियो दिखाने के लिए OverlayView के साथ इंटरैक्ट करता है.
  • OverlayView.kt - पता लगाए गए पोज़ के लिए डिसप्ले लागू करता है.

सेटअप

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

डिपेंडेंसी

'पोज़ लैंडमार्क' टास्क, com.google.mediapipe:tasks-vision लाइब्रेरी का इस्तेमाल करता है. अपने Android ऐप्लिकेशन की build.gradle फ़ाइल पर यह डिपेंडेंसी जोड़ें:

dependencies {
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

मॉडल

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

मॉडल चुनें और डाउनलोड करें और इसे अपनी प्रोजेक्ट डायरेक्ट्री में स्टोर करें:

<dev-project-root>/src/main/assets

ModelAssetPath पैरामीटर में मॉडल का पाथ बताएं. उदाहरण कोड में, मॉडल की जानकारी PoseLandmarkerHelper.kt फ़ाइल में दी गई है:

val modelName = "pose_landmarker_lite.task"
baseOptionsBuilder.setModelAssetPath(modelName)

टास्क बनाएं

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

'पोज़ लैंडमार्क' इन इनपुट डेटा टाइप के साथ काम करता है: स्टिल इमेज, वीडियो फ़ाइलें, और लाइव वीडियो स्ट्रीम. टास्क बनाते समय, आपको अपने इनपुट डेटा टाइप से मेल खाने वाला 'रनिंग मोड' तय करना होगा. टास्क बनाने का तरीका देखने के लिए, अपने इनपुट डेटा टाइप के लिए टैब चुनें.

Image

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    

वीडियो

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    

लाइव स्ट्रीम

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    

पोज़ लैंडमार्कर के उदाहरण कोड को लागू करने पर, उपयोगकर्ता एक से दूसरे प्रोसेस मोड पर स्विच कर सकता है. यह तरीका टास्क बनाने वाले कोड को ज़्यादा जटिल बना देता है. ऐसा भी हो सकता है कि वह आपके इस्तेमाल के उदाहरण के लिए सही न हो. आपके पास इस कोड को PoseLandmarkerHelper.kt फ़ाइल में मौजूद setupPoseLandmarker() फ़ंक्शन में देखने का विकल्प है.

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

इस टास्क में, Android ऐप्लिकेशन के कॉन्फ़िगरेशन के ये विकल्प मौजूद हैं:

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

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

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

LIVE_STREAM: इनपुट डेटा की लाइव स्ट्रीम का मोड, जैसे कि कैमरे से स्ट्रीम किया जाने वाला मोड. इस मोड में, रिज़ल्ट पहचानकर्ता को लिसनर को सेट अप करने के लिए कॉल किया जाना चाहिए, ताकि वह एसिंक्रोनस तरीके से नतीजे पा सके.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numposes पोज़ लैंडमार्कर की मदद से, ज़्यादा से ज़्यादा कितनी मुद्राओं का पता लगाया जा सकता है. Integer > 0 1
minPoseDetectionConfidence पोज़ पहचान के लिए कम से कम कॉन्फ़िडेंस स्कोर को सफल माना जाएगा. Float [0.0,1.0] 0.5
minPosePresenceConfidence पोज़ लैंडमार्क की पहचान में पोज़ वाली मौजूदगी के स्कोर का कम से कम कॉन्फ़िडेंस स्कोर. Float [0.0,1.0] 0.5
minTrackingConfidence पोज़ ट्रैकिंग के लिए ज़रूरी सबसे कम कॉन्फ़िडेंस स्कोर. Float [0.0,1.0] 0.5
outputSegmentationMasks पोज़ लैंडमार्क में दिखाए गए पोज़ के लिए, सेगमेंटेशन मास्क दिखाएगा या नहीं. Boolean False
resultListener जब पोज़ लैंडमार्कर के लाइव स्ट्रीम मोड में होता है, तो यह सुविधा लैंडमार्क के नतीजों को एसिंक्रोनस तरीके से पाने के लिए, नतीजे लिसनर को सेट करती है. सिर्फ़ तब इस्तेमाल किया जा सकता है, जब रनिंग मोड LIVE_STREAM पर सेट हो ResultListener N/A
errorListener गड़बड़ी की जानकारी देने वाला वैकल्पिक लिसनर सेट करता है. ErrorListener N/A

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

'पोज़ लैंडमार्कर' इमेज, वीडियो फ़ाइलों, और लाइव वीडियो स्ट्रीम के साथ काम करता है. यह टास्क, डेटा इनपुट की प्री-प्रोसेसिंग को हैंडल करता है. इसमें साइज़ बदलना, घुमाना, और वैल्यू को सामान्य बनाना भी शामिल है.

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

Image

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()
    

वीडियो

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

val argb8888Frame =
    if (frame.config == Bitmap.Config.ARGB_8888) frame
    else frame.copy(Bitmap.Config.ARGB_8888, false)

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(argb8888Frame).build()
    

लाइव स्ट्रीम

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    

'पोज़ लैंडमार्कर' के उदाहरण कोड में, डेटा तैयार करने का काम PoseLandmarkerHelper.kt फ़ाइल में किया जाता है.

टास्क चलाएं

आपको किस तरह के डेटा के साथ काम करना है, इस आधार पर poseLandmarker.detect...() वाला तरीका इस्तेमाल करें. यह तरीका खास तौर पर उस डेटा टाइप के हिसाब से होना चाहिए. अलग-अलग इमेज के लिए detect(), वीडियो फ़ाइलों में फ़्रेम के लिए detectForVideo(), और वीडियो स्ट्रीम के लिए detectAsync() का इस्तेमाल करें. जब किसी वीडियो स्ट्रीम पर डिटेक्शन चलाया जा रहा हो, तो पक्का करें कि आप डिटेक्शन को किसी अलग थ्रेड पर चलाएं, ताकि उपयोगकर्ता को इंटरपोज़ किए गए थ्रेड को ब्लॉक करने से रोका जा सके.

नीचे दिए गए कोड सैंपल में कुछ आसान उदाहरण दिए गए हैं. इनमें बताया गया है कि इन अलग-अलग डेटा मोड में 'पोज़ लैंडमार्कर' कैसे चलाया जाता है:

Image

val result = poseLandmarker.detect(mpImage)
    

वीडियो

val timestampMs = i * inferenceIntervalMs

poseLandmarker.detectForVideo(mpImage, timestampMs)
    .let { detectionResult ->
        resultList.add(detectionResult)
    }
    

लाइव स्ट्रीम

val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()

poseLandmarker.detectAsync(mpImage, frameTime)
    

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

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

पोज़ लैंडमार्क के उदाहरण कोड में, detect, detectForVideo, और detectAsync फ़ंक्शन के बारे में PoseLandmarkerHelper.kt फ़ाइल में बताया गया है.

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

'पोज़ लैंडमार्क' हर बार चलाए जाने के लिए, एक poseLandmarkerResult ऑब्जेक्ट दिखाता है. नतीजे के ऑब्जेक्ट में, हर पोज़ लैंडमार्क के लिए निर्देशांक होते हैं.

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

PoseLandmarkerResult:
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : 0.129959
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
      visibility   : 0.999909
      presence     : 0.999958
    ... (33 landmarks per pose)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
      visibility   : 0.999976
      presence     : 0.999998
    ... (33 world landmarks per pose)
  SegmentationMasks:
    ... (pictured below)

आउटपुट में हर लैंडमार्क के लिए, सामान्य निर्देशांक (Landmarks) और वर्ल्ड निर्देशांक (WorldLandmarks) दोनों होते हैं.

आउटपुट में ये सामान्य निर्देशांक (Landmarks) होते हैं:

  • x और y: मशहूर निर्देशांक, इमेज की चौड़ाई (x) और ऊंचाई (y) के हिसाब से 0.0 से 1.0 के बीच सामान्य किए जाते हैं.

  • z: लैंडमार्क की गहराई, जहां मूल रूप से कूल्हे के बीच में गहराई होती है. इसकी वैल्यू जितनी छोटी होगी, लैंडमार्क कैमरे के उतना ही करीब होगा. z की तीव्रता करीब x के बराबर स्केल का इस्तेमाल करती है.

  • visibility: इमेज में लैंडमार्क के दिखने की संभावना कितनी होती है.

आउटपुट में नीचे दिए गए दुनिया के निर्देशांक शामिल हैं (WorldLandmarks):

  • x, y, और z: असल दुनिया में 3-डाइमेंशन वाले निर्देशांक, मीटर में. इस तरह के निर्देशांक, कूल्हे की शुरुआत की जगह होते हैं.

  • visibility: इमेज में लैंडमार्क के दिखने की संभावना कितनी होती है.

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

वैकल्पिक सेगमेंटेशन मास्क, इस बात की संभावना बताता है कि हर पिक्सल किसी व्यक्ति से जुड़ा है या नहीं. यह इमेज, टास्क के आउटपुट का सेगमेंटेशन मास्क है:

'पोज़ लैंडमार्कर' के उदाहरण वाले कोड से पता चलता है कि टास्क से दिखाए गए नतीजों को कैसे दिखाया जाता है. ज़्यादा जानकारी के लिए, OverlayView क्लास देखें.