Building an AI-Powered Sit-Up Counter App with Pose Estimation Using QuickPose iOS SDK
Are you looking to develop an AI-powered Sit-Up counter for your fitness app? Sit-Ups are a classic core-strengthening exercise that primarily targets the rectus abdominis, often referred to as the “six-pack” muscles. This exercise also engages the hip flexors, obliques, and lower back muscles, making it an essential part of any core workout routine aimed at building abdominal strength and improving overall stability.
In this guide, you’ll learn how to create a Sit-Up counter app using pose estimation with the QuickPose iOS SDK. Whether you’re building a new fitness app or enhancing an existing one, this tutorial will help you leverage AI and pose estimation technology to deliver a precise and user-friendly Sit-Up counter that stands out in the competitive fitness market.
Steps to integrate a Sit Up counter into your app:
Register an SDK Key with QuickPose
Get your free SDK key on https://dev.quickpose.ai, usage limits may apply. SDK Keys are linked to your bundle ID, please check Key before distributing to the App Store.
This is a quick look to integrate the Sit Ups counter using the QuickPose iOS SDK. You can see the full documentation here: QuickPose iOS SDK Sit Ups installation.
Activate Sit Ups Feature
feature = .fitness(.sitUps)
feature = .fitness(.sitUps, style: customOrConditionalStyle)
Form Feedback
We recommend using the feature feedback to guide the user if an error occurs.
quickPose.start(features: [.fitness(.sitUps)], onFrame: { status, image, features, feedback, landmarks in
switch status {
case .success:
overlayImage = image
if let result = features.values.first {
feedbackText = "Sit Ups: \(Int(result.value * 100))%"
} else if let feedback = feedback.values.first, feedback.isRequired {
feedbackText = feedback.displayString
} else {
feedbackText = nil
}
case .noPersonFound:
feedbackText = "Stand in view";
case .sdkValidationError:
feedbackText = "Be back soon";
}
})
Body position: "Get on your back, side on"
.body(feedback: floorSideOnWithBackOnTheGround, isRequired: true)
Joint Visibility:
"Move left arm into view"
"Move right arm into view"
"Move upper body into view"
"Move left leg into view"
"Move right leg into view"
"Move lower body into view"
"Move whole body into view"
.group(action: .move, group:.arm(side: .left), direction:.intoView, isRequired: true)
.group(action: .move, group:.arm(side: .right), direction:.intoView, isRequired: true)
.group(action: .move, group:.upperBody, direction:.intoView, isRequired: true)
.group(action: .move, group:.leg(side: .left), direction:.intoView, isRequired: true)
.group(action: .move, group:.leg(side: .right), direction:.intoView, isRequired: true)
.group(action: .move, group:.lowerBody, direction:.intoView, isRequired: true)
.group(action: .move, group:.wholeBody, direction:.intoView, isRequired: true)
Conditional Styling
To give user feedback consider using conditional styling so that when the user’s measurement goes above a threshold, here 0.8, a green highlight is shown.
let greenHighlightStyle = QuickPose.Style(conditionalColors: [QuickPose.Style.ConditionalColor(min: 0.8, max: nil, color: UIColor.green)])
quickPose.start(features: [.fitness(.sitUps, style: customOrConditionalStyle)],
onFrame: { status, image, features, feedback, landmarks in ...
})
How to Count Sit Ups
Real-time Sit Up counting with AI
To count the Sit Up declare a configurable threshold counter, which can be used to turn lots of our features into counts.
@State private var counter = QuickPoseThresholdCounter()
Then pass QuickPose’s Sit Up result to the counter, and display in the feedback text declared above.
quickPose.start(features: [.fitness(.sitUps)], onFrame: { status, image, features, feedback, landmarks in
switch status {
case .success:
overlayImage = image
if let result = features.values.first {
let counterState = counter.count(result.value)
feedbackText = "\(counterState.count) Sit Ups"
} else {
feedbackText = nil
}
case .noPersonFound:
feedbackText = "Stand in view";
case .sdkValidationError:
feedbackText = "Be back soon";
}
})
Sit Up Timer
To time the Sit Ups declare a configurable threshold timer, which can be used to turn lots of our features into timers. For Sit Ups we suggest modifying the default threshold, taking account of expected camera positioning and tilt.
@State private var timer = QuickPoseThresholdTimer(threshold: 0.2)
Then pass the result’s raw value to the timer, and display in the feedback text declared above.
quickPose.start(features: [.fitness(.sitUps)], onFrame: { status, image, features, feedback, landmarks in
switch status {
case .success:
overlayImage = image
if let result = features.values.first {
let timerState = timer.time(result.value)
feedbackText = String(format: "%.1f", timerState.time) + "secs"
} else {
feedbackText = nil
}
case .noPersonFound:
feedbackText = "Stand in view";
case .sdkValidationError:
feedbackText = "Be back soon";
}
})