המשימה 'זיהוי פנים' מאפשרת לך לזהות פנים בתמונה או בסרטון. אפשר להשתמש במשימה הזו מאתרים פנים ותווי פנים בתוך מסגרת. במשימה הזאת נעשה שימוש מודל למידת מכונה (ML) שעובד עם תמונות בודדות או עם שידור רציף של תמונות. פלט המשימה: מיקומים של זיהוי פנים ומפתח זיהוי הפנים הבא נקודות: עין שמאל, עין ימין, קצה אף, פה, טרגדיה של עין שמאל ועין ימין טרגיה.
דוגמת הקוד שמתוארת בהוראות האלה זמינה ב-GitHub. אפשר לראות את המשימה הזו באתר . לקבלת מידע נוסף מידע על היכולות, המודלים ואפשרויות התצורה של אפשרות זו במשימה, סקירה כללית
קוד לדוגמה
קוד הדוגמה למשימות MediaPipe הוא הטמעה פשוטה של גלאי פנים אפליקציה ל-iOS. בדוגמה, נעשה שימוש במצלמה במכשיר Android פיזי כדי לזהות פנים בשידור וידאו רציף. האפליקציה יכולה לזהות פנים גם בתמונות סרטונים מגלריית המכשיר.
אפשר להשתמש באפליקציה כנקודת התחלה של אפליקציה משלך ל-iOS, או להתייחס אליה כשמשנים אפליקציה קיימת. הקוד לדוגמה של 'זיהוי פנים' מתארח ב GitHub.
להורדת הקוד
בהוראות הבאות מוסבר איך ליצור עותק מקומי של הדוגמה באמצעות כלי שורת הפקודה git.
כדי להוריד את הקוד לדוגמה:
משכפלים את מאגר ה-Git באמצעות הפקודה הבאה:
git clone https://github.com/google-ai-edge/mediapipe-samples
לחלופין, להגדיר את מכונת ה-Git שלך לשימוש בקופה עם היעדר תשלום, כדי רק הקבצים לאפליקציה לדוגמה של 'זיהוי פנים':
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/face_detector/ios/
אחרי שתיצרו גרסה מקומית של הקוד לדוגמה, תוכלו להתקין את ספריית המשימות של MediaPipe, פותחים את הפרויקט באמצעות Xcode ומריצים את האפליקציה. עבור ההוראות מפורטות במדריך ההגדרה ל-iOS.
רכיבים מרכזיים
הקבצים הבאים מכילים את הקוד החיוני לדוגמה של 'זיהוי פנים' יישום:
- FaceDetectorService.swift: הפעלת הגלאי, טיפול בבחירת המודל והרצת ההסקה על נתוני הקלט.
- CameraViewController: הטמעה של ממשק המשתמש עבור מצב הקלט של פיד המצלמה בשידור חי והצגת תוצאות הזיהוי באופן חזותי.
- MediaLibraryViewController.swift: הטמעה של ממשק המשתמש עבור מצב הקלט של קובץ תמונה וקובץ וידאו והצגת תוצאות הזיהוי באופן חזותי.
הגדרה
בקטע הזה מתוארים השלבים העיקריים להגדרת סביבת הפיתוח פרויקטים של קוד לשימוש ב'זיהוי פנים'. לקבלת מידע כללי על הגדרת סביבת פיתוח לשימוש במשימות MediaPipe, כולל גרסת פלטפורמה מומלץ לעיין במדריך ההגדרה ל-iOS.
יחסי תלות
התכונה 'זיהוי פנים' משתמשת בספרייה MediaPipeTasksVision
, שצריכה להיות מותקנת
באמצעות CocoaPods. הספרייה תואמת גם לאפליקציות Swift ו-Objective-C
ולא נדרשת הגדרה נוספת ספציפית לשפה.
הוראות להתקנת CocoaPods ב-macOS מפורטות במאמר CocoaPods
במדריך ההתקנה.
לקבלת הוראות ליצירת Podfile
עם ה-pods שדרושים
באפליקציה, קראו את המאמר שימוש
CocoaPods.
מוסיפים את הרצף של MediaPipeTasksVision ב-Podfile
באמצעות הקוד הבא:
target 'MyFaceDetectorApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
אם האפליקציה שלך כוללת יעדים לבדיקת יחידות, יש לעיין במדריך ההגדרה של
iOS למידע נוסף על ההגדרה
Podfile
.
דגם
למשימה 'זיהוי פנים של MediaPipe' נדרש מודל מאומן שתואם ל- במשימה הזו. לקבלת מידע נוסף על המודלים הזמינים המאומנים עבור ב'זיהוי פנים', אפשר לעיין בסקירה הכללית של המשימה מודלים .
בוחרים מודל ומורידים אותו, ומוסיפים אותו לספריית הפרויקט באמצעות Xcode. לקבלת הוראות להוספת קבצים לפרויקט Xcode, קראו את המאמר ניהול קבצים ותיקיות ב-Xcode. project.
משתמשים במאפיין BaseOptions.modelAssetPath
כדי לציין את הנתיב למודל
ב-App Bundle. בקטע הבא מופיע קוד לדוגמה.
יצירת המשימה
כדי ליצור את המשימה 'זיהוי פנים', צריך להפעיל אחד מהמאתחלים שלה.
המאתחל של FaceDetector(options:)
מקבל ערכים להגדרה
אפשרויות.
אם אין לך צורך בגלאי פנים שאותחלו עם הגדרות בהתאמה אישית
אפשר להשתמש במאתחל של FaceDetector(modelPath:)
כדי ליצור
גלאי פנים עם אפשרויות ברירת המחדל. מידע נוסף על הגדרה
אפשרויות נוספות, ראו סקירה כללית של ההגדרות.
במשימה של 'זיהוי פנים' יש תמיכה ב-3 סוגים של נתוני קלט: תמונות סטילס וקובצי וידאו
בסטרימינג של וידאו בשידור חי. כברירת מחדל, FaceDetector(modelPath:)
מאתחל
לתמונות סטילס. אם רוצים שהמשימה תופעל כדי לעבד סרטון
קבצים או שידורים חיים, צריך להשתמש ב-FaceDetector(options:)
כדי לציין את הסרטון
או במצב ריצה בשידור חי. במצב השידור החי נדרשות גם פעולות נוספות
את אפשרות ההגדרה של faceDetectorLiveStreamDelegate
, שמאפשרת
גלאי פנים יספק למקבל הגישה באופן אסינכרוני את תוצאות זיהוי הפנים.
כדי לראות איך יוצרים את המשימה, צריך לבחור את הכרטיסייה שמתאימה למצב הריצה ולהריץ את ההסקה.
Swift
תמונה
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = FaceDetectorOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image let faceDetector = try FaceDetector(options: options)
וידאו
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = FaceDetectorOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video let faceDetector = try FaceDetector(options: options)
שידור חי
import MediaPipeTasksVision // Class that conforms to the `FaceDetectorLiveStreamDelegate` protocol and // implements the method that the face detector calls once it finishes // detecting faces in each input frame. class FaceDetectorResultProcessor: NSObject, FaceDetectorLiveStreamDelegate { func faceDetector( _ faceDetector: FaceDetector, didFinishDetection result: FaceDetectorResult?, timestampInMilliseconds: Int, error: Error?) { // Process the face detection result or errors here. } } let modelPath = Bundle.main.path( forResource: "model", ofType: "tflite") let options = FaceDetectorOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream // Assign an object of the class to the `faceDetectorLiveStreamDelegate` // property. let processor = FaceDetectorResultProcessor() options.faceDetectorLiveStreamDelegate = processor let faceDetector = try FaceDetector(options: options)
Objective-C
תמונה
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPFaceDetectorOptions *options = [[MPPFaceDetectorOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; MPPFaceDetector *faceDetector = [[MPPFaceDetector alloc] initWithOptions:options error:nil];
וידאו
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPFaceDetectorOptions *options = [[MPPFaceDetectorOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; MPPFaceDetector *faceDetector = [[MPPFaceDetector alloc] initWithOptions:options error:nil];
שידור חי
@import MediaPipeTasksVision; // Class that conforms to the `MPPFaceDetectorLiveStreamDelegate` protocol // and implements the method that the face detector calls once it finishes // detecting faces in each input frame. @interface APPFaceDetectorResultProcessor : NSObject@end @implementation APPFaceDetectorResultProcessor - (void)faceDetector:(MPPFaceDetector *)faceDetector didFinishDetectionWithResult:(MPPFaceDetectorResult *)faceDetectorResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the face detector result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPFaceDetectorOptions *options = [[MPPFaceDetectorOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; // Assign an object of the class to the `faceDetectorLiveStreamDelegate` // property. APPFaceDetectorResultProcessor *processor = [APPFaceDetectorResultProcessor new]; options.faceDetectorLiveStreamDelegate = processor; MPPFaceDetector *faceDetector = [[MPPFaceDetector alloc] initWithOptions:options error:nil];
הערה: אם משתמשים במצב סרטון או במצב שידור חי, התכונה 'זיהוי פנים' משתמשת כדי להימנע מהפעלת מודל הזיהוי בכל פריים, וכך להפחית את זמן האחזור.
אפשרויות תצורה
המשימה הזו כוללת את אפשרויות ההגדרה הבאות לאפליקציות ל-iOS:
שם האפשרות | תיאור | טווח ערכים | ערך ברירת מחדל |
---|---|---|---|
runningMode |
מגדיר את מצב הריצה של המשימה. יש שלושה סוגים
מצבים: IMAGE: המצב לקלט של תמונה יחידה. סרטון: המצב של פריימים מפוענחים בסרטון. LIVE_STREAM: המצב לשידור חי של קלט נתונים ממצלמה, במצב הזה, resultListener חייב להיות נשלחה קריאה כדי להגדיר אוזן כדי לקבל תוצאות באופן אסינכרוני. |
{RunningMode.image, RunningMode.video, RunningMode.liveStream } |
RunningMode.image |
minDetectionConfidence |
ציון הסמך המינימלי כדי שזיהוי הפנים ייחשב כמוצלח. | Float [0,1] |
0.5 |
minSuppressionThreshold |
סף המינימום שאינו מקסימלי כדי לזהות פנים, ייחשב כחופף. | Float [0,1] |
0.3 |
הגדרות השידור החי
כשמצב ריצה מוגדר כשידור חי, גלאי הפנים דורש
אפשרות הגדרה נוספת של faceDetectorLiveStreamDelegate
, שמאפשרת
את גלאי הפנים כדי לספק תוצאות זיהוי באופן אסינכרוני. בעל/ת הגישה
מטמיעים את
אמצעי תשלום אחד (faceDetector(_:didFinishDetection:timestampInMilliseconds:error:)
),
שאליו מתבצעת קריאה ב'גלאי הפנים' אחרי עיבוד התוצאות של זיהוי הפנים
בכל מסגרת.
שם האפשרות | תיאור | טווח ערכים | ערך ברירת מחדל |
---|---|---|---|
faceDetectorLiveStreamDelegate |
ההגדרה הזו מאפשרת לקבל תוצאות של זיהוי פנים באופן אסינכרוני באמצעות התכונה 'זיהוי פנים'
במצב סטרימינג בשידור חי. המחלקה שהמופע שלה מוגדר לנכס הזה חייבת
להטמיע את
faceDetector(_:didFinishDetection:timestampInMilliseconds:error:)
. |
לא רלוונטי | לא מוגדר |
הכנת נתונים
צריך להמיר את תמונת הקלט או המסגרת לאובייקט MPImage
לפני
ומעבירים אותו לגלאי הפנים. ב-MPImage
יש תמיכה בסוגים שונים של קובצי תמונה ב-iOS
ויכולים להשתמש בהם בכל מצב ריצה לצורך הסקת מסקנות. לקבלת מידע נוסף
מידע על MPImage
, מתייחס
MPImage API
צריך לבחור פורמט תמונה ל-iOS בהתאם לתרחיש לדוגמה שלכם ולמצב הריצה
מחייב.MPImage
מקבל את UIImage
, CVPixelBuffer
,
CMSampleBuffer
פורמטים של תמונות ל-iOS.
UIImage
הפורמט UIImage
מתאים במיוחד למצבי הריצה הבאים:
תמונות: תמונות מ-App Bundle, מגלריית משתמשים או ממערכת קבצים בפורמט אפשר להמיר
UIImage
תמונות לאובייקטMPImage
.סרטונים: משתמשים ב-AVAssetImageGenerator כדי לחלץ פריימים של וידאו CGImage וממירים אותן ל-
UIImage
תמונות.
Swift
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(uiImage: image)
Objective-C
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
הדוגמה מאתחלת MPImage
עם ברירת המחדל
UIImage.Orientation.Up
לכיוון מסוים. אפשר לאתחל MPImage
עם כל אחד מהפורמטים הנתמכים
UIImage.Orientation
ערכים. התכונה 'זיהוי פנים' לא תומכת בכיוונים מסונכרנים כמו .upMirrored
,
.downMirrored
, .leftMirrored
, .rightMirrored
.
למידע נוסף על UIImage
, יש לעיין ב-UIImage Apple Developer
מסמכים.
CVPixelBuffer
הפורמט CVPixelBuffer
מתאים מאוד לאפליקציות שיוצרות פריימים
ולהשתמש ב-CoreImage של iOS
לעיבוד טקסט.
הפורמט CVPixelBuffer
מתאים במיוחד למצבי הריצה הבאים:
תמונות: אפליקציות שיוצרות
CVPixelBuffer
תמונות לאחר עיבוד מסוים באמצעות המסגרתCoreImage
של iOS ניתן לשלוח אל 'גלאי הפנים' ב מצב הרצת התמונות.סרטונים: ניתן להמיר פריימים של וידאו לפורמט
CVPixelBuffer
עבור מתבצע עיבוד ולאחר מכן נשלחים ל'גלאי הפנים' במצב וידאו.בשידור חי: אפליקציות שמשתמשות במצלמת iOS ליצירת פריימים עשויים לעבור המרה בפורמט
CVPixelBuffer
לעיבוד לפני השליחה גלאי פנים במצב שידור חי.
Swift
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(pixelBuffer: pixelBuffer)
Objective-C
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
כדי לקבל מידע נוסף על CVPixelBuffer
, אפשר לעיין ב-CVPixelBuffer Apple
מפתחי המשחק
מסמכים.
CMSampleBuffer
הפורמט CMSampleBuffer
מאחסן דוגמאות מדיה מסוג מדיה אחיד,
הוא גבוה מאוד למצב ההרצה של השידור החי. הפריימים בשידור חי ממצלמות iOS
מועברים באופן אסינכרוני בפורמט CMSampleBuffer
על ידי iOS
AVCaptureVideoDataOutput.
Swift
// Obtain a CMSampleBuffer. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(sampleBuffer: sampleBuffer)
Objective-C
// Obtain a `CMSampleBuffer`. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
מידע נוסף על CMSampleBuffer
זמין ב-CMSampleBuffer Apple
מפתחי המשחק
מסמכים.
הרצת המשימה
כדי להפעיל את גלאי הפנים, צריך להשתמש בשיטה detect()
הספציפית שהוקצתה
מצב ריצה:
- תמונת סטילס:
detect(image:)
- סרטון:
detect(videoFrame:timestampInMilliseconds:)
- צפייה בשידור חי:
detectAsync(image:timestampInMilliseconds:)
חיישן הפנים מחזיר את הפנים שזוהו בתמונת הקלט או בפריים.
דוגמאות הקוד הבאות מראות פשוטות להרצת גלאי פנים מצבי הריצה השונים הבאים:
Swift
תמונה
let result = try faceDetector.detect(image: image)
וידאו
let result = try faceDetector.detect( videoFrame: image, timestampInMilliseconds: timestamp)
שידור חי
try faceDetector.detectAsync( image: image, timestampInMilliseconds: timestamp)
Objective-C
תמונה
MPPFaceDetectorResult *result = [faceDetector detectInImage:image error:nil];
וידאו
MPPFaceDetectorResult *result = [faceDetector detectInVideoFrame:image timestampInMilliseconds:timestamp error:nil];
שידור חי
BOOL success = [faceDetector detectAsyncInImage:image timestampInMilliseconds:timestamp error:nil];
בדוגמה של הקוד של 'זיהוי פנים' אפשר לראות את ההטמעה של כל אחד מהמצבים האלה
בצורה מפורטת יותר detect(image:)
, detect(videoFrame:timestampInMilliseconds:)
,
ו-detectAsync(image:timestampInMilliseconds:)
. הקוד לדוגמה מאפשר
המשתמש יצטרך לעבור בין מצבי עיבוד שייתכן שהם לא נדרשים לשימוש שלך
מותאמת אישית.
שימו לב לנקודות הבאות:
כשמפעילים במצב וידאו או במצב שידור חי, צריך גם לספק את הפרטים הבאים: חותמת הזמן של מסגרת הקלט למשימה 'זיהוי פנים'.
כשמפעילים את התכונה 'זיהוי פנים', היא חוסמת את את ה-thread הנוכחי עד לסיום העיבוד של תמונת הקלט או המסגרת. שפת תרגום לא לחסום את השרשור הנוכחי, צריך לבצע את העיבוד ברקע שרשור באמצעות iOS שליחה או NSOperation של מסגרות.
כשפועלים במצב שידור חי, המשימה 'זיהוי פנים' חוזרת באופן מיידי והיא לא חוסמת את השרשור הנוכחי. היא מפעילה את אמצעי תשלום אחד (
faceDetector(_:didFinishDetection:timestampInMilliseconds:error:)
) בתוצאת זיהוי הפנים לאחר העיבוד של כל פריים הקלט. חיישן הפנים מפעיל את השיטה הזו באופן אסינכרוני במספר סידורי ייעודי תור השליחה. להצגת תוצאות בממשק המשתמש, יש לשלוח את יוצגו לתור הראשי אחרי עיבוד התוצאות. אםdetectAsync
מתבצעת קריאה לפונקציה כאשר משימת 'זיהוי פנים' עסוקה בעיבוד אחר מסגרת הקלט, 'זיהוי פנים' מתעלם ממסגרת הקלט החדשה.
טיפול בתוצאות והצגתן
כשמריצים את ההסקה, המשימה 'זיהוי פנים' מחזירה 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)
בתמונה הזו אפשר לראות את פלט המשימה:
לתמונה שאין בה תיבות תוחמות, יש לעיין בתמונה המקורית.
הקוד לדוגמה של 'זיהוי פנים' מדגים איך להציג את התוצאות. לצפייה דוגמה לקוד לפרטים.