Android के लिए ऑब्जेक्ट का पता लगाने वाली गाइड

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

कोड का उदाहरण

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

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

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

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

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

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

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

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

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

  • ObjectDetectorHelper.kt - ऑब्जेक्ट डिटेक्टर को शुरू करता है और मॉडल और प्रतिनिधि चुनने की प्रोसेस को मैनेज करता है
  • MainActivity.kt - ऐप्लिकेशन को लागू करता है और यूज़र इंटरफ़ेस कॉम्पोनेंट को इकट्ठा करता है
  • OverlayView.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

मॉडल के इस्तेमाल किए गए पाथ की जानकारी देने के लिए, BaseOptions.Builder.setModelAssetPath() वाले तरीके का इस्तेमाल करें. कोड का उदाहरण देखने के लिए, अगला सेक्शन देखें.

टास्क बनाना

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

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

इमेज

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

वीडियो

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

लाइव स्ट्रीम

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(model.tflite).build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
      // Process the detection result here.
    })
    .setErrorListener((result, inputImage) -> {
      // Process the classification errors here.
    })
   .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

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

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

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

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

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

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

LIVE_STREAM: कैमरे से मिले इनपुट डेटा की लाइव स्ट्रीम के लिए मोड. इस मोड में, नतीजे असींक्रोनस तरीके से पाने के लिए, एक listener सेट अप करने के लिए, resultListener को कॉल करना होगा.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocales टास्क के मॉडल के मेटाडेटा में दिए गए डिसप्ले नेम के लिए, लेबल की भाषा सेट करता है. हालांकि, ऐसा तब ही किया जाता है, जब वह भाषा उपलब्ध हो. अंग्रेज़ी के लिए, डिफ़ॉल्ट तौर पर en होता है. TensorFlow Lite मेटाडेटा राइटर एपीआई का इस्तेमाल करके, कस्टम मॉडल के मेटाडेटा में स्थानीय भाषा के लेबल जोड़े जा सकते हैं स्थानीय भाषा का कोड en
maxResults सबसे ज़्यादा स्कोर वाले पहचान के नतीजों की ज़्यादा से ज़्यादा संख्या सेट करता है, ताकि उन्हें दिखाया जा सके. हालांकि, ऐसा करना ज़रूरी नहीं है. कोई भी पॉज़िटिव संख्या -1 (सभी नतीजे दिखाए जाते हैं)
scoreThreshold अनुमान के स्कोर का थ्रेशोल्ड सेट करता है. यह थ्रेशोल्ड, मॉडल के मेटाडेटा में दिए गए थ्रेशोल्ड (अगर कोई है) को बदल देता है. इस वैल्यू से कम के नतीजे अस्वीकार कर दिए जाते हैं. कोई भी फ़्लोट सेट नहीं है
categoryAllowlist कैटगरी के लिए इस्तेमाल किए जा सकने वाले नामों की सूची सेट करता है. हालांकि, यह सूची सेट करना ज़रूरी नहीं है. अगर यह सेट नहीं है, तो कैटगरी के नाम के आधार पर, पहचान के उन नतीजों को फ़िल्टर कर दिया जाएगा जो इस सेट में शामिल नहीं हैं. डुप्लीकेट या अज्ञात कैटगरी के नामों को अनदेखा कर दिया जाता है. यह विकल्प, categoryDenylist के साथ इस्तेमाल नहीं किया जा सकता. दोनों का इस्तेमाल करने पर गड़बड़ी का मैसेज दिखता है. कोई भी स्ट्रिंग सेट नहीं है
categoryDenylist कैटगरी के उन नामों की वैकल्पिक सूची सेट करता है जिनका इस्तेमाल नहीं किया जा सकता. अगर यह सेट खाली नहीं है, तो जिन कैटगरी के नाम इस सेट में शामिल हैं उनके लिए, कॉन्टेंट की पहचान करने की सुविधा से मिले नतीजे फ़िल्टर कर दिए जाएंगे. डुप्लीकेट या अज्ञात कैटगरी के नामों को अनदेखा कर दिया जाता है. यह विकल्प, categoryAllowlist के साथ इस्तेमाल नहीं किया जा सकता. दोनों का इस्तेमाल करने पर गड़बड़ी होती है. कोई भी स्ट्रिंग सेट नहीं है
resultListener ऑब्जेक्ट डिटेक्टर के लाइव स्ट्रीम मोड में होने पर, ऑब्जेक्ट का पता चलने के नतीजे अलग-अलग समय पर पाने के लिए, नतीजा सुनने वाले को सेट करता है. इस विकल्प का इस्तेमाल सिर्फ़ तब किया जा सकता है, जब runningMode को LIVE_STREAM पर सेट किया गया हो. लागू नहीं सेट नहीं है

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

ऑब्जेक्ट डिटेक्टर को इनपुट इमेज या फ़्रेम देने से पहले, आपको उसे com.google.mediapipe.framework.image.MPImage ऑब्जेक्ट में बदलना होगा.

यहां दिए गए उदाहरणों में, उपलब्ध हर तरह के डेटा को प्रोसेस करने के लिए, डेटा को तैयार करने का तरीका बताया गया है:

इमेज

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

// Load an image on the users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

वीडियो

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

// Load a video file on the user's device using MediaMetadataRetriever

// From the videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT values. Use these values
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

लाइव स्ट्रीम

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

ऑब्जेक्ट डिटेक्टर के उदाहरण वाले कोड में, डेटा तैयार करने की प्रोसेस को detectImage(), detectVideoFile(), detectLivestreamFrame() फ़ंक्शन में ObjectDetectorHelper क्लास में मैनेज किया जाता है.

टास्क चलाना

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

नीचे दिए गए कोड सैंपल में, अलग-अलग डेटा मोड में ऑब्जेक्ट डिटेक्टर को चलाने का आसान तरीका बताया गया है:

इमेज

ObjectDetectorResult detectionResult = objectDetector.detect(image);
    

वीडियो

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ObjectDetectorResult detectionResult =
    objectDetector.detectForVideo(image, frameTimestampMs);
    

लाइव स्ट्रीम

// Run inference on the frame. The detection results will be available
// via the `resultListener` provided in the `ObjectDetectorOptions` when
// the object detector was created.
objectDetector.detectAsync(image, frameTimestampMs);
    

ऑब्जेक्ट डिटेक्टर कोड के उदाहरण में, इनमें से हर मोड को लागू करने के बारे में ज़्यादा जानकारी दी गई है: detect(), detectVideoFile(), और detectAsync(). उदाहरण के तौर पर दिए गए कोड की मदद से, उपयोगकर्ता डेटा प्रोसेस करने के उन मोड के बीच स्विच कर सकता है जो शायद आपके इस्तेमाल के उदाहरण के लिए ज़रूरी न हों.

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

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

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

अनुमान लगाने के बाद, ऑब्जेक्ट डिटेक्टर टास्क एक ObjectDetectorResult ऑब्जेक्ट दिखाता है. इसमें, इनपुट इमेज में मिले ऑब्जेक्ट की जानकारी होती है.

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

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

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

बॉउंडिंग बॉक्स से हाइलाइट किए गए दो कुत्ते

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