راهنمای جاسازی تصویر برای اندروید

وظیفه MediaPipe Image Embedder به شما امکان می دهد داده های تصویر را به یک نمایش عددی تبدیل کنید تا وظایف پردازش تصویر مربوط به ML را انجام دهید، مانند مقایسه شباهت دو تصویر. این دستورالعمل ها به شما نحوه استفاده از Image Embedder را با برنامه های Android نشان می دهد.

برای اطلاعات بیشتر در مورد قابلیت‌ها، مدل‌ها و گزینه‌های پیکربندی این کار، به نمای کلی مراجعه کنید.

نمونه کد

کد مثال MediaPipe Tasks یک پیاده سازی ساده از یک برنامه Image Embedder برای اندروید است. این مثال از دوربین یک دستگاه اندروید فیزیکی برای جاسازی مداوم تصاویر استفاده می‌کند و همچنین می‌تواند جاسازی را روی فایل‌های تصویری ذخیره شده در دستگاه اجرا کند.

می‌توانید از برنامه به‌عنوان نقطه شروع برای برنامه اندرویدی خود استفاده کنید یا هنگام تغییر برنامه موجود به آن مراجعه کنید. کد نمونه Image Embedder در GitHub میزبانی می شود.

کد را دانلود کنید

دستورالعمل های زیر به شما نشان می دهد که چگونه با استفاده از ابزار خط فرمان git یک کپی محلی از کد مثال ایجاد کنید.

برای دانلود کد نمونه:

  1. با استفاده از دستور زیر مخزن git را کلون کنید:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. در صورت تمایل، نمونه git خود را برای استفاده از پرداخت پراکنده پیکربندی کنید، بنابراین فقط فایل‌های برنامه نمونه Image Embedder را داشته باشید:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_embedder/android
    

پس از ایجاد یک نسخه محلی از کد نمونه، می توانید پروژه را به اندروید استودیو وارد کرده و برنامه را اجرا کنید. برای دستورالعمل‌ها، به راهنمای راه‌اندازی برای Android مراجعه کنید.

اجزای کلیدی

فایل های زیر حاوی کد حیاتی برای این برنامه نمونه جاسازی تصویر هستند:

  • ImageEmbedderHelper.kt : جاسازی تصویر را راه اندازی می کند و مدل و انتخاب نماینده را مدیریت می کند.
  • MainActivity.kt : برنامه را پیاده سازی می کند و اجزای رابط کاربری را مونتاژ می کند.

راه اندازی

این بخش مراحل کلیدی را برای راه اندازی محیط توسعه و پروژه های کد برای استفاده از Image Embedder توضیح می دهد. برای اطلاعات کلی در مورد تنظیم محیط توسعه خود برای استفاده از وظایف MediaPipe، از جمله الزامات نسخه پلت فرم، به راهنمای راه اندازی برای Android مراجعه کنید.

وابستگی ها

Image Embedder از کتابخانه com.google.mediapipe:tasks-vision استفاده می کند. این وابستگی را به فایل build.gradle پروژه توسعه برنامه اندروید خود اضافه کنید. وابستگی های مورد نیاز را با کد زیر وارد کنید:

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

مدل

وظیفه MediaPipe Image Embedder به یک مدل آموزش دیده نیاز دارد که با این کار سازگار باشد. برای اطلاعات بیشتر در مورد مدل‌های آموزش‌دیده موجود برای Image Embedder، بخش مدل‌های نمای کلی کار را ببینید.

مدل را انتخاب و دانلود کنید و سپس آن را در فهرست پروژه خود ذخیره کنید:

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

مسیر مدل را در پارامتر ModelAssetPath مشخص کنید. در کد مثال، مدل در تابع setupImageEmbedder() در فایل ImageEmbedderHelper.kt تعریف شده است:

از متد BaseOptions.Builder.setModelAssetPath() برای تعیین مسیر استفاده شده توسط مدل استفاده کنید. به این روش در مثال کد در قسمت بعدی اشاره شده است.

