מדריך לפילוח תמונות ב-Android

המשימה 'פלח התמונות של MediaPipe' מאפשרת לחלק תמונות לאזורים על סמך קטגוריות מוגדרות מראש, ולהשתמש באפקטים חזותיים כמו טשטוש רקע. בהוראות האלה מוסבר איך להשתמש ב'פלח התמונות' באפליקציות ל-Android. דוגמת הקוד שמתוארת בהוראות האלו זמינה ב-GitHub. למידע נוסף על היכולות, המודלים ואפשרויות ההגדרה של המשימה הזו, קראו את הסקירה הכללית.

קוד לדוגמה

דוגמה לקוד משימות של MediaPipe מכילה שני יישומים פשוטים של יישום 'פלח תמונות' ל-Android:

בדוגמאות נעשה שימוש במצלמה במכשיר Android פיזי, כדי לבצע פילוח תמונות בפיד של המצלמה בזמן אמת, או לבחור תמונות וסרטונים מגלריית המכשיר. אפשר להשתמש באפליקציות כנקודת התחלה לאפליקציה משלכם ל-Android, או להתייחס אליהן כשאתם משנים אפליקציה קיימת. הקוד לדוגמה של 'פלח התמונות' מתארח ב-GitHub.

הקטעים הבאים מתייחסים לאפליקציה פלח של תמונות עם מסיכת קטגוריה.

הורדת הקוד

בהוראות הבאות מוסבר איך ליצור עותק מקומי של הקוד לדוגמה באמצעות כלי שורת הפקודה git.

כדי להוריד את הקוד לדוגמה:

  1. משכפלים את מאגר ה-Git באמצעות הפקודה הבאה:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. לחלופין, אפשר להגדיר את מכונת ה-Git לשימוש בקופה עם נפח נתונים נמוך (sparse), כדי שיהיו לכם רק את הקבצים של האפליקציה לדוגמה של 'פלח התמונות':
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/android
    

אחרי שיוצרים גרסה מקומית של הקוד לדוגמה, אפשר לייבא את הפרויקט ל-Android Studio ולהפעיל את האפליקציה. הוראות מפורטות זמינות במדריך ההגדרה ל-Android.

רכיבים עיקריים

הקבצים הבאים מכילים את הקוד החיוני לאפליקציה לדוגמה של פילוח תמונות:

  • ImageSegmenterHelper.kt – מפעיל את המשימה 'פלח של תמונות' ומטפל במודל ובבחירת המשתמשים.
  • CameraFragment.kt – ממשק המשתמש וקוד הבקרה של המצלמה.
  • GalleryFragment.kt – ממשק משתמש וקוד בקרה לבחירת קובצי תמונה ווידאו.
  • OverlayView.kt - טיפול בתוצאות הפילוח ועיצוב שלהן.

הגדרה

בקטע זה מתוארים שלבים עיקריים להגדרת סביבת הפיתוח ופרויקטים של קוד לשימוש ב'פלח התמונות'. במדריך ההגדרה ל-Android תוכלו לקרוא מידע כללי על הגדרת סביבת הפיתוח לשימוש במשימות של MediaPipe, כולל הדרישות לגרסת הפלטפורמה.

יחסי תלות

כלי פלחים של התמונות משתמש בספרייה com.google.mediapipe:tasks-vision. מוסיפים את התלות הזאת לקובץ build.gradle של פרויקט פיתוח האפליקציה ל-Android. מייבאים את יחסי התלות הנדרשים באמצעות הקוד הבא:

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

מודל

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

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

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

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

בקוד לדוגמה של פלח התמונות, המודל מוגדר במחלקה ImageSegmenterHelper.kt בפונקציה setupImageSegmenter().

יצירת המשימה

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

המשימה 'פלח של תמונות' תומכת בסוגים הבאים של נתוני קלט: תמונות סטילס, קובצי וידאו וסטרימינג של וידאו בשידור חי. כשיוצרים את המשימה, צריך לציין את מצב הריצה שתואם לסוג נתוני הקלט. כדי לראות איך יוצרים את המשימה, תוכלו לבחור את הכרטיסייה בהתאם לסוג נתוני הקלט.

תמונה

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

וידאו

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

שידור חי

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

הטמעת הקוד לדוגמה של פילוח התמונות מאפשרת למשתמש לעבור בין מצבי עיבוד. הגישה הזו יוצרת את הקוד ליצירת משימה ועשויה לא להתאים לתרחיש שלכם לדוגמה. אפשר לראות את הקוד הזה במחלקה ImageSegmenterHelper באמצעות הפונקציה setupImageSegmenter().

אפשרויות הגדרה

המשימה כוללת את אפשרויות ההגדרה הבאות לאפליקציות ל-Android:

שם האפשרות תיאור טווח ערכים ערך ברירת מחדל
runningMode מגדיר את מצב הריצה של המשימה. יש שלושה מצבים:

IMAGE: המצב שבו ניתן להזין תמונה יחידה.

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

