ML Kit מספק שתי ערכות SDK שעברו אופטימיזציה לזיהוי תנוחה.
שם ה-SDK | PoseDetection | PoseDetectionAccurate |
---|---|---|
הטמעה | הנכסים של המזהה הבסיסי מקושרים לאפליקציה באופן סטטי בזמן ה-build. | נכסים לזיהוי מדויק מקושרים באופן סטטי לאפליקציה בזמן ה-build. |
גודל האפליקציה | עד 29.6MB | עד 33.2MB |
ביצועים | iPhone X: כ-45FPS | iPhone X: כ-29FPS |
רוצה לנסות?
- מומלץ לשחק עם האפליקציה לדוגמה כדי .
לפני שמתחילים
כוללים ב-Podfile את רצפי ה-ML Kit הבאים:
# 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'
אחרי שמתקינים או מעדכנים את רצפי הפרויקט של הפרויקט, פותחים את פרויקט 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 של ההשלמה או מחזירה את המערך,
תלוי אם קראתם לשיטה האסינכרונית או הסנכרונית.
אם האדם לא היה מלא בתוך התמונה, המודל מקצה את נקודות הציון החסרות, הקואורדינטות מחוץ למסגרת ערכי מהימנות של InFrame.
אם לא זוהה אדם, המערך ריק.
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 פיקסלים.
- אם מזהה תנוחה מסוימת באפליקציה בזמן אמת, כדאי גם לבדוק את הממדים הכוללים של תמונות הקלט. אפשר לעבד תמונות קטנות יותר מהר יותר, כדי להפחית את זמן האחזור, לצלם תמונות ברזולוציה נמוכה יותר לעמוד בדרישות הפתרון שהוזכרו למעלה, ולוודא שהנושא עוסק חלק גדול ככל האפשר מהתמונה.
- גם מיקוד תמונה לא טוב יכול להשפיע על רמת הדיוק. אם אתם לא מקבלים תוצאות מקובלות, לבקש מהמשתמש לצלם מחדש את התמונה.
אם אתם רוצים להשתמש בזיהוי תנוחה באפליקציה בזמן אמת, צריך לפעול לפי ההנחיות הבאות כדי להשיג את קצב הפריימים הטוב ביותר:
- שימוש ב-Base PoseDetection SDK ובמצב זיהוי
stream
. - כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב לזכור גם את הדרישות בנוגע למידות תמונה ב-API הזה.
- כדי לעבד פריימים של וידאו, צריך להשתמש ב-API הסינכרוני
results(in:)
של הגלאי. קוראים לשיטה הזו מה-AVCaptureVideoDataOutputSampleBufferDelegate הפונקציה captureOutput(_, didOutput:from:) כדי לקבל באופן סינכרוני תוצאות מהפריים הנתון בסרטון. יש להשאיר את הערך alwaysDiscardsLateVideoFrames של AVCaptureVideoDataOutput כ-TRUE כדי לווסת את הקריאות למזהה. אם פריים חדש לסרטון יהפוך לזמין בזמן שהגלאי פועל, היא תוסר. - אם משתמשים בפלט של הגלאי כדי ליצור שכבת-על של גרפיקה בתמונת הקלט, מקבלים קודם את התוצאה מ-ML Kit ואז מעבדים את התמונה ושכבת-העל בשלב אחד. כך תוכלו לעבד את משטח המסך פעם אחת בלבד עבור כל מסגרת קלט מעובדת. לצפייה previewOverlayView וגם MLKDetectionOverlayView באפליקציה לדוגמה של Showcase.
השלבים הבאים
- כדי ללמוד איך להשתמש בציוני דרך שמבוססים על ציוני דרך שמבוססים על תנוחות, כדאי לעיין בטיפים לסיווג פוזה.
- כדי לראות דוגמה לשימוש ב-API הזה, אפשר לעיין בדוגמה של המדריך למתחילים ל-ML Kit ב-GitHub.