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

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

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

कोड का उदाहरण

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

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

टास्क बनाना

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

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

इमेज

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 टास्क के लिए रनिंग मोड सेट करता है. इसके तीन मोड हैं:

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

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

LIVE_STREAM: कैमरे से मिले इनपुट डेटा की लाइव स्ट्रीम के लिए मोड. इस मोड में, नतीजे असींक्रोनस तरीके से पाने के लिए, एक listener सेट अप करने के लिए, resultListener को कॉल करना होगा.
{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 ऑब्जेक्ट में बदलना होगा.

इमेज

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 value. Youll need them
// 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()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

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

टास्क चलाना

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

इमेज

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));