ערכת ML מספקת שתי ערכות SDK שעברו אופטימיזציה לזיהוי תנוחות.
שם ה-SDK | זיהוי תנוחה | זיהוי תנוחה מדויק |
---|---|---|
יישום | נכסים של מזהה בסיסי מקושרים באופן סטטי לאפליקציה שלכם בזמן הפיתוח. | נכסים של מזהה מדויק מקושרים באופן סטטי לאפליקציה שלכם בזמן היצירה. |
גודל האפליקציה | עד 29.6MB | עד MB 33.2 |
ביצועים | iPhone X: כ-45FPS | iPhone X: כ-29FPS |
אני רוצה לנסות
- כדאי לשחק עם האפליקציה לדוגמה כדי לראות שימוש לדוגמה ב-API הזה.
לפני שמתחילים
כוללים את רכיבי ה-ML Kit ב-Podfile:
# If you want to use the base implementation: pod 'GoogleMLKit/PoseDetection', '3.2.0' # If you want to use the accurate implementation: pod 'GoogleMLKit/PoseDetectionAccurate', '3.2.0'
אחרי התקנה או עדכון של רכיבי ה-pod של הפרויקט, פותחים את הפרויקט ב-Xcode באמצעות
xcworkspace
. קיימת תמיכה ב-ML Kit בגרסה Xcode 13.2.1 ואילך.
1. יצירת מכונה של PoseDetector
כדי לזהות תנוחה בתמונה, קודם כל צריך ליצור מכונה של PoseDetector
ולציין את הגדרות המזהה.
PoseDetector
אפשרויות
מצב זיהוי
PoseDetector
פועל בשני מצבי זיהוי. חשוב לבחור את הקישור שמתאים לתרחיש לדוגמה שלכם.
stream
(ברירת מחדל)- מזהה התנוחה יזהה תחילה את האדם הבולט ביותר בתמונה, ולאחר מכן יפעיל את זיהוי התנוחה. בפריים הבאים, שלב זיהוי האדם לא יתבצע אלא אם האדם יהפוך למוסתר או לא יזוהה יותר ברמת מהימנות גבוהה. מזהה התנוחה ינסה לעקוב אחרי האדם הבולט ביותר ולהחזיר את התנוחה שלו בכל מסקנות. הפעולה הזו מקצרת את זמן האחזור ומחליקה חלק. השתמשו במצב הזה כשאתם רוצים לזהות תנוחה במהלך שידור וידאו.
singleImage
- מזהה התנוחה יזהה אדם מסוים, ולאחר מכן יפעיל את זיהוי התנוחה. שלב זיהוי המשתמש יפעל על כל תמונה, כך שזמן האחזור יהיה גבוה יותר ואין מעקב אחר אנשים. משתמשים במצב הזה כשמשתמשים בזיהוי תנוחות בתמונות סטטיות, או כשלא רוצים להשתמש במעקב.
הגדרת האפשרויות של מזהה התנוחה:
Swift
// Base pose detector with streaming, when depending on the PoseDetection SDK let options = PoseDetectorOptions() options.detectorMode = .stream // Accurate pose detector on static images, when depending on the // PoseDetectionAccurate SDK let options = AccuratePoseDetectorOptions() options.detectorMode = .singleImage
Objective-C
// Base pose detector with streaming, when depending on the PoseDetection SDK MLKPoseDetectorOptions *options = [[MLKPoseDetectorOptions alloc] init]; options.detectorMode = MLKPoseDetectorModeStream; // Accurate pose detector on static images, when depending on the // PoseDetectionAccurate SDK MLKAccuratePoseDetectorOptions *options = [[MLKAccuratePoseDetectorOptions alloc] init]; options.detectorMode = MLKPoseDetectorModeSingleImage;
לבסוף, מקבלים מכונה של PoseDetector
. העברת האפשרויות שציינתם:
Swift
let poseDetector = PoseDetector.poseDetector(options: options)
Objective-C
MLKPoseDetector *poseDetector = [MLKPoseDetector poseDetectorWithOptions:options];
2. מכינים את תמונת הקלט
כדי לזהות תנוחות, יש לבצע את השלבים הבאים בכל תמונה או מסגרת של סרטון.
אם הפעלתם את מצב הסטרימינג, עליכם ליצור VisionImage
אובייקטים מ-CMSampleBuffer
שנ'.
יצירת אובייקט VisionImage
באמצעות UIImage
או CMSampleBuffer
.
אם משתמשים ב-UIImage
, יש לבצע את השלבים הבאים:
- יצירת אובייקט
VisionImage
עםUIImage
. חשוב לציין את.orientation
הנכון.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
אם משתמשים ב-CMSampleBuffer
, יש לבצע את השלבים הבאים:
-
יש לציין את הכיוון של נתוני התמונה שמופיעים ב
CMSampleBuffer
.כדי לקבל את כיוון התמונה:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- יוצרים אובייקט
VisionImage
באמצעות האובייקט והכיוון שלCMSampleBuffer
:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. עיבוד התמונה
מעבירים את VisionImage
אל אחת מהשיטות לעיבוד תמונות במזהה תנוחה. אפשר להשתמש בשיטה process(image:)
האסינכרונית או בשיטה results()
הסינכרונית.
כדי לזהות אובייקטים באופן סינכרוני:
Swift
var results: [Pose] do { results = try poseDetector.results(in: image) } catch let error { print("Failed to detect pose with error: \(error.localizedDescription).") return } guard let detectedPoses = results, !detectedPoses.isEmpty else { print("Pose detector returned no results.") return } // Success. Get pose landmarks here.
Objective-C
NSError *error; NSArray*poses = [poseDetector resultsInImage:image error:&error]; if (error != nil) { // Error. return; } if (poses.count == 0) { // No pose detected. return; } // Success. Get pose landmarks here.
כדי לזהות אובייקטים באופן אסינכרוני:
Swift
poseDetector.process(image) { detectedPoses, error in guard error == nil else { // Error. return } guard !detectedPoses.isEmpty else { // No pose detected. return } // Success. Get pose landmarks here. }
Objective-C
[poseDetector processImage:image completion:^(NSArray* _Nullable poses, NSError * _Nullable error) { if (error != nil) { // Error. return; } if (poses.count == 0) { // No pose detected. return; } // Success. Get pose landmarks here. }];
4. קבלת מידע על התנוחה שצוינה
אם מזוהה אדם בתמונה, ה-API לזיהוי תזוזה מעביר מערך של אובייקטים מסוג Pose
אל ה-handler של ההשלמה או מחזיר את המערך, בהתאם לשיטה שבה השתמשתם בשיטה האסינכרונית או הסינכרונית.
אם האדם לא היה בתוך התמונה, המודל מקצה את נקודות הציון החסרות מחוץ למסגרת ומספק להן ערכים נמוכים של InFrameConsecure.
אם לא זוהה אדם, המערך ריק.
Swift
for pose in detectedPoses { let leftAnkleLandmark = pose.landmark(ofType: .leftAnkle) if leftAnkleLandmark.inFrameLikelihood > 0.5 { let position = leftAnkleLandmark.position } }
Objective-C
for (MLKPose *pose in detectedPoses) { MLKPoseLandmark *leftAnkleLandmark = [pose landmarkOfType:MLKPoseLandmarkTypeLeftAnkle]; if (leftAnkleLandmark.inFrameLikelihood > 0.5) { MLKVision3DPoint *position = leftAnkleLandmark.position; } }
טיפים לשיפור הביצועים
האיכות של התוצאות תלויה באיכות של תמונת הקלט:
- כדי ש-ML Kit יזהה במדויק את התנוחה, האדם שבתמונה צריך להיות מיוצג על ידי מספיק נתוני פיקסלים. לקבלת הביצועים הטובים ביותר, המושא צריך להיות בגודל 256x256 פיקסלים לפחות.
- אם אתם מזהים תנוחה באפליקציה בזמן אמת, מומלץ לשקול גם את המידות הכלליות של תמונות הקלט. אפשר לעבד תמונות קטנות יותר מהר יותר, כדי לקצר את זמן האחזור כדי לצלם תמונות ברזולוציות נמוכות יותר, אבל חשוב לזכור את דרישות הרזולוציה שלמעלה ולוודא שהאובייקט מופיע כמה שיותר בתמונה.
- גם מיקוד לקוי של תמונה יכול להשפיע על הדיוק. אם לא מקבלים תוצאות מקובלות, מבקשים מהמשתמש לצלם מחדש את התמונה.
אם רוצים להשתמש בזיהוי תנוחה באפליקציה בזמן אמת, יש לפעול לפי ההנחיות הבאות כדי להשיג את קצב הפריימים הטוב ביותר:
- שימוש ב-PoseDetection SDK הבסיסי ובמצב זיהוי
stream
. - כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב גם לזכור את הדרישות של מידות התמונה בממשק ה-API הזה.
- לעיבוד מסגרות וידאו, יש להשתמש ב-API הסינכרוני של
results(in:)
של המזהה. קראו לשיטה הזו מתוך הפונקציה captureפלט(_, doפלט:מ:) של AVCaptureVideoDataפלטSampleBufferDelegate כדי לקבל תוצאות סינכרוניות ממסגרת הווידאו הנתונה. משאירים את תמיד מתבטלים ב-AVCaptureVideoDataפלט כוויסות נתונים (throttle) של קריאות אל המזהה. אם פריים חדש של סרטון הופך לזמין בזמן שהמזהה פועל, הוא יוסר. - אם משתמשים בפלט של המזהה כדי להוסיף גרפיקה כשכבת-על בתמונת הקלט, קודם צריך לקבל את התוצאה מ-ML Kit ולאחר מכן לעבד את התמונה ואת שכבת-העל בפעולה אחת. על ידי כך, אתם מבצעים רינדור למשטח התצוגה פעם אחת בלבד לכל מסגרת קלט מעובדת. לצפייה בדוגמה, תוכלו לראות את המחלקות PreviewLayerView ו-MLKDetectionLayerView.
השלבים הבאים
- רוצים לדעת איך משתמשים בציוני דרך כדי לסווג תנוחות? אפשר להיעזר בטיפים לסיווג תנוחה.
- בדוגמה למתחילים של ML Kit ב-GitHub תוכלו לראות דוגמה ל-API הזה.