מדריך להטמעת תמונות ל-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. הוספת הפריט שתלויות בקובץ build.gradle של פרויקט פיתוח האפליקציה ל-Android. מייבאים את יחסי התלות הנדרשים באמצעות הקוד הבא:

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

דגם

למשימה של הכלי להטמעת תמונות MediaPipe נדרש מודל מאומן שתואם למשימה הזו. לקבלת מידע נוסף על מודלים זמינים מאומנים של כלי להטמעת תמונות, אפשר לעיין במאמר בסקירה הכללית על המשימה בקטע 'מודלים'.

בוחרים את המודל, מורידים אותו ושומרים אותו בספריית הפרויקט:

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

צריך לציין את הנתיב של המודל בתוך הפרמטר ModelAssetPath. ב הקוד לדוגמה מוגדר בפונקציה setupImageEmbedder() ImageEmbedderHelper.kt file:

משתמשים בשיטה BaseOptions.Builder.setModelAssetPath() כדי לציין את הנתיב שבו משתמש המודל. השיטה הזו תופיע בדוגמה של הקוד .

יצירת המשימה

אפשר להשתמש בפונקציה createFromOptions כדי ליצור את המשימה. הפונקציה createFromOptions מקבלת אפשרויות הגדרה כדי להגדיר את כלי ההטמעה אפשרויות. למידע נוסף על אפשרויות ההגדרה, ראו הגדרות אישיות סקירה כללית

במשימה של 'כלי להטמעת תמונות' יש תמיכה ב-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: המצב לקלט של תמונה יחידה.

סרטון: המצב של פריימים מפוענחים בסרטון.

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