מדריך לזיהוי של זיהוי פנים ל-Android

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

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

קוד לדוגמה

קוד הדוגמה של MediaPipe Tasks הוא הטמעה פשוטה של אפליקציית Face Landmarker ל-Android. בדוגמה הזו נעשה שימוש במצלמה במכשיר Android פיזי כדי לזהות פנים בשידור וידאו רציף. האפליקציה יכולה גם לזהות פנים בתמונות ובסרטונים מהגלריה של המכשיר.

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

מורידים את הקוד

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

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

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

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

רכיבים מרכזיים

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

  • FaceLandmarkerHelper.kt – הפונקציה מפעילה את ה-Face Landmarker ומטפלת בבחירת המודל וההענקה.
  • CameraFragment.kt – טיפול במצלמה של המכשיר ועיבוד נתוני הקלט של התמונות והסרטונים.
  • GalleryFragment.kt – הקוד הזה יוצר אינטראקציה עם OverlayView כדי להציג את התמונה או הסרטון בתוצאה.
  • OverlayView.kt – הטמעת המסך עם רשת פנים לפנים שזוהו.

הגדרה

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

יחסי תלות

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

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

דגם

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

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

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

מציינים את הנתיב של המודל בתוך הפרמטר ModelAssetPath. בקוד לדוגמה, המודל מוגדר בקובץ FaceLandmarkerHelper.kt:

baseOptionsBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK)

יצירת המשימה

המשימה של MediaPipe Face Landmarker משתמשת בפונקציה createFromOptions() כדי להגדיר את המשימה. הפונקציה createFromOptions() מקבלת ערכים לאפשרויות ההגדרה. מידע נוסף על אפשרויות ההגדרה זמין במאמר אפשרויות הגדרה.

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

תמונה

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    FaceLandmarker.FaceLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinFaceDetectionConfidence(minFaceDetectionConfidence)
        .setMinTrackingConfidence(minFaceTrackingConfidence)
        .setMinFacePresenceConfidence(minFacePresenceConfidence)
        .setNumFaces(maxNumFaces)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
    

וידאו

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    FaceLandmarker.FaceLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinFaceDetectionConfidence(minFaceDetectionConfidence)
        .setMinTrackingConfidence(minFaceTrackingConfidence)
        .setMinFacePresenceConfidence(minFacePresenceConfidence)
        .setNumFaces(maxNumFaces)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
    

שידור חי

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_FACE_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder = 
    FaceLandmarker.FaceLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinFaceDetectionConfidence(minFaceDetectionConfidence)
        .setMinTrackingConfidence(minFaceTrackingConfidence)
        .setMinFacePresenceConfidence(minFacePresenceConfidence)
        .setNumFaces(maxNumFaces)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()
FaceLandmarker = FaceLandmarker.createFromOptions(context, options)
    

הטמעת הקוד לדוגמה של Face Landmarker מאפשרת למשתמש לעבור בין מצבי העיבוד. הגישה הזו הופכת את הקוד ליצירת המשימות למורכב יותר, ויכול להיות שהיא לא מתאימה לתרחיש לדוגמה שלכם. הקוד הזה מופיע בפונקציה setupFaceLandmarker() בקובץ FaceLandmarkerHelper.kt.

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

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

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

IMAGE: המצב להזנת תמונה אחת.

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

LIVE_STREAM: המצב של סטרימינג בשידור חי של נתוני קלט, למשל ממצלמה. במצב הזה, צריך להפעיל את resultListener כדי להגדיר מאזין שיקבל את התוצאות באופן אסינכרוני.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numFaces המספר המקסימלי של הפנים שאפשר לזהות באמצעות FaceLandmarker. ההחלקה חלה רק כשהערך של num_faces מוגדר ל-1. Integer > 0 1
minFaceDetectionConfidence דירוג האמון המינימלי שדרוש כדי שזיהוי הפנים יחשב כהצלחה. Float [0.0,1.0] 0.5
minFacePresenceConfidence דירוג הוודאות המינימלי של דירוג נוכחות הפנים בזיהוי נקודות ציון בפנים. Float [0.0,1.0] 0.5
minTrackingConfidence דירוג האמון המינימלי שדרוש כדי שהמעקב אחר הפנים ייחשבו כמצליח. Float [0.0,1.0] 0.5
outputFaceBlendshapes אם המערכת של Face Landmarker תייצר צורות פנים משולבות. תבניות עיבוד של פנים משמשות לעיבוד הנתונים של מודל הפנים התלת-ממדי. Boolean False
outputFacialTransformationMatrixes אם הפלט של FaceLandmarker יהיה מטריצת הטרנספורמציה של הפנים. הפונקציה FaceLandmarker משתמשת במטריצה כדי להמיר את נקודות הציון בפנים ממודל פנים קנוני לפנים שזוהה, כדי שמשתמשים יוכלו להחיל אפקטים על נקודות הציון שזוהו. Boolean False
resultListener מגדיר את מאזין התוצאות לקבל את תוצאות ה-landmarker באופן אסינכרוני כש-FaceLandmarker נמצא במצב של שידור חי. אפשר להשתמש בה רק כשמצב ההפעלה מוגדר כ-LIVE_STREAM ResultListener N/A
errorListener הגדרת מאזין אופציונלי לשגיאות. ErrorListener N/A

