Analysing harmonic motion using computer vision
September 2023
this is more of a personal journey of winning a coding competition, less of a technical guide to computer vision
A few days ago, I saw the Creative Coding Competition by Radu Mariescu-Istodor. I’ve been following his work for a while.
When this competition popped up, I had to give it a shot. It was way outside my comfort zone, but it ended up being one of the most fun coding experiences I’ve had.
ps: I actually scored the highest in the competition (46/50), here's the video reviewing my project by Radu Mariescu-Istodor
The Challenge
The challenge was straightforward: Take a video footage and transform it with a visual effect, using nothing but code.
This is my submission of the project github.com/rudrodip/Harmonic-Oscillator-CV
Overview of the project
It's very simple tool to analyse harmonic of a pendulumn given the video of the pendulum. It uses some popular python libraries like OpenCV, SciPy, NumPy to detect, analyse and predict the harmonic motion of the pendulum. It can take video feed from a file, webcam or a URL, and try to guess the critical parameters of the harmonic motion of the pendulum.
How to use it?
Check out the UI section first, it'll make setup way easier and help you understand how everything works.
Before you begin, ensure you have python 3.6 or higher installed on your system. You can download Python from python.org.
Setting up the project
Clone the repository
git clone https://github.com/rudrodip/Harmonic-Oscillator-CV
cd Harmonic-Oscillator-CVCreate a virtual environment
python -m venv venvActivate the virtual environment
On Windows:
venv\Scripts\activateOn MacOS and Linux:
source venv/bin/activateInstalling Dependencies
Once you have your virtual environment set up and activated, you can install the project's dependencies
pip install -r requirements.txtUsage
- Run the main application script:
python app/app.pyThe OpenCV library you will be using for this project is opencv-python-headless (not opencv-python), so make sure you have the correct library installed in virtual environment, otherwise uninstall opencv-python and reinstall opencv-python-headless using this command
pip install opencv-python-headless --no-cache-dirUser Interface
The UI is very straightforward and made with python and pyqt5.
Buttons and Dropdowns
Main controls:
- Run/Stop: Start and stop video processing
- Select Video/Webcam/URL: Choose your video source
- Hide Params: Toggle visual guides on/off
Dropdowns let you switch between display modes (raw video, contours, mask) and detection methods (HSV color detection is recommended).
HSV Range Sliders
Fine-tune color detection here. My workflow: set display to "Mask," run the video, then adjust sliders until the white blob matches your pendulum bob. Save when it looks good.
Analyze Widget
Hit Estimate once you have good tracking to fit a curve to your data. Shows calculated physics parameters that you can save for later.
Graph
Built with pyqtgraph - zoom, pan, scale, and export however you want
Project Sections
This project has three main parts:
-
Programming: Here I built the user interface and set up image processing using OpenCV and
cvzone. The UI was pretty easy to make with Python and PyQt5. -
Mathematics: This part is about using math to get useful info from the data.
- Curve Fitting with
curve_fit: I use SciPy’scurve_fitto match the data to a damped oscillation curve. This helps find and analyze the motion patterns. least_squarefor Circular Path Detection: Theleast_squarealgorithm is not only used for curve fitting but also for assessing the accuracy of circular paths.
- Curve Fitting with
-
Physics: Physics provides the necessary equations to model and estimate physical parameters like pendulum length and pivot—crucial for understanding the motion.
Programming
Image Processing
OpenCV handled the video feed, object detection, and tracking. cvzone made contour detection easy, especially for finding objects by HSV color range.
Main Loop Overview
Each frame went through this cycle:
- Capture Frame – Get the latest image from the camera.
- Find Contours – Use
cvzoneto detect objects by color. - Pivot & Path Prediction – With SciPy’s
least_square, estimate the pivot point and predict motion. - Send Data to UI – Position and frame count updates for display.
- Render Frame – Show processed video in real time.
- Repeat – Frame after frame for smooth live analysis.
Mathematics
Detecting Circular Motion with least_square
Even if the video is rotated, circular motion can be detected reliably:
- Extract Contours – Get the object’s outline each frame.
- Residuals Calculation – Compare actual points to a circle model:
def circle_residuals(params, x, y):
a, b, r = params # circle center (a,b) and radius r
return np.sqrt((x - a)**2 + (y - b)**2) - rResiduals (per point) For data points and circle :
- Optimize Parameters – Let
least_squareadjust center and to minimize . - Pivot & Rotation – After estimating the pivot and rotation angle , transform coordinates to a de-rotated frame:
Fitting Harmonic Motion with curve_fit
Goal: fit the exact motion equation.
Model (underdamped oscillator):
def underdamped_harmonic_oscillator(t, A, gamma, w, phi, C):
return A * np.exp(-gamma * t) * np.cos(w * t + phi) + CProcess
- Collect data.
- Fit with
curve_fit. - Extract .
Result: a clean curve matching real motion.
Physics
Understanding the physics behind the motion is key to making sense of the data.
Our object behaves like a damped harmonic oscillator, so the starting point is the classic equations of motion.
From Springs to Pendulums
A damped mass–spring system is described by:
- → mass
- → damping coefficient (friction, air resistance, etc.)
- → stiffness or restoring constant
A simple pendulum with small oscillations follows a very similar form:
- → angular displacement
- → natural angular frequency (no damping)
This similarity is why the math we use for springs also works for pendulums.
The Underdamped Case
When damping is small (), the motion looks like a decaying cosine:
Here:
- → amplitude
- → damping rate
- → damped angular frequency
- → phase
- → vertical offset
The link between damped and natural frequencies is:
This means damping slows the oscillation slightly compared to the ideal case.
Connecting to String Length
For a simple pendulum:
where is the string length and is gravity.
From the fitted parameters in our data:
- Get and from the curve fit.
- Compute the natural frequency:
- Solve for the length:
If the Pendulum isn’t “Simple”
Real pendulums can be compound pendulums — the bob has its own size and mass distribution.
We then need its moment of inertia :
Moment of inertia of a solid sphere about its center:
Shifted to the pivot point using the parallel-axis theorem:
The natural frequency becomes:
where is the distance from the pivot to the center of mass.
In practice:
- Use the fitted motion data to estimate .
- Apply the correct formula (simple or compound) to back-calculate .
So that's it, it's super simple, and I know there are tons of better ideas out there, a lot of optimizations to be done, but it was a fun project to work on.
I really want you guys to try it out, it feels magical when you see the plots being drawn in real time.
If you want to chat about it, you can knock me on X. Give it a star on github if you like it.
See ya 👋!