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

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

דוגמת הקוד שמתוארת בהוראות האלה זמינה ב-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-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/face_landmarker/android
    

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

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

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

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

הגדרה

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

תלויות

המשימה Face Landmarker משתמשת בספרייה 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 הגדרת מצב ההפעלה של המשימה. יש שלושה מצבים:

תמונה: המצב להזנת תמונות בודדות.

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

LIVE_STREAM: המצב לשידור חי של נתוני קלט, למשל ממצלמה. במצב הזה, צריך להפעיל את resultListener כדי להגדיר listener לקבלת תוצאות באופן אסינכרוני.
{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 מוציאה נתוני blendshapes של הפנים. צורות הפנים המעורבות משמשות לעיבוד של התבנית התלת-ממדית לזיהוי הפנים. Boolean False
outputFacialTransformationMatrixes ההגדרה הזו קובעת אם FaceLandmarker יוציא את מטריצת השינוי של הפנים. המודל FaceLandmarker משתמש במטריצה כדי לשנות את נקודות הציון של הפנים ממודל פנים קנוני לפנים שזוהו, כך שהמשתמשים יכולים להחיל אפקטים על נקודות הציון שזוהו. Boolean False
resultListener מגדיר את מאזין התוצאות לקבלת תוצאות של נקודות ציון באופן אסינכרוני כש-FaceLandmarker נמצא במצב שידור חי. אפשר להשתמש בהגדרה הזו רק אם מצב ההפעלה מוגדר ל-LIVE_STREAM ResultListener N/A
errorListener הגדרת פונקציית event listener אופציונלית לשגיאות. 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 במצב תמונה או במצב סרטון, היא חוסמת את השרשור הנוכחי עד שהיא מסיימת לעבד את תמונת הקלט או הפריים. כדי למנוע חסימה של ממשק המשתמש, צריך להריץ את העיבוד בשרשור ברקע.
  • כשמריצים את המשימה במצב שידור חי, היא מחזירה תוצאות באופן מיידי ולא חוסמת את השרשור הנוכחי. הפונקציה תפעיל את מאזין התוצאות עם תוצאת הזיהוי בכל פעם שהיא תסיים לעבד פריים קלט.

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

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

הכלי לזיהוי נקודות ציון בפנים מחזיר אובייקט 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.