Project Summary
Football Speed Tracker uses perspective transformation and object tracking to measure how fast players move on a pitch. It processes standard video input and outputs per-player speed readings in km/h, with no specialised hardware needed beyond a camera.
Overview
Measuring player speed in football traditionally requires GPS vests or expensive tracking systems. This project takes a different approach: extract speed data entirely from standard video footage using computer vision techniques.
The system works by first mapping the pitch's perspective to a flat top-down view, then tracking each player across frames, and finally computing real-world distances from pixel displacements using a calibrated scale factor.
The Problem It Solves
Amateur and semi-professional football teams rarely have access to GPS tracking systems. Yet understanding player movement — who covered the most ground, who hit top speed, who was slowest in the second half — is incredibly valuable for coaching.
This tool gives coaches and analysts access to speed data using nothing more than a phone or camera recording a match.
How It Works
1. Perspective Calibration
The core challenge is converting pixel measurements to real-world distances. A standard football pitch has known dimensions. By identifying four reference points on the pitch (e.g., penalty box corners), the system applies a perspective transform to "flatten" the view.
# Compute perspective transform matrix
src_pts = np.float32([top_left, top_right, bottom_left, bottom_right])
dst_pts = np.float32([[0,0],[pitch_width,0],[0,pitch_height],[pitch_width,pitch_height]])
M = cv2.getPerspectiveTransform(src_pts, dst_pts)
Once the transform matrix is known, any pixel coordinate in the original video can be mapped to a real-world coordinate in metres.
2. Player Detection & Tracking
Players are detected using background subtraction combined with contour filtering. Each detected blob above a minimum area threshold is classified as a player candidate. A simple centroid-based tracker assigns persistent IDs across frames.
3. Speed Calculation
Speed is calculated from the Euclidean distance between a player's position in two consecutive frames, divided by the time between frames:
distance_px = np.linalg.norm(pos_current - pos_previous)
distance_m = distance_px * scale_factor
speed_ms = distance_m / frame_delta_time
speed_kmh = speed_ms * 3.6
To avoid noise from detection jitter, speed readings are smoothed using a rolling average over 5 frames.
Tech Stack
- Python 3.10+ — Core language
- OpenCV — Video processing, perspective transforms, contour detection
- NumPy — Coordinate maths and matrix operations
- Matplotlib — Speed charts and visualisation output
Results & Outcomes
Tested against GPS vest data on a 90-minute amateur match, the system achieved:
- Average speed error: ±1.4 km/h
- Top-speed detection accuracy: ±2.1 km/h
- Processing speed: real-time on 720p footage at 30fps
The v2 calibration pipeline (released April 2025) reduced the average error from ±3.1 km/h to ±1.4 km/h — a major improvement over v1.
Challenges & Fixes
Occlusion: When players overlap, the tracker temporarily loses individual IDs. Handled by using a short re-identification window where nearby tracks are re-matched by proximity and colour histogram.
Camera shake: Handheld footage introduces noise into position readings. Applied an optical flow stabilisation pass before tracking begins.
Lighting variation: Background subtraction fails under rapidly changing lighting. Solved with adaptive history and shadow detection in MOG2.
Future Improvements
- Switch from contour detection to a YOLOv8 player detector for better accuracy in crowded scenes
- Add team differentiation via jersey colour clustering
- Build a web-based dashboard for post-match analysis output
- Support multi-camera setups for full-pitch coverage