The Pose contract
A Pose is one frame of body points. The whole engine trusts that poses follow this contract; if you write your own PoseProvider, it’s up to you to respect it.
public struct Pose: Sendable { public var points: [Joint: CGPoint] public var timestamp: TimeInterval public var imageSize: CGSize? public var confidence: [Joint: Double]}The four rules
Section titled “The four rules”- Image pixels, with
ypointing down. The origin is at the top left, as in UIKit. Don’t use normalized coordinates (0…1) or Vision’s bottom-left origin. - Anatomical sides.
.leftElbowis the patient’s real left elbow. With the front camera the image is mirrored, so the adapter must swap left and right before building the pose. - Only confident points. Low-confidence joints are left out of the dictionary. A missing joint means “I can’t see it”, and the engine treats it that way: it doesn’t measure, doesn’t penalize and reports it as missing.
confidenceis optional. If your detector has no confidence, leave the dictionary empty; confidence metrics will benil.
The 19 joints
Section titled “The 19 joints”Joint follows the 19 points of Vision’s 2D body detector:
| Area | Joints |
|---|---|
| Head | nose, leftEye, rightEye, leftEar, rightEar |
| Midline | neck, root (center of the hips) |
| Arms | leftShoulder, rightShoulder, leftElbow, rightElbow, leftWrist, rightWrist |
| Legs | leftHip, rightHip, leftKnee, rightKnee, leftAnkle, rightAnkle |
To avoid writing side == .left ? .leftKnee : .rightKnee, use the shortcuts:
Joint.knee(.left) // .leftKneeJoint.shoulder(side) // depends on the sideBodySide.right.opposite // .leftReading a pose
Section titled “Reading a pose”if let elbow = pose[.rightElbow] { print(elbow) // CGPoint in pixels}pose.confidence(of: [.rightShoulder, .rightElbow, .rightWrist])// The lowest confidence among the visible ones, or nilimageSize lets you draw the points over the camera view by scaling them to the view’s size.