Building an AI-Powered Push-Up Counter App with QuickPose iOS SDK
Looking to create an AI-powered push-up counter for your fitness app? Perhaps looking to create a push-up game? Push-ups are a fundamental exercise for building upper body strength, engaging key muscle groups like the chest, triceps, and shoulders, while also activating the core, glutes, and lower back. Integrating an AI-driven push-up counter into your app can help users accurately track their reps, improve their form, and reach their fitness goals more effectively.
In this quick guide, you’ll learn how to build a push-up counter app using the QuickPose iOS SDK. We’ll cover everything from real-time rep counting to providing form corrections and customising feedback, so you can deliver an enhanced user experience with the power of AI. Whether you’re developing a dedicated fitness tracker or adding new features to an existing app, this tutorial will equip you with the knowledge to create a cutting-edge push-up counter that stands out in the market.
Steps to integrate an AI Push 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 push up counter using the QuickPose iOS SDK. You can see the full documentation here: QuickPose iOS SDK Push Up Counter installation.
Activate Push Up Feature
feature = .fitness(.pushUps)
feature = .fitness(.pushUps, style: customOrConditionalStyle)
Give your users feedback on their push up form
We recommend using the feature feedback to guide the user.
quickPose.start(features: [.fitness(.pushUps)], onFrame: { status, image, features, feedback, landmarks in
switch status {
case .success:
overlayImage = image
if let result = features.values.first {
feedbackText = "Push 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";
}
})
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(.pushUps, style: customOrConditionalStyle)],
onFrame: { status, image, features, feedback, landmarks in ...
})
How to Count Push Ups
Real-time push-up counting with AI
To count the Push Ups 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 Push Up result to the counter, and display in the feedback text declared above.
quickPose.start(features: [.fitness(.pushUps)], 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) Push Ups"
} else {
feedbackText = nil
}
case .noPersonFound:
feedbackText = "Stand in view";
case .sdkValidationError:
feedbackText = "Be back soon";
}
})
Push Up Timer
To time the Push Ups declare a configurable threshold timer, which can be used to turn lots of our features into timers. For Push 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(.pushUps)], 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";
}
})