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

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

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

קוד לדוגמה

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

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

להורדת הקוד

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

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

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

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

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

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

  • FaceDetectorHelper.kt – הפעלת גלאי הפנים וטיפול במודל ובהענקת גישה בחירה.
  • CameraFragment.kt – המכשיר מטפל במצלמת המכשיר ומעבד את נתוני קלט התמונה והווידאו.
  • GalleryFragment.kt – יוצר אינטראקציה עם OverlayView כדי להציג את הפלט של התמונה או הסרטון.
  • OverlayView.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. ב קוד לדוגמה, המודל מוגדר FaceDetectorHelper.kt file:

val modelName = "face_detection_short_range.tflite"
baseOptionsBuilder.setModelAssetPath(modelName)

יצירת המשימה

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

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

תמונה

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

val optionsBuilder =
    FaceDetector.FaceDetectorOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinDetectionConfidence(threshold)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()

FaceDetector =
    FaceDetector.createFromOptions(context, options)
    

וידאו

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

val optionsBuilder =
    FaceDetector.FaceDetectorOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinDetectionConfidence(threshold)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()

FaceDetector =
    FaceDetector.createFromOptions(context, options)
    

שידור חי

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

val optionsBuilder =
    FaceDetector.FaceDetectorOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinDetectionConfidence(threshold)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()

FaceDetector =
    FaceDetector.createFromOptions(context, options)
    

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

אפשרויות תצורה

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

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

IMAGE: המצב לקלט של תמונה יחידה.

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

LIVE_STREAM: המצב לשידור חי של קלט נתונים ממצלמה, במצב הזה, resultListener חייב להיות נשלחה קריאה כדי להגדיר אוזן כדי לקבל תוצאות באופן אסינכרוני.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
minDetectionConfidence ציון הסמך המינימלי כדי שזיהוי הפנים ייחשב כמוצלח. Float [0,1] 0.5
minSuppressionThreshold סף המינימום שאינו מקסימלי כדי לזהות פנים, ייחשב כחופף. Float [0,1] 0.3
resultListener מגדיר את אוזן התוצאות לקבל את תוצאות הזיהוי באופן אסינכרוני כשזיהוי הפנים פועל בשידור החי במצב תצוגה. אפשר להשתמש באפשרות הזו רק כשמצב הריצה מוגדר ל-LIVE_STREAM. N/A Not set
errorListener הגדרת האזנה לשגיאות אופציונלית. N/A Not set

הכנת נתונים

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

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

תמונה

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

ב הקוד לדוגמה של 'מזהה פנים', הכנת הנתונים מטופלת FaceDetectorHelper.kt חדש.

הרצת המשימה

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

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

תמונה

val result = faceDetector.detect(mpImage)
    

וידאו

val timestampMs = i * inferenceIntervalMs

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

שידור חי

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

faceDetector.detectAsync(mpImage, frameTime)
    

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

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

ב הקוד לדוגמה של 'מזהה הפנים': detect, detectForVideo וגם פונקציות detectAsync מוגדרות FaceDetectorHelper.kt חדש.

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

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

בדוגמה הבאה אפשר לראות את נתוני הפלט מהמשימה:

FaceDetectionResult:
  Detections:
    Detection #0:
      BoundingBox:
        origin_x: 126
        origin_y: 100
        width: 463
        height: 463
      Categories:
        Category #0:
          index: 0
          score: 0.9729152917861938
      NormalizedKeypoints:
        NormalizedKeypoint #0:
          x: 0.18298381567001343
          y: 0.2961040139198303
        NormalizedKeypoint #1:
          x: 0.3302789330482483
          y: 0.29289937019348145
        ... (6 keypoints for each face)
    Detection #1:
      BoundingBox:
        origin_x: 616
        origin_y: 193
        width: 430
        height: 430
      Categories:
        Category #0:
          index: 0
          score: 0.9251380562782288
      NormalizedKeypoints:
        NormalizedKeypoint #0:
          x: 0.6151331663131714
          y: 0.3713381886482239
        NormalizedKeypoint #1:
          x: 0.7460576295852661
          y: 0.38825345039367676
        ... (6 keypoints for each face)

בתמונה הזו אפשר לראות את פלט המשימה:

לתמונה שאין בה תיבות תוחמות, יש לעיין בתמונה המקורית.

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