How to Build a Squat Counter App

Building an AI-Powered Squat Counter App with QuickPose iOS SDK

Are you interested in developing an AI-powered squat counter for your fitness app? Squats are a cornerstone exercise in strength training, known for their ability to target multiple muscle groups, including the quadriceps, hamstrings, glutes, and lower back. This compound movement not only builds strength and endurance in the lower body but also engages the core for stability.

In this guide, you’ll learn how to create a squat counter app using the QuickPose iOS SDK. We’ll walk you through the process of implementing real-time squat counting, providing form corrections, and customising feedback to enhance user engagement. Whether you’re building a new fitness app or adding advanced features to an existing one, this tutorial will help you leverage AI to deliver an accurate and user-friendly squat counter that sets your app apart from the competition.

Image shows a fitness app user using the QuickPose AI Squats Counter to count squat reps in the gym. He is an AI engineer wearing a blue exercise tracksuit and orange trainers (sneakers)

Steps to integrate an AI Squat 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 squat counter using the QuickPose iOS SDK. You can see the full documentation here: QuickPose iOS SDK Squat Counter installation.

Activate Squats Feature

				
					feature = .fitness(.squats)
feature = .fitness(.squats, style: customOrConditionalStyle)
				
			


Give your users feedback on their squat form

We recommend using the Feedback Feature to provide form feedback to users.

				
					quickPose.start(features: [.fitness(.squats)], onFrame: { status, image, features, feedback, landmarks in
    switch status {
        case .success:
            overlayImage = image
            if let result = features.values.first  {
                feedbackText = "Squats: \(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(.squats, style: customOrConditionalStyle)], 
                onFrame: { status, image, features, feedback, landmarks in  ...
})
				
			

How to Count Squats

Real-time squat counting with AI

To count the Squats 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 squat result to the counter, and display in the feedback text declared above.

				
					quickPose.start(features: [.fitness(.squats)], 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) Squats"
            } else {
                feedbackText = nil
            }
            
        case .noPersonFound:
            feedbackText = "Stand in view";
        case .sdkValidationError:
            feedbackText = "Be back soon";
    }
})
				
			

Squat Timer

To time the Squats declare a configurable threshold timer, which can be used to turn lots of our features into timers. For Squats, 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(.squats)], 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";
    }
})
				
			

Need help building an AI project?

At QuickPose, our mission is to build smart Pose Estimation Solutions that elevate your product. Schedule a free consultation with us to discuss your project.