הכנת הנתונים

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

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

תמונה

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

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()
    

וידאו

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

val argb8888Frame =
    if (frame.config == Bitmap.Config.ARGB_8888) frame
    else frame.copy(Bitmap.Config.ARGB_8888, false)

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(argb8888Frame).build()
    

שידור חי

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

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    

בקוד לדוגמה של Face Landmarker, הכנת הנתונים מתבצעת בקובץ FaceLandmarkerHelper.kt.

הרצת המשימה

בהתאם לסוג הנתונים שאתם עובדים איתו, צריך להשתמש בשיטה FaceLandmarker.detect...() שספציפית לסוג הנתונים הזה. משתמשים ב-detect() לתמונות בודדות, ב-detectForVideo() לפריימים בקובצי וידאו וב-detectAsync() לשידורי וידאו. כשמבצעים זיהויים בסטרימינג של וידאו, חשוב להריץ את הזיהויים בשרשור נפרד כדי למנוע חסימה של שרשור ממשק המשתמש.

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

תמונה

val result = FaceLandmarker.detect(mpImage)
    

וידאו

val timestampMs = i * inferenceIntervalMs

FaceLandmarker.detectForVideo(mpImage, timestampMs)
    .let { detectionResult ->
        resultList.add(detectionResult)
    }
    

שידור חי

val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()

FaceLandmarker.detectAsync(mpImage, frameTime)
    

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

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

בקוד לדוגמה של Face Landmarker, הפונקציות detect,‏ detectForVideo ו-detectAsync מוגדרות בקובץ FaceLandmarkerHelper.kt.

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

ה-Face Landmarker מחזיר אובייקט FaceLandmarkerResult לכל הפעלה של זיהוי. אובייקט התוצאה מכיל רשת פנים לכל פנים שזוהה, עם קואורדינטות לכל ציון דרך בפנים. לחלופין, אובייקט התוצאה יכול להכיל גם צורות מעורבות (blendshapes) שמציינות הבעות פנים ומטריצות טרנספורמציה של פנים כדי להחיל אפקטים על הנקודות החשובות שזוהו.

בהמשך מוצגת דוגמה לנתוני הפלט של המשימה הזו:

FaceLandmarkerResult:
  face_landmarks:
    NormalizedLandmark #0:
      x: 0.5971359014511108
      y: 0.485361784696579
      z: -0.038440968841314316
    NormalizedLandmark #1:
      x: 0.3302789330482483
      y: 0.29289937019348145
      z: -0.09489090740680695
    ... (478 landmarks for each face)
  face_blendshapes:
    browDownLeft: 0.8296722769737244
    browDownRight: 0.8096957206726074
    browInnerUp: 0.00035583582939580083
    browOuterUpLeft: 0.00035752105759456754
    ... (52 blendshapes for each face)
  facial_transformation_matrixes:
    [9.99158978e-01, -1.23036895e-02, 3.91213447e-02, -3.70770246e-01]
    [1.66496094e-02,  9.93480563e-01, -1.12779640e-01, 2.27719707e+01]
    ...

בתמונה הבאה מוצגת תצוגה חזותית של הפלט של המשימה:

גבר עם אזורים של הפנים שלו ממופה באופן גיאומטרי כדי לציין את הצורה והמידות של הפנים שלו

בקוד לדוגמה של Face Landmarker מוסבר איך להציג את התוצאות שמוחזרות מהמשימה. פרטים נוספים זמינים בכיתה OverlayView.