Skip to main content

Annotations & Styling

QuickPose provides high definition annotations at a minimal performance cost.

PointsOverlayMeasuring LineRange Of Motion
Example Example Example 2Example 3

As annotations provide important visual feedback to your users, quickpose defaults to display an annotation for every feature.

There are cases where the body overlay is not automatically drawn:

Exercise GuideInside Box
Example 4Example 4

In the Exercise Guide example, when the user is not standing or performing a move correctly, the body overlay is turned off, providing a visual clue to the user's mistake and does not draw focus from the feedback message "Move arms apart" shown in an overlay.

For Inside Box, developer's have to choose whether to implement the skeleton whilst the user is not in the correct position.


This feature visualizes what landmarks have been found by the underlying ML model.

case showPoints()
case showPoints(style: customStyle) // with a custom style
Model Validation

Use this feature when changing the model complexity, for example for performance tuning, as some model versions don't track the face and hands in the same resolution, so whilst you may get a faster frame rate you may be losing key landmarks you need for your app to work.


Whilst overlays are returned in overlay image, they don't provide a numeric result. These are intended to provide visual feedback to the user, and are often included in higher level features such as range of motion or fitness features.

case overlay(feature: Landmarks.Group)
case overlay(feature: Landmarks.Group, style: customStyle) // with a custom style

Overlays accept a landmark group:

case none
case wholeBody
case wholeBodyAndHead
case upperBody
case straightArmsUpperBody
case toWristsUpperBody
case shoulders

case arm(side: Side)
case armToWrist(side: Side)
case armNoElbow(side: Side)
case straightArm(side: Side)
case hand(side: Side)
case leg(side: Side)

case lowerBody
case hips
case elbows
case knees
case legs
case arms
case head

Customizing annotations

To specify a smaller line width set a relativeLineWidth:

let smallerStyle = QuickPose.Style(relativeLineWidth: 0.33)
let feature1: QuickPose.Feature = .overlay(.upperBody, style: smallerStyle)

The style entries are relative to the original drawn size, so this will be 1/3 of the size of the default line width.

For shrink the angle markers of a range of motion measurement override relativeArcSize and relativeFontSize, as the rangeOfMotion renders text on screen.

let smallerStyle = QuickPose.Style(relativeFontSize: 0.33, relativeArcSize: 0.33, relativeLineWidth: 0.33)
let feature1: QuickPose.Feature = .rangeOfMotion(.shoulder(side: .right, clockwiseDirection: false), style: smallerStyle)
Remove all Annotations

If you would like to see no annotations for your feature set the hidden value to true

let hiddenStyle = QuickPose.Style(isHidden: true)
let feature1: QuickPose.Feature = .overlay(.upperBody, style: hiddenStyle)

However, we don't recommend this approach as annotations give the user feedback that they are visible to the camera, and what is expected of them,

Conditional Styling

QuickPose allows the annotation color to provide visual feedback on a user's movement.

Target RangeWarning

The above gifs demonstrate the two major use cases: displaying visuall when the user has entered a target range or has entered a dangerous range. Keep in mind that target or dangerous ranges vary by user and exercise.

For conditional highlighting when the angle goes above 120 degrees use:

let conditionalStyle = QuickPose.Style(conditionalColors: [QuickPose.Style.ConditionalColor(min: 120, max: nil, color:])
let feature1: QuickPose.Feature = .rangeOfMotion(.shoulder(side: .right, clockwiseDirection: false), style: conditionalStyle)