کار را ایجاد کنید

برای ایجاد کار می توانید از تابع createFromOptions استفاده کنید. تابع createFromOptions گزینه های پیکربندی را برای تنظیم گزینه های embedder می پذیرد. برای اطلاعات بیشتر در مورد گزینه های پیکربندی، به نمای کلی پیکربندی مراجعه کنید.

وظیفه Image Embedder از 3 نوع داده ورودی پشتیبانی می کند: تصاویر ثابت، فایل های ویدیویی، و جریان های ویدیویی زنده. هنگام ایجاد کار، باید حالت اجرای مربوط به نوع داده ورودی خود را مشخص کنید. برای مشاهده نحوه ایجاد کار و اجرای استنتاج، برگه مربوط به نوع داده ورودی خود را انتخاب کنید.

تصویر

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

اجرای کد مثال به کاربر اجازه می دهد تا بین حالت های پردازش جابجا شود. این رویکرد کد ایجاد کار را پیچیده‌تر می‌کند و ممکن است برای مورد استفاده شما مناسب نباشد. می توانید این کد را در تابع setupImageEmbedder() در فایل ImageEmbedderHelper.kt مشاهده کنید.

گزینه های پیکربندی

این کار دارای گزینه های پیکربندی زیر برای برنامه های Android است:

نام گزینه توضیحات محدوده ارزش مقدار پیش فرض
runningMode حالت اجرا را برای کار تنظیم می کند. سه حالت وجود دارد:

IMAGE: حالت برای ورودی های تک تصویر.

VIDEO: حالت برای فریم های رمزگشایی شده یک ویدیو.

LIVE_STREAM: حالت پخش زنده داده های ورودی، مانند دوربین. در این حالت، 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 شنونده نتیجه را طوری تنظیم می‌کند که وقتی که Image Embedder در حالت پخش زنده است، نتایج جاسازی را به صورت ناهمزمان دریافت کند. فقط زمانی قابل استفاده است که حالت اجرا روی LIVE_STREAM تنظیم شده باشد N/A تنظیم نشده است
errorListener یک شنونده خطای اختیاری را تنظیم می کند. N/A تنظیم نشده است

داده ها را آماده کنید

Image Embedder با تصاویر، فایل ویدئویی و پخش زنده ویدئو کار می کند. این وظیفه، پیش پردازش ورودی داده، از جمله تغییر اندازه، چرخش و نرمال سازی مقدار را انجام می دهد.

شما باید تصویر یا قاب ورودی را قبل از ارسال به وظیفه Image Embedder به یک شی 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);
    

به موارد زیر توجه کنید:

  • هنگام اجرا در حالت ویدئو یا حالت پخش زنده، باید مُهر زمانی فریم ورودی را نیز به وظیفه Image Embedder ارائه دهید.
  • هنگامی که در حالت تصویر یا ویدیو اجرا می شود، وظیفه Image Embedder رشته فعلی را مسدود می کند تا زمانی که پردازش تصویر یا فریم ورودی به پایان برسد. برای جلوگیری از مسدود کردن رشته فعلی، پردازش را در یک موضوع پس‌زمینه اجرا کنید.
  • وقتی در حالت پخش زنده اجرا می شود، وظیفه Image Embedder رشته فعلی را مسدود نمی کند اما بلافاصله برمی گردد. هر بار که پردازش یک فریم ورودی را تمام کند، شنونده نتیجه خود را با نتیجه تشخیص فراخوانی می کند. اگر تابع embedAsync زمانی فراخوانی شود که وظیفه Image Embedder مشغول پردازش یک فریم دیگر است، کار فریم ورودی جدید را نادیده می گیرد.

در کد مثال، تابع embed در فایل ImageEmbedderHelper.kt تعریف شده است.

کنترل و نمایش نتایج

پس از اجرای استنتاج، وظیفه Image Embedder یک شی 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));