המשימה MediaPipe HandTimestamper מאפשרת לכם לזהות את ציוני הדרך של הידיים בתמונה. בהוראות הבאות מוסבר איך להשתמש בציון הדרך היד באפליקציות ל-Android. דוגמת הקוד שמתוארת בהוראות אלה זמינה GitHub.
מידע נוסף על היכולות, המודלים ואפשרויות ההגדרה במשימה הזאת, ראו סקירה כללית.
קוד לדוגמה
קוד הדוגמה למשימות MediaPipe הוא הטמעה פשוטה של HandTimestamper לאפליקציה ל-Android. בדוגמה, המצלמה במכשיר Android פיזי משמשת את המצלמה כדי: לזהות ציוני דרך בכתב יד, ולהשתמש בתמונות ובסרטונים מהגלריה כדי לזהות באופן סטטי ציוני דרך של ידיים.
אפשר להשתמש באפליקציה כנקודת התחלה של אפליקציה משלכם ל-Android, או להתייחס אליה כשמשנים אפליקציה קיימת. הקוד לדוגמה של Hand Scoreer מתארח ב- GitHub.
להורדת הקוד
בהוראות הבאות מוסבר איך ליצור עותק מקומי של הדוגמה באמצעות כלי שורת הפקודה git.
כדי להוריד את הקוד לדוגמה:
- משכפלים את מאגר ה-Git באמצעות הפקודה הבאה:
git clone https://github.com/google-ai-edge/mediapipe-samples
- אפשר גם להגדיר את ה-Git למכונת ה-Git לשימוש בקופה מועטה,
כך שיש לכם רק את הקבצים עבור האפליקציה לדוגמה של Hand Lawer:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/hand_landmarker/android
אחרי שיוצרים גרסה מקומית של הקוד לדוגמה, אפשר לייבא את הפרויקט אל Android Studio ולהריץ את האפליקציה. הוראות מופיעות מדריך ההגדרה ל-Android.
רכיבים מרכזיים
הקבצים הבאים מכילים את הקוד החשוב של מאפיין היד הזה אפליקציה לדוגמה לזיהוי:
- HandLandmarkerHelper.kt - הפעלת הגלאי של ציוני הדרך בכתב יד ומטפלת במודל ובהאצלת הגישה בחירה.
- MainActivity.kt -
מטמיע את האפליקציה, כולל קריאה ל-
HandLandmarkerHelper
.
הגדרה
בקטע הזה מתוארים השלבים העיקריים להגדרת סביבת הפיתוח בפרויקטים של קוד שישמשו באופן ספציפי לשימוש ב-Hand לאתרer. למידע כללי על להגדיר את סביבת הפיתוח לשימוש במשימות של MediaPipe, כולל הדרישות לגרסת הפלטפורמה. מדריך ההגדרה ל-Android.
יחסי תלות
במשימה Hand Placeer נעשה שימוש בcom.google.mediapipe:tasks-vision
לספרייה. מוסיפים את התלות הזאת לקובץ build.gradle
של האפליקציה ל-Android:
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
דגם
למשימה MediaPipe HandTimestamper נדרשת חבילת מודלים מאומנת שתואמת ל- במשימה הזאת. לקבלת מידע נוסף על מודלים זמינים שעברו אימון של Hand Scoreer, ראו את הקטע 'מודלים' בסקירה הכללית על המשימה.
בוחרים את המודל, מורידים אותו ושומרים אותו בספריית הפרויקט:
<dev-project-root>/src/main/assets
צריך לציין את הנתיב של המודל בתוך הפרמטר ModelAssetPath
. ב
קוד לדוגמה,
המודל מוגדר HandLandmarkerHelper.kt
file:
baseOptionBuilder.setModelAssetPath(MP_HAND_LANDMARKER_TASK)
יצירת המשימה
המשימה MediaPipe HandTimestamper משתמשת בפונקציה createFromOptions()
כדי להגדיר
למשימה הזו. הפונקציה createFromOptions()
מקבלת ערכים להגדרה
אפשרויות. למידע נוסף על אפשרויות תצורה,
אפשרויות להגדרות.
Hand Placeer תומך ב-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 Scoreer מאפשרת למשתמש לעבור בין
במצבי עיבוד שונים. הגישה הזו הופכת את הקוד ליצירת משימה למורכב יותר
לא מתאים לתרחיש לדוגמה שלכם. אפשר לראות את הקוד הזה
הפונקציה setupHandLandmarker()
HandLandmarkerHelper.kt
חדש.
אפשרויות תצורה
המשימה הזו כוללת את אפשרויות ההגדרה הבאות לאפליקציות ל-Android:
שם האפשרות | תיאור | טווח ערכים | ערך ברירת מחדל |
---|---|---|---|
runningMode |
מגדיר את מצב הריצה של המשימה. יש שלושה סוגים
מצבים: IMAGE: המצב לקלט של תמונה יחידה. סרטון: המצב של פריימים מפוענחים בסרטון. LIVE_STREAM: המצב לשידור חי של קלט נתונים ממצלמה, במצב הזה, resultListener חייב להיות נשלחה קריאה כדי להגדיר אוזן כדי לקבל תוצאות באופן אסינכרוני. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
numHands |
מספר הידיים המקסימלי שזוהה על ידי מזהה ציון הדרך של היד. | Any integer > 0 |
1 |
minHandDetectionConfidence |
ציון הסמך המינימלי שצריך להיות זיהוי היד נחשב למוצלח במודל זיהוי כף היד. | 0.0 - 1.0 |
0.5 |
minHandPresenceConfidence |
ציון הסמך המינימלי של ציון הנוכחות בכף היד לזיהוי מאפיינים של ציוני דרך. במצב וידאו ובמצב 'שידור חי': אם ציון המהימנות של נוכחות היד מהמודל של יד הציון נמצא מתחת את הסף הזה, Hand landmarker מפעיל את המודל לזיהוי כף היד. אחרת, אלגוריתם קל ופשוט למעקב אחר תנועות הידיים קובע את המיקום של את הידים לזיהוי של ציוני הדרך הבאים. | 0.0 - 1.0 |
0.5 |
minTrackingConfidence |
ציון הסמך המינימלי שצריך להביא בחשבון את המעקב אחר היד הפעולה הצליחה. זהו סף IoU של התיבה התוחמת בין הידיים הפריים הנוכחי והפריים האחרון. במצב וידאו ובמצב 'זרם' של Hand Placeer, אם המעקב נכשל, Hand Largeer מפעיל את היד זיהוי וזיהוי אובייקטים. אחרת, התכונה מדלגת על זיהוי היד. | 0.0 - 1.0 |
0.5 |
resultListener |
מגדיר את אוזן התוצאות לקבל את תוצאות הזיהוי
באופן אסינכרוני כשסמן היד נמצא במצב של שידור חי.
רלוונטי רק כשמצב הריצה מוגדר כ-LIVE_STREAM |
לא רלוונטי | לא רלוונטי |
errorListener |
הגדרת האזנה לשגיאות אופציונלית. | לא רלוונטי | לא רלוונטי |
הכנת נתונים
התכונה Handlander עובדת עם תמונות, קובצי וידאו וסרטונים בשידור חי. המשימה מטפל בעיבוד מראש של קלט נתונים, כולל שינוי גודל, סיבוב וערך נירמול.
הקוד הבא מדגים איך להעביר נתונים לצורך עיבוד. תזות הדוגמאות כוללות פרטים על אופן הטיפול בנתונים מתמונות, מקובצי וידאו ומשידורים חיים וידאו בסטרימינג.
תמונה
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()
ב
קוד לדוגמה של HandAdser, הכנת הנתונים מטופלת
HandLandmarkerHelper.kt
חדש.
הרצת המשימה
בהתאם לסוג הנתונים שאתם עובדים איתם, משתמשים באופרטור
HandLandmarker.detect...()
שספציפית לסוג הנתונים הזה. כדאי להשתמש
detect()
לתמונות בודדות,
detectForVideo()
לפריימים בקובצי וידאו, וגם
detectAsync()
לזרמי וידאו. כשאתם מבצעים זיהוי
וידאו בסטרימינג, חשוב לוודא שאתם מריצים את הזיהוי בשרשור נפרד,
וחוסם את ה-thread של ממשק המשתמש.
בדוגמאות הקוד הבאות מוצגות דוגמאות פשוטות להרצת Handmarker במצבי הנתונים השונים האלה:
תמונה
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 Lawer.
- בזמן ההפעלה בתמונה או במצב וידאו, המשימה Handבליטֶר לחסום את השרשור הנוכחי עד שיסיים לעבד את תמונת הקלט מסגרת. כדי לא לחסום את ממשק המשתמש, צריך לבצע את העיבוד שרשור ברקע.
- כשהמשימה הזאת מופעלת במצב שידור חי, המשימה Hand Scoreer לא חוסמת השרשור הנוכחי, אבל חוזר מיד. הוא יפעיל את התוצאה שלו המאזין עם תוצאת הזיהוי בכל פעם שהוא מסיים לעבד מסגרת הקלט. אם נשלחת קריאה לפונקציית הזיהוי במהלך משימת Hand IMAPer עמוס בעיבוד פריים אחר, המשימה תתעלם ממסגרת הקלט החדשה.
ב
קוד הדוגמה של היד של ציון הדרך, detect
, detectForVideo
פונקציות detectAsync
מוגדרות
HandLandmarkerHelper.kt
חדש.
טיפול בתוצאות והצגתן
Hand Placeer יוצר אובייקט תוצאת חיפוש ידני לכל זיהוי לרוץ. אובייקט התוצאה מכיל ציוני דרך של יד בקואורדינטות של תמונה, יד ציוני דרך בעולם מבחינת הקואורדינטות והידיות(יד שמאל/ימין) של את הידיים.
בדוגמה הבאה אפשר לראות את נתוני הפלט מהמשימה:
הפלט של 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 Scoreer מדגים איך להציג
של התוצאות שהוחזרו מהמשימה,
OverlayView
לקבלת פרטים נוספים.