המשימה 'זיהוי ציוני דרך של ידיים' ב-MediaPipe מאפשרת לזהות את ציוני הדרך של הידיים בתמונה. בהוראות הבאות מוסבר איך להשתמש ב-Hand Landmarker עם אפליקציות ל-Android. דוגמת הקוד שמתוארת בהוראות האלה זמינה ב-GitHub.
מידע נוסף על היכולות, המודלים והאפשרויות להגדרה של המשימה הזו זמין בסקירה הכללית.
קוד לדוגמה
קוד הדוגמה של MediaPipe Tasks הוא הטמעה פשוטה של אפליקציית Hand Landmarker ל-Android. בדוגמה הזו נעשה שימוש במצלמה של מכשיר Android פיזי כדי לזהות באופן רציף נקודות ציון ביד, ואפשר גם להשתמש בתמונות ובסרטונים מהגלריה של המכשיר כדי לזהות נקודות ציון ביד באופן סטטי.
אפשר להשתמש באפליקציה כנקודת התחלה לאפליקציה משלכם ל-Android, או להיעזר בה כשמשנים אפליקציה קיימת. קוד הדוגמה של Hand Landmarker מתארח ב-GitHub.
מורידים את הקוד
בהוראות הבאות מוסבר איך ליצור עותק מקומי של קוד הדוגמה באמצעות כלי שורת הפקודה git.
כדי להוריד את הקוד לדוגמה:
- משכפלים את מאגר git באמצעות הפקודה הבאה:
git clone https://github.com/google-ai-edge/mediapipe-samples
- אפשר גם להגדיר את מכונה של git כך שתשתמש ב-sparse checkout, כך שיישארו רק הקבצים של אפליקציית הדוגמה Hand Landmarker:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/hand_landmarker/android
אחרי שיוצרים גרסה מקומית של קוד הדוגמה, אפשר לייבא את הפרויקט ל-Android Studio ולהריץ את האפליקציה. להוראות, אפשר לעיין במדריך ההגדרה ל-Android.
רכיבים מרכזיים
הקבצים הבאים מכילים את הקוד החשוב לאפליקציית הדוגמה לזיהוי נקודות ציון ביד:
- HandLandmarkerHelper.kt – הפונקציה מפעילה את השירות לזיהוי נקודות ציון ביד ומטפלת בבחירת המודל והנציג.
- MainActivity.kt – הטמעת האפליקציה, כולל קריאה ל-
HandLandmarkerHelper
.
הגדרה
בקטע הזה מתוארים השלבים העיקריים להגדרת סביבת הפיתוח ופרויקטי הקוד, באופן ספציפי לשימוש ב-Hand Landmarker. למידע כללי על הגדרת סביבת הפיתוח לשימוש במשימות של MediaPipe, כולל דרישות לגרסאות הפלטפורמה, אפשר לעיין במדריך ההגדרה ל-Android.
יחסי תלות
המשימה 'סימון נקודות ציון ביד' משתמשת בספרייה com.google.mediapipe:tasks-vision
. מוסיפים את התלות הזו לקובץ build.gradle
של אפליקציית Android:
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
דגם
כדי לבצע את המשימה 'זיהוי נקודות ציון ביד' ב-MediaPipe, נדרש חבילת מודל מאומנת שתואמת למשימה הזו. מידע נוסף על המודלים המאומנים הזמינים ל-Hand Landmarker זמין בקטע 'מודלים' בסקירה הכללית של המשימה.
בוחרים את המודל ומורידים אותו, ושומרים אותו בספריית הפרויקט:
<dev-project-root>/src/main/assets
מציינים את הנתיב של המודל בתוך הפרמטר ModelAssetPath
. בקוד לדוגמה, המודל מוגדר בקובץ HandLandmarkerHelper.kt
:
baseOptionBuilder.setModelAssetPath(MP_HAND_LANDMARKER_TASK)
יצירת המשימה
כדי להגדיר את המשימה של MediaPipe Hand Landmarker, משתמשים בפונקציה createFromOptions()
. הפונקציה createFromOptions()
מקבלת ערכים לאפשרויות ההגדרה. מידע נוסף על אפשרויות ההגדרה זמין במאמר אפשרויות הגדרה.
התכונה 'סימון נקודות על ידי יד' תומכת ב-3 סוגי נתוני קלט: תמונות סטילס, קובצי וידאו ושידור חי. כשיוצרים את המשימה, צריך לציין את מצב ההפעלה התואם לסוג נתוני הקלט. בוחרים את הכרטיסייה שמתאימה לסוג נתוני הקלט כדי לראות איך יוצרים את המשימה ומריצים את ההסקה.
תמונה
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = HandLandmarker.HandLandmarkerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setNumHands(maxNumHands) .setRunningMode(RunningMode.IMAGE) val options = optionsBuilder.build() handLandmarker = HandLandmarker.createFromOptions(context, options)
וידאו
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = HandLandmarker.HandLandmarkerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setNumHands(maxNumHands) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() handLandmarker = HandLandmarker.createFromOptions(context, options)
שידור חי
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = HandLandmarker.HandLandmarkerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setNumHands(maxNumHands) .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() handLandmarker = HandLandmarker.createFromOptions(context, options)
הטמעת הקוד לדוגמה של Hand Landmarker מאפשרת למשתמש לעבור בין מצבי העיבוד. הגישה הזו הופכת את הקוד ליצירת המשימות למורכב יותר, ויכול להיות שהיא לא מתאימה לתרחיש לדוגמה שלכם. הקוד הזה מופיע בפונקציה setupHandLandmarker()
בקובץ HandLandmarkerHelper.kt
.
אפשרויות הגדרה
למשימה הזו יש את אפשרויות התצורה הבאות לאפליקציות ל-Android:
שם האפשרות | תיאור | טווח ערכים | ערך ברירת מחדל |
---|---|---|---|
runningMode |
הגדרת מצב ההפעלה של המשימה. יש שלושה מצבים: IMAGE: המצב להזנת תמונה אחת. VIDEO: המצב של פריימים מפוענחים של סרטון. LIVE_STREAM: המצב של סטרימינג בשידור חי של נתוני קלט, למשל ממצלמה. במצב הזה, צריך להפעיל את resultListener כדי להגדיר מאזין שיקבל את התוצאות באופן אסינכרוני. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
numHands |
המספר המקסימלי של ידיים שזוהו על ידי הגלאי של נקודות ציון ביד. | Any integer > 0 |
1 |
minHandDetectionConfidence |
ציון האמון המינימלי שדרוש כדי שזיהוי היד ייחשב מוצלח במודל לזיהוי כף היד. | 0.0 - 1.0 |
0.5 |
minHandPresenceConfidence |
דירוג האמון המינימלי של דירוג נוכחות היד במודל לזיהוי ציוני ציון ביד. במצב וידאו ובמצב שידור חי, אם דירוג האמינות של נוכחות היד ממודל ציון הנקודות ביד נמוך מהסף הזה, הכלי לזיהוי נקודות ביד מפעיל את מודל זיהוי כף היד. אחרת, אלגוריתם קל למעקב אחר הידיים קובע את המיקום שלהן לצורך זיהוי של נקודות ציון בהמשך. | 0.0 - 1.0 |
0.5 |
minTrackingConfidence |
דירוג האמון המינימלי שדרוש כדי שהמעקב אחר הידיים יחשב כהצלחה. זהו סף IoU של תיבת ההיקף בין הידיים בפריים הנוכחי לבין הפריים האחרון. במצב וידאו ובמצב סטרימינג של Hand Landmarker, אם המעקב נכשל, התכונה Hand Landmarker מפעילה זיהוי של היד. אחרת, המערכת תדלג על זיהוי היד. | 0.0 - 1.0 |
0.5 |
resultListener |
מגדיר את מאזין התוצאות כך שיקבל את תוצאות הזיהוי באופן אסינכרוני כשכלי הסימון של כף היד נמצא במצב של שידור חי.
רלוונטי רק כשמצב ההפעלה מוגדר כ-LIVE_STREAM |
לא רלוונטי | לא רלוונטי |
errorListener |
הגדרת מאזין אופציונלי לשגיאות. | לא רלוונטי | לא רלוונטי |
הכנת הנתונים
התכונה 'סימון נקודות עניין ביד' פועלת עם תמונות, קובצי וידאו וסרטונים בשידור חי. המשימה מטפלת בעיבוד מקדים של קלט הנתונים, כולל שינוי גודל, סיבוב ונירמול ערכים.
הקוד הבא מראה איך מעבירים נתונים לעיבוד. הדוגמאות האלה כוללות פרטים על אופן הטיפול בנתונים מתמונות, מקובצי וידאו ומשידורי וידאו חיים.
תמונה
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()
בקוד לדוגמה של תיוג נקודות ציון ביד, הכנת הנתונים מתבצעת בקובץ HandLandmarkerHelper.kt
.
הרצת המשימה
בהתאם לסוג הנתונים שאתם עובדים איתו, צריך להשתמש בשיטה HandLandmarker.detect...()
שספציפית לסוג הנתונים הזה. משתמשים ב-detect()
לתמונות בודדות, ב-detectForVideo()
לפריימים בקובצי וידאו וב-detectAsync()
לשידורי וידאו. כשמבצעים זיהויים בסטרימינג של וידאו, חשוב להריץ את הזיהויים בשרשור נפרד כדי למנוע חסימה של שרשור ממשק המשתמש.
בדוגמאות הקוד הבאות מפורטות דוגמאות פשוטות להפעלת Hand Landmarker במצבי הנתונים השונים האלה:
תמונה
val result = handLandmarker?.detect(mpImage)
וידאו
val timestampMs = i * inferenceIntervalMs handLandmarker?.detectForVideo(mpImage, timestampMs) ?.let { detectionResult -> resultList.add(detectionResult) }
שידור חי
val mpImage = BitmapImageBuilder(rotatedBitmap).build() val frameTime = SystemClock.uptimeMillis() handLandmarker?.detectAsync(mpImage, frameTime)
שימו לב לנקודות הבאות:
- כשמריצים את המשימה במצב וידאו או במצב של שידור חי, צריך לספק גם את חותמת הזמן של פריים הקלט למשימה Hand Landmarker.
- כשהיא פועלת במצב תמונה או במצב וידאו, המשימה 'סימון נקודות ציון ביד' תמנע את המשך הפעילות של השרשור הנוכחי עד שיסתיים עיבוד התמונה או הפריים של הקלט. כדי למנוע חסימה של ממשק המשתמש, צריך להריץ את העיבוד בשרשור רקע.
- כשהיא פועלת במצב של שידור חי, המשימה של תיוג ידיים לא חוסמת את השרשור הנוכחי אלא חוזרת מיד. הוא יפעיל את מאזין התוצאות שלו עם תוצאת הזיהוי בכל פעם שהוא יסיים לעבד מסגרת קלט. אם פונקציית הזיהוי מופעלת בזמן שהמשימה של Hand Landmarker עסוקה בעיבוד של פריים אחר, המשימה תתעלם מפריים הקלט החדש.
בקוד לדוגמה של תיוג נקודות ציון ביד, הפונקציות detect
, detectForVideo
ו-detectAsync
מוגדרות בקובץ HandLandmarkerHelper.kt
.
טיפול בתוצאות והצגתן
ה-Hand Landmarker יוצר אובייקט תוצאה של Hand Landmarker לכל הפעלה של זיהוי. אובייקט התוצאה מכיל ציוני ציון של היד בקואורדינטות התמונה, ציוני ציון של היד בקואורדינטות העולם ואת היד הדומיננטית(יד ימין/יד שמאל) של הידיים שזוהו.
בהמשך מוצגת דוגמה לנתוני הפלט של המשימה הזו:
הפלט של HandLandmarkerResult
מכיל שלושה רכיבים. כל רכיב הוא מערך, שבו כל רכיב מכיל את התוצאות הבאות לגבי יד אחת שזוהתה:
יד דומיננטית
היד הדומיננטית מייצגת אם הידיים שזוהו הן יד שמאל או יד ימין.
ציוני דרך
יש 21 נקודות ציון ביד, כל אחת מורכבת מהקואורדינטות
x
, y
ו-z
. הקואורדינטותx
ו-y
מתכווננות לטווח [0.0, 1.0] לפי רוחב התמונה וגובהה, בהתאמה. הקואורדינטהz
מייצגת את עומק ציון הדרך, כאשר עומק פרק כף היד הוא המקור. ככל שהערך קטן יותר, כך ציון הדרך קרוב יותר למצלמה. הערך שלz
משתמש בערך באותו סולם כמוx
.אתרים חשובים בעולם
21 נקודות הציון של היד מוצגות גם בקואורדינטות גלובליות. כל ציון דרך מורכב מ-
x
, y
ו-z
, שמייצגים קואורדינטות תלת-ממדיות בעולם האמיתי במטרים, כאשר המקור נמצא במרכז הגיאומטרי של היד.
HandLandmarkerResult:
Handedness:
Categories #0:
index : 0
score : 0.98396
categoryName : Left
Landmarks:
Landmark #0:
x : 0.638852
y : 0.671197
z : -3.41E-7
Landmark #1:
x : 0.634599
y : 0.536441
z : -0.06984
... (21 landmarks for a hand)
WorldLandmarks:
Landmark #0:
x : 0.067485
y : 0.031084
z : 0.055223
Landmark #1:
x : 0.063209
y : -0.00382
z : 0.020920
... (21 world landmarks for a hand)
בתמונה הבאה מוצגת תצוגה חזותית של הפלט של המשימה:
בקוד לדוגמה של Hand Landmarker מוסבר איך להציג את התוצאות שמוחזרות מהמשימה. פרטים נוספים זמינים בכיתה OverlayView
.