Android के लिए इमेज एम्बेड करने की गाइड

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

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

कोड का उदाहरण

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

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

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

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

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

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

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

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

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

  • ImageEmbedderHelper.kt: इमेज एम्बेडर को शुरू करता है और मॉडल और डेलिगेट को मैनेज करता है.
  • MainActivity.kt: ऐप्लिकेशन को लागू करता है और यूज़र इंटरफ़ेस के कॉम्पोनेंट इकट्ठा करता है.

सेटअप

इस सेक्शन में इमेज एम्बेडर का इस्तेमाल करने के लिए, डेवलपमेंट एनवायरमेंट को सेट अप करने और कोड प्रोजेक्ट को सेट करने के मुख्य तरीके बताए गए हैं. प्लैटफ़ॉर्म के वर्शन की ज़रूरी शर्तों के साथ-साथ MediaPipe टास्क का इस्तेमाल करने के लिए, अपना डेवलपमेंट एनवायरमेंट सेट अप करने की सामान्य जानकारी के लिए, 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 पैरामीटर में मॉडल का पाथ बताएं. उदाहरण कोड में, मॉडल को ImageEmbedderHelper.kt फ़ाइल के setupImageEmbedder() फ़ंक्शन में दिखाया गया है:

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

टास्क बनाएं

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

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

Image

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.IMAGE)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

वीडियो

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.VIDEO)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

लाइव स्ट्रीम

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener((result, inputImage) -> {
         // Process the embedding result here.
    })
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

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

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

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

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

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

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

LIVE_STREAM: इनपुट डेटा की लाइव स्ट्रीम का मोड, जैसे कि कैमरे से स्ट्रीम किया जाने वाला मोड. इस मोड में, रिज़ल्ट पहचानकर्ता को लिसनर को सेट अप करने के लिए कॉल किया जाना चाहिए, ताकि वह एसिंक्रोनस तरीके से नतीजे पा सके.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
l2_normalize रिटर्न किए गए फ़ीचर वेक्टर को L2 स्टैंडर्ड के साथ सामान्य बनाना है या नहीं. इस विकल्प का इस्तेमाल सिर्फ़ तब करें, जब मॉडल में पहले से ही कोई नेटिव L2_NORMALIZATION TFLite Op मौजूद न हो. ज़्यादातर मामलों में, ऐसा पहले से ही होता है और L2 नॉर्मलाइज़ेशन को TFLite अनुमान के ज़रिए पूरा किया जाता है. इसके लिए, इस विकल्प की कोई ज़रूरत नहीं होती. Boolean False
quantize दिखाए गए एम्बेड किए गए मैसेज को स्केलर क्वांटाइज़ेशन के ज़रिए बाइट में मापा जाना चाहिए या नहीं. एम्बेड किए गए डाइमेंशन को यूनिट-नर्म माना जाता है. इसलिए, किसी भी डाइमेंशन की वैल्यू [-1.0, 1.0] में होने की गारंटी होती है. अगर ऐसा नहीं है, तो l2_normalize विकल्प का इस्तेमाल करें. Boolean False
resultListener जब इमेज एम्बेडर लाइव स्ट्रीम मोड में होता है, तो यह नतीजा लिसनर को एम्बेड करने के नतीजों को एसिंक्रोनस तरीके से पाने के लिए सेट करता है. सिर्फ़ तब इस्तेमाल किया जा सकता है, जब रनिंग मोड LIVE_STREAM पर सेट हो लागू नहीं सेट नहीं किया गया है
errorListener गड़बड़ी की जानकारी देने वाला वैकल्पिक लिसनर सेट करता है. लागू नहीं सेट नहीं किया गया है

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

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

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

Image

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

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s 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 video’s metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them
// to calculate the timestamp of each frame later.

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

// Convert the Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

लाइव स्ट्रीम

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

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

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

उदाहरण कोड में, डेटा तैयार करने का काम ImageEmbedderHelper.kt फ़ाइल में किया गया है.

टास्क चलाएं

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

Image

ImageEmbedderResult embedderResult = imageEmbedder.embed(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.
ImageEmbedderResult embedderResult =
    imageEmbedder.embedForVideo(image, frameTimestampMs);
    

लाइव स्ट्रीम


// Run inference on the frame. The embedding results will be available
// via the `resultListener` provided in the `ImageEmbedderOptions` when
// the image embedder was created.
imageEmbedder.embedAsync(image, frameTimestampMs);
    

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

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

उदाहरण के तौर पर दिए गए कोड में, embed फ़ंक्शन को ImageEmbedderHelper.kt फ़ाइल में बताया गया है.

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

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

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

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

यह नतीजा इस इमेज को एम्बेड करके लिया गया था:

ImageEmbedder.cosineSimilarity फ़ंक्शन का इस्तेमाल करके, दो एम्बेड किए गए लिंक की समानता की तुलना की जा सकती है. उदाहरण के लिए, यह कोड देखें.

// Compute cosine similarity.
double similarity = ImageEmbedder.cosineSimilarity(
  result.embeddingResult().embeddings().get(0),
  otherResult.embeddingResult().embeddings().get(0));