MediaPipe जेस्चर रेकग्निज़र टास्क की मदद से, रीयल टाइम में हाथ के जेस्चर की पहचान की जा सकती है. साथ ही, इससे हाथ के जेस्चर की पहचान के नतीजे और हाथ के पहचाने गए हिस्सों की जानकारी मिलती है. इन निर्देशों में, Android ऐप्लिकेशन के साथ जेस्चर रेकग्निज़र का इस्तेमाल करने का तरीका बताया गया है. इन निर्देशों में बताया गया कोड सैंपल, GitHub पर उपलब्ध है.
वेब डेमो देखकर, इस टास्क को काम करते हुए देखा जा सकता है. इस टास्क की सुविधाओं, मॉडल, और कॉन्फ़िगरेशन के विकल्पों के बारे में ज़्यादा जानने के लिए, खास जानकारी देखें.
कोड का उदाहरण
MediaPipe Tasks के उदाहरण के तौर पर दिया गया कोड, Android के लिए जेस्चर रेकग्निज़र ऐप्लिकेशन को आसानी से लागू करने का तरीका है. इस उदाहरण में, हाथ के जेस्चर का लगातार पता लगाने के लिए, किसी Android डिवाइस के कैमरे का इस्तेमाल किया गया है. साथ ही, जेस्चर का स्टैटिक तरीके से पता लगाने के लिए, डिवाइस की गैलरी में मौजूद इमेज और वीडियो का भी इस्तेमाल किया जा सकता है.
इस ऐप्लिकेशन का इस्तेमाल, अपने Android ऐप्लिकेशन के लिए शुरुआती बिंदु के तौर पर किया जा सकता है. इसके अलावा, किसी मौजूदा ऐप्लिकेशन में बदलाव करते समय भी इसका इस्तेमाल किया जा सकता है. जेस्चर रेकग्निज़र के उदाहरण का कोड, GitHub पर होस्ट किया गया है.
कोड डाउनलोड करना
यहां दिए गए निर्देशों में, git कमांड-लाइन टूल का इस्तेमाल करके, उदाहरण के कोड की लोकल कॉपी बनाने का तरीका बताया गया है.
उदाहरण के तौर पर दिया गया कोड डाउनलोड करने के लिए:
- यहां दिए गए कमांड का इस्तेमाल करके, Git डेटा स्टोर करने की जगह को क्लोन करें:
git clone https://github.com/google-ai-edge/mediapipe-samples
- इसके अलावा, अपने git इंस्टेंस को स्पैर्स चेकआउट का इस्तेमाल करने के लिए कॉन्फ़िगर करें, ताकि आपके पास सिर्फ़ जेस्चर रिकॉगनाइज़र के उदाहरण वाले ऐप्लिकेशन की फ़ाइलें हों:
cd mediapipe-samples git sparse-checkout init --cone git sparse-checkout set examples/gesture_recognizer/android
उदाहरण के तौर पर दिए गए कोड का लोकल वर्शन बनाने के बाद, प्रोजेक्ट को Android Studio में इंपोर्ट करके ऐप्लिकेशन चलाया जा सकता है. निर्देशों के लिए, Android के लिए सेटअप गाइड देखें.
मुख्य कॉम्पोनेंट
नीचे दी गई फ़ाइलों में, हाथ के जेस्चर की पहचान करने वाले इस ऐप्लिकेशन के उदाहरण का अहम कोड मौजूद है:
- GestureRecognizerHelper.kt - जेस्चर पहचानने वाले टूल को शुरू करता है. साथ ही, मॉडल और प्रतिनिधि चुनने की सुविधा को मैनेज करता है.
- MainActivity.kt - ऐप्लिकेशन को लागू करता है. इसमें
GestureRecognizerHelper
औरGestureRecognizerResultsAdapter
को कॉल करना भी शामिल है. - GestureRecognizerResultsAdapter.kt - नतीजों को मैनेज और फ़ॉर्मैट करता है.
सेटअप
इस सेक्शन में, खास तौर पर जेस्चर रेकग्निज़र का इस्तेमाल करने के लिए, डेवलपमेंट एनवायरमेंट और कोड प्रोजेक्ट सेट अप करने के मुख्य चरणों के बारे में बताया गया है. MediaPipe Tasks का इस्तेमाल करने के लिए, डेवलपमेंट एनवायरमेंट सेट अप करने के बारे में सामान्य जानकारी पाने के लिए, Android के लिए सेटअप गाइड देखें. इसमें प्लैटफ़ॉर्म के वर्शन से जुड़ी ज़रूरी शर्तें भी शामिल हैं.
डिपेंडेंसी
जेस्चर की पहचान करने वाला टास्क, com.google.mediapipe:tasks-vision
लाइब्रेरी का इस्तेमाल करता है. अपने Android ऐप्लिकेशन की build.gradle
फ़ाइल में यह डिपेंडेंसी जोड़ें:
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
मॉडल
MediaPipe जेस्चर पहचानने वाले टास्क के लिए, ट्रेन किए गए मॉडल का बंडल ज़रूरी है, जो इस टास्क के साथ काम करता हो. जेस्चर पहचानने वाले टूल के लिए, पहले से ट्रेन किए गए मॉडल के बारे में ज़्यादा जानने के लिए, टास्क की खास जानकारी वाला मॉडल सेक्शन देखें.
मॉडल चुनें और डाउनलोड करें. इसके बाद, उसे अपनी प्रोजेक्ट डायरेक्ट्री में सेव करें:
<dev-project-root>/src/main/assets
ModelAssetPath
पैरामीटर में मॉडल का पाथ बताएं. उदाहरण के कोड में, मॉडल को GestureRecognizerHelper.kt
फ़ाइल में तय किया गया है:
baseOptionBuilder.setModelAssetPath(MP_RECOGNIZER_TASK)
टास्क बनाना
MediaPipe जेस्चर रेकग्निज़र टास्क, टास्क को सेट अप करने के लिए createFromOptions()
फ़ंक्शन का इस्तेमाल करता है. createFromOptions()
फ़ंक्शन, कॉन्फ़िगरेशन के विकल्पों के लिए वैल्यू स्वीकार करता है. कॉन्फ़िगरेशन के विकल्पों के बारे में ज़्यादा जानने के लिए,
कॉन्फ़िगरेशन के विकल्प देखें.
जेस्चर रिकॉगनिज़र, इनपुट डेटा के तीन टाइप के साथ काम करता है: स्टिल इमेज, वीडियो फ़ाइलें, और लाइव वीडियो स्ट्रीम. टास्क बनाते समय, आपको अपने इनपुट डेटा टाइप के हिसाब से, रनिंग मोड तय करना होगा. टास्क बनाने और अनुमान लगाने का तरीका जानने के लिए, अपने इनपुट डेटा टाइप से जुड़ा टैब चुनें.
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setRunningMode(RunningMode.IMAGE) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) .setRunningMode(RunningMode.LIVE_STREAM) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
जेस्चर पहचानने वाले टूल के उदाहरण के तौर पर दिए गए कोड को लागू करने से, उपयोगकर्ता को प्रोसेसिंग मोड के बीच स्विच करने की अनुमति मिलती है. इस तरीके से, टास्क बनाने का कोड ज़्यादा जटिल हो जाता है और हो सकता है कि यह आपके इस्तेमाल के उदाहरण के लिए सही न हो. इस कोड को GestureRecognizerHelper.kt
फ़ाइल में, setupGestureRecognizer()
फ़ंक्शन में देखा जा सकता है.
कॉन्फ़िगरेशन विकल्प
इस टास्क में, Android ऐप्लिकेशन के लिए कॉन्फ़िगरेशन के ये विकल्प हैं:
विकल्प का नाम | ब्यौरा | वैल्यू की रेंज | डिफ़ॉल्ट मान | |
---|---|---|---|---|
runningMode |
टास्क के लिए रनिंग मोड सेट करता है. इसके तीन मोड हैं: IMAGE: एक इमेज इनपुट के लिए मोड. वीडियो: किसी वीडियो के डिकोड किए गए फ़्रेम के लिए मोड. LIVE_STREAM: कैमरे से मिले इनपुट डेटा की लाइव स्ट्रीम के लिए मोड. इस मोड में, नतीजे असींक्रोनस तरीके से पाने के लिए, एक listener सेट अप करने के लिए, resultListener को कॉल करना होगा. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
|
numHands |
GestureRecognizer की मदद से, ज़्यादा से ज़्यादा जितने हाथों का पता लगाया जा सकता है उतने ही हाथों का पता लगाया जा सकता है.
|
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 |
|
cannedGesturesClassifierOptions |
पहले से तैयार जेस्चर क्लासिफ़ायर के व्यवहार को कॉन्फ़िगर करने के विकल्प. पहले से सेव किए गए जेस्चर ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"] हैं |
|
|
|
customGesturesClassifierOptions |
कस्टम जेस्चर क्लासिफ़ायर के व्यवहार को कॉन्फ़िगर करने के विकल्प. |
|
|
|
resultListener |
जब जेस्चर पहचानने वाला टूल लाइव स्ट्रीम मोड में हो, तब कैटगरी के नतीजे पाने के लिए रिज़ल्ट लिसनर को असिंक्रोनस तरीके से सेट करता है.
इसका इस्तेमाल सिर्फ़ तब किया जा सकता है, जब रनिंग मोड को LIVE_STREAM पर सेट किया गया हो |
ResultListener |
लागू नहीं | लागू नहीं |
errorListener |
गड़बड़ी सुनने वाले को सेट करता है. हालांकि, ऐसा करना ज़रूरी नहीं है. | ErrorListener |
लागू नहीं | लागू नहीं |
डेटा तैयार करना
जेस्चर रिकॉग्निज़र की सुविधा, इमेज, वीडियो फ़ाइल, और लाइव स्ट्रीम वीडियो के साथ काम करती है. यह टास्क, डेटा इनपुट को प्रोसेस करने से पहले की प्रोसेस को मैनेज करता है. इसमें, साइज़ बदलना, घुमाना, और वैल्यू को सामान्य करना शामिल है.
यहां दिए गए कोड में, डेटा को प्रोसेस करने के लिए उसे हैंड ऑफ करने का तरीका बताया गया है. इन सैंपल में, इमेज, वीडियो फ़ाइलों, और लाइव वीडियो स्ट्रीम के डेटा को मैनेज करने का तरीका बताया गया है.
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()
जेस्चर रेकग्निज़र के उदाहरण के कोड में, डेटा तैयार करने की प्रोसेस को GestureRecognizerHelper.kt
फ़ाइल में मैनेज किया जाता है.
टास्क चलाना
अनुमान लगाने के लिए, जेस्चर पहचानने वाला टूल recognize
, recognizeForVideo
, और recognizeAsync
फ़ंक्शन का इस्तेमाल करता है. जेस्चर की पहचान करने के लिए, इनपुट डेटा को पहले से प्रोसेस करना, इमेज में हाथों का पता लगाना, हाथ के लैंडमार्क का पता लगाना, और लैंडमार्क से हाथ के जेस्चर की पहचान करना शामिल है.
नीचे दिए गए कोड में, टास्क मॉडल की मदद से प्रोसेसिंग को लागू करने का तरीका बताया गया है. इन सैंपल में, इमेज, वीडियो फ़ाइलों, और लाइव वीडियो स्ट्रीम के डेटा को मैनेज करने के तरीके के बारे में जानकारी शामिल है.
val result = gestureRecognizer?.recognize(mpImage)
val timestampMs = i * inferenceIntervalMs gestureRecognizer?.recognizeForVideo(mpImage, timestampMs) ?.let { recognizerResult -> resultList.add(recognizerResult) }
val mpImage = BitmapImageBuilder(rotatedBitmap).build() val frameTime = SystemClock.uptimeMillis() gestureRecognizer?.recognizeAsync(mpImage, frameTime)
निम्न पर ध्यान दें:
- वीडियो मोड या लाइव स्ट्रीम मोड में चलाने पर, आपको जेस्चर पहचानने वाले टास्क के लिए, इनपुट फ़्रेम का टाइमस्टैंप भी देना होगा.
- इमेज या वीडियो मोड में चलने पर, जेस्चर पहचानने वाला टास्क, मौजूदा थ्रेड को तब तक ब्लॉक कर देगा, जब तक वह इनपुट इमेज या फ़्रेम को प्रोसेस नहीं कर लेता. यूज़र इंटरफ़ेस को ब्लॉक होने से बचाने के लिए, प्रोसेसिंग को बैकग्राउंड थ्रेड में चलाएं.
- लाइव स्ट्रीम मोड में चलने पर, जेस्चर (हाव-भाव) की पहचान करने वाला टास्क, मौजूदा थ्रेड को ब्लॉक नहीं करता, बल्कि तुरंत वापस आ जाता है. यह हर बार किसी इनपुट फ़्रेम को प्रोसेस करने के बाद, पहचान के नतीजे के साथ अपने नतीजे सुनने वाले को कॉल करेगा. अगर जेस्चर पहचानने वाले टास्क के किसी फ़्रेम को प्रोसेस करने के दौरान, पहचान करने वाले फ़ंक्शन को कॉल किया जाता है, तो टास्क नए इनपुट फ़्रेम को अनदेखा कर देगा.
जेस्चर रेकग्निज़र के उदाहरण वाले कोड में, recognize
, recognizeForVideo
, और recognizeAsync
फ़ंक्शन को GestureRecognizerHelper.kt
फ़ाइल में तय किया गया है.
नतीजों को मैनेज और दिखाना
जेस्चर की पहचान करने वाला टूल, पहचान करने के हर चरण के लिए जेस्चर डिटेक्शन का नतीजा ऑब्जेक्ट जनरेट करता है. नतीजे के ऑब्जेक्ट में, इमेज के कोऑर्डिनेट में हाथ के लैंडमार्क, दुनिया के कोऑर्डिनेट में हाथ के लैंडमार्क, हाथ का इस्तेमाल करने वाला व्यक्ति(बायां/दायां हाथ), और हाथ के जेस्चर की कैटगरी शामिल होती है.
यहां इस टास्क के आउटपुट डेटा का उदाहरण दिया गया है:
नतीजे के तौर पर मिले GestureRecognizerResult
में चार कॉम्पोनेंट होते हैं. हर कॉम्पोनेंट एक कलेक्शन होता है. इसमें हर एलिमेंट में, हाथ के एक हिस्से का पता लगाने से जुड़ा नतीजा होता है.
किसी खास हाथ का इस्तेमाल
इस एट्रिब्यूट से पता चलता है कि पहचाने गए हाथ बाएं हैं या दाएं.
हाथ के जेस्चर
हाथों के जेस्चर की पहचान की गई कैटगरी.
लैंडमार्क
हाथ के 21 लैंडमार्क हैं. हर लैंडमार्क में
x
,y
, औरz
कोऑर्डिनेट होते हैं.x
औरy
निर्देशांक को इमेज की चौड़ाई और ऊंचाई के हिसाब से, [0.0, 1.0] पर नॉर्मलाइज़ किया जाता है.z
निर्देशांक, लैंडमार्क की गहराई दिखाता है. इसमें कलाई की गहराई को ऑरिजिन माना जाता है. वैल्यू जितनी कम होगी, लैंडमार्क कैमरे के उतना ही करीब होगा.z
के मैग्नीट्यूड के लिए,x
के स्केल का इस्तेमाल किया जाता है.विश्व भू-स्थल
हाथ के 21 लैंडमार्क, वर्ल्ड कोऑर्डिनेट में भी दिखाए जाते हैं. हर लैंडमार्क,
x
,y
, औरz
से बना होता है. यह मीटर में, असल दुनिया के 3D कोऑर्डिनेट दिखाता है. इसमें हाथ के ज्यामितीय केंद्र को ऑरिजिन माना जाता है.
GestureRecognizerResult:
Handedness:
Categories #0:
index : 0
score : 0.98396
categoryName : Left
Gestures:
Categories #0:
score : 0.76893
categoryName : Thumb_Up
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)
नीचे दी गई इमेज में, टास्क के आउटपुट को विज़ुअलाइज़ किया गया है:
जेस्चर रेकग्निज़र के उदाहरण वाले कोड में, GestureRecognizerResultsAdapter.kt
फ़ाइल में मौजूद GestureRecognizerResultsAdapter
क्लास, नतीजों को मैनेज करती है.