LIVE_STREAM: המצב עבור סטרימינג בשידור חי של נתוני קלט, למשל ממצלמה. במצב הזה, יש להפעיל את resultListener כדי להגדיר מאזין לקבלת תוצאות באופן אסינכרוני.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask אם המדיניות מוגדרת כ-True, הפלט כולל מסכת פילוח כתמונה של Uint8, וכל ערך של פיקסל מציין את ערך הקטגוריה המנצחת. {True, False} False
outputConfidenceMasks אם היא מוגדרת כ-True, הפלט כולל מסכת פילוח כתמונה של ערך צף, שבה כל ערך צף מייצג את מפת ציון המהימנות של הקטגוריה. {True, False} True
displayNamesLocale ההגדרה הזו מגדירה את השפה של התוויות שישמשו לשמות תצוגה שנמסרים במטא-נתונים של מודל המשימה, אם יש כאלה. ברירת המחדל היא en עבור אנגלית. אפשר להוסיף תוויות שהותאמו לשוק המקומי למטא-נתונים של מודל מותאם אישית באמצעות TensorFlow Lite Metadata Writer API קוד הלוקאל en
resultListener מגדיר את הכלי להאזנה לתוצאות כך שיקבל את תוצאות הפילוח באופן אסינכרוני כאשר מפלח התמונות נמצא במצב שידור חי. אפשר להשתמש רק כשמצב ריצה מוגדר ל-LIVE_STREAM לא רלוונטי לא רלוונטי
errorListener מגדירה האזנה לשגיאות כאופציונלי. לא רלוונטי לא הוגדרה

הכנת הנתונים

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

לפני שמעבירים את התמונה או את המסגרת של הקלט לאובייקט com.google.mediapipe.framework.image.MPImage, צריך להמיר אותם ל-Image segmenter.

תמונה

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

בקוד לדוגמה של פלח התמונות, הכנת הנתונים מתבצעת במחלקה ImageSegmenterHelper על ידי הפונקציה segmentLiveStreamFrame().

מריצים את המשימה.

בחרת להפעיל פונקציית segment אחרת, על סמך מצב הריצה שבו אתה משתמש. הפונקציה של 'פלח התמונות' מחזירה את אזורי הפלח שזוהו בתמונה או במסגרת הקלט.

תמונה

ImageSegmenterResult segmenterResult = imagesegmenter.segment(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.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

שידור חי

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

שימו לב לנקודות הבאות:

  • כשמפעילים את מצב הווידאו או השידור החי, צריך גם לציין את חותמת הזמן של פריים הקלט למשימה של 'פלח התמונות'.
  • כשמפעילים את התכונה 'פלח תמונות' במצב תמונה או במצב וידאו, המשימה 'מפלח תמונות' חוסמת את השרשור הנוכחי עד לסיום העיבוד של התמונה או הפריים שהוגדרו כקלט. כדי לא לחסום את ממשק המשתמש, צריך לבצע את העיבוד בשרשור ברקע.
  • כשמפעילים את התכונה 'פלח של תמונות' במצב שידור חי, המשימה לא חוסמת את השרשור הנוכחי אלא מוחזרת מיד. בכל פעם שהוא יסיים לעבד מסגרת קלט, הוא יפעיל את מאזין התוצאות עם תוצאת הזיהוי. אם מתבצעת קריאה לפונקציה segmentAsync כשהמשימה של פילוח התמונות עסוקה בעיבוד פריים אחר, המשימה מתעלמת ממסגרת הקלט החדשה.

בקוד לדוגמה של פילוח התמונות, הפונקציות segment מוגדרות בקובץ ImageSegmenterHelper.kt.

טיפול בתוצאות והצגתן

לאחר הרצה של ההסקה, המשימה של 'פלח התמונות' מחזירה אובייקט ImageSegmenterResult שמכיל את התוצאות של משימת הפילוח. תוכן הפלט תלוי ב-outputType שהגדרתם כשהגדרתם את המשימה.

בקטעים הבאים מוצגות דוגמאות של נתוני הפלט מהמשימה הזו:

מהימנות הקטגוריה

בתמונות הבאות אפשר לראות המחשה חזותית של פלט המשימה של מסכת ביטחון של קטגוריה. הפלט של מסכת הביטחון מכיל ערכים צפים בין [0, 1].

פלט מסכת המהימנות של התמונה והקטגוריה המקורית. תמונת המקור ממערך הנתונים של Pascal VOC 2012.

ערך קטגוריה

בתמונות הבאות אפשר לראות המחשה חזותית של פלט המשימה של מסכת ערכים של קטגוריה. הטווח של מסכות הקטגוריה הוא [0, 255], וכל ערך של פיקסל מייצג את אינדקס הקטגוריה הזוכה של פלט המודל. אינדקס הקטגוריות הזוכה הוא בעל הניקוד הגבוה ביותר מבין הקטגוריות שהמודל יכול לזהות.

פלט התמונה המקורית של המסכה והקטגוריה. תמונת המקור ממערך הנתונים של Pascal VOC 2012.