Mhmdwael77/ai-football-analytics

End-to-end football computer-vision analytics: detection, tracking, dynamic teams & roles, pitch calibration, speed/distance, tactics, possession & an AI match report. YOLO11 + BoT-SORT.

Python

8

7 commits

updated Sep 20, 2026

See the code

See what people are saying

SourceMessageScoreDate

I built an end-to-end AI football analytics system using YOLO11 and BoT-SORT (r/computervision)

Hey everyone! I've been working on a computer vision project that turns regular football match footage into player tracking, performance statistics, and tactical insights. It started as my graduation project, but I wanted to go beyond basic object detection and build a complete video analytics…

1

Oct 9, 2026

README

⚽ AI Football Analytics

An end-to-end computer-vision system that turns raw match footage into a full tactical & performance report

Python Ultralytics YOLO11 OpenCV Tests License: MIT

Detection → Tracking → Dynamic teams & roles → Pitch calibration → Speed & distance → Tactics, possession & an AI match report


Full broadcast composite: skeleton overlays, player names, tactical minimap, possession and live stat bars

One command, any match. Skeleton overlays · player names · tactical minimap · live speed/distance bars · possession — all discovered from the footage, nothing hard-coded.


📖 Overview

AI Football Analytics is a graduation project that processes a football video from raw frames all the way to an analyst-grade report. It detects and tracks every player, goalkeeper, referee and the ball, discovers the two teams from their kit colours, projects the action onto a real-metre pitch, and then computes speed, distance, heatmaps, possession, tactical profiles and a per-player rating — finishing with a natural-language match report.

Design principle — nothing is hard-coded. Teams, jersey colours, pitch geometry and player roles are all learned per match from the footage. The same command runs on any match, with no per-video constants.

python main.py --video match.mp4 --all --device cuda:0

That single command runs the entire 12-stage pipeline.


✨ Highlights

  • 🎯 Custom-trained YOLO11m detector for 4 classes (player · goalkeeper · referee · ball).
  • 🔗 Identity-stable tracking — BoT-SORT for people + a dedicated ball tracker (the ball is too small & fast for IoU tracking), plus appearance-based stitching and swap-correction to repair broken/swapped IDs.
  • 🎽 Dynamic team & role discovery — teams are clustered from jersey histograms (numpy-only spherical k-means); goalkeepers/referees split by position & motion. No fixed colours.
  • 🗺️ Automatic pitch calibration — our own trained keypoint model solves the per-frame homography (no manual clicking), smoothed with camera-motion estimation, projecting every player to real pitch metres.
  • 🏃 Speed & distance with smoothing and impossible-jump rejection, shown live under each player.
  • 🧠 Explainable analytics — per-player performance & 0–10 rating, team tactical profiles, heatmaps, ball possession, and a final match report. Every label carries the metric & reason behind it — no external LLM anywhere.
  • 🖐️ Human-in-the-loop (optional) — exactly two reproducible manual touch-points (team multi-select + per-track correction with player names), overlaid on the automatic result so it's never overwritten.
  • 🧪 340+ tests across 39 modules — runs with no GPU and no weights (fake YOLO model + fake tracker).

🎬 Pipeline in pictures

Every figure below is rendered from a real match processed by the system.

DetectionTrackingTeams & roles
DetectionTrackingTeams & roles
Raw YOLO boxes for the 4 classesStable BoT-SORT identitiesDynamic team clustering + GK/ref split + names
Pitch calibrationSkeleton poseTactical minimap
HomographyPoseMinimap
Keypoints + canonical pitch reprojectedPer-player body-pose overlayTop-down team shapes & average lines
Team heatmapSpeed & distanceFinal composite
HeatmapSpeed/distanceComposite
Gaussian positional heatmap per teamLive per-player speed + distanceFull broadcast-style output

🏗️ Architecture

A modular, layered system. Each stage is an independent package that talks to the next only through typed data contracts (dataclasses) and JSON on disk — never by passing raw frames around. Any stage can be re-run on a previous stage's output.

            video
              │
   ┌──────────▼───────────┐
   │ detection            │  YOLO11m → typed Detections
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ tracking             │  BoT-SORT + ball tracker → Tracks (stable ids)
   │   stitch / swap-fix  │  appearance-based identity repair
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ role_refinement      │  dynamic team clustering → roles & teams
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ manual_correction    │  human-in-the-loop overlay (optional)
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ calibration          │  keypoint model → homography → field metres
   │   + minimap          │  + camera-motion smoothing, top-down render
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ analytics            │  speed/distance, performance, heatmaps,
   │                      │  tactics, possession, match report
   └──────────────────────┘

   utils  ── config, logging, video I/O, JSON export (shared by all)

📚 Deep dives: Architecture · Full pipeline · Manual workflow


🔬 The 12 stages

#StageWhat it produces
1DetectionPlayer / goalkeeper / referee / ball boxes per frame
2TrackingStable IDs (BoT-SORT + ball tracker, stitch + swap-fix)
3Role refinementDynamically discovered teams + GK/referee split
4Manual correction (optional)Team multi-select + per-track names
5Homography / field projectionPer-frame player positions in pitch metres
6Minimap & final videoTactical top-down map + skeleton broadcast video
7Speed & distanceDistance covered, avg/max speed per player
8Player performanceWork rate, fatigue, 0–10 rating + insight
9HeatmapsPer-team & best-player positional heatmaps
10Team tactical analysisCompactness, press, build-up, attacking zone
11Ball possessionField-space possession %, timeline, dominant team
12Match reportMan of the match, key insights, recommendations

Every analytics artifact is emitted as both machine-readable JSON and human-readable TXT.


🚀 Getting started

1. Clone & install

git clone https://github.com/Mhmdwael77/ai-football-analytics.git
cd ai-football-analytics
python -m venv .venv
.venv\Scripts\activate          # Windows  (use: source .venv/bin/activate on Linux/macOS)
pip install -r requirements.txt

2. Get the model weights

The trained checkpoints are published on the Releases page (too large for git). Download them into weights/:

gh release download v1.0.0 --dir weights/
FilePurpose
weights/best.ptYOLO11m detector
weights/pitch_keypoints_yolo11m_best.pt.ptPitch-keypoint / homography model

See weights/README.md for details. The pose model yolo11m-pose.pt is fetched automatically on first use.

3. Run it

# Full pipeline — detection → tracking → roles → calibration → analytics → report
python main.py --video match.mp4 --all --device cuda:0

# Just detection
python main.py --video match.mp4

# Detection + tracking, with a live preview window
python main.py --video match.mp4 --tracking --display

# Quick validation on the first N frames
python main.py --video match.mp4 --all --max-frames 200

Outputs land in outputs/ (annotated videos, minimap, JSON/TXT reports, heatmaps). All tunables live in config/config.yaml.


📊 Sample output

Real match report produced by the pipeline (see docs/sample_outputs/ for the full set):

MATCH REPORT — input_video
========================================================

Team 0 dominated the match with 59% possession. The standout performer was
Player 21 (Team 1), rated 9.5/10. Tactically: Team 0 counter-attacking,
Team 1 attacking.

Dominant team   : Team 0
Man of the match: Player 21
Weakest player  : Player 37

TEAMS
  Team 0: Counter-Attacking | Mid Block | Compact | Fast transitions
  Team 1: Attacking | High Press | Compact | Fast transitions

KEY INSIGHTS
  - Team 0 controlled possession (59%).
  - Player 21 (Team 1) was the standout at 9.5/10 — Very active and
    frequently involved in play. Covered a lot of ground.

🧪 Tests

python -m pytest tests/ -v

340+ tests across 39 modules. No model weights or GPU required — the detector tests use a fake YOLO model, pipeline tests inject a fake tracker, and the BoT-SORT integration tests run the real tracker on synthetic detections.


🧰 Tech stack

Python 3.12 · Ultralytics YOLO11 (detection · pose · BoT-SORT) · OpenCV · NumPy · PyYAML · pytest · Streamlit (optional manual-correction UI).


📁 Project structure

detection/          YOLO detector + Detection contracts
tracking/           BoT-SORT, ball tracker, stitching, swap-correction
role_refinement/    dynamic team clustering + role assignment
manual_correction/  optional human-in-the-loop tools (Tk + Streamlit)
calibration/        pitch keypoints, homography, camera motion, minimap
analytics/          speed/distance, performance, heatmaps, tactics,
                    possession, match report
visualization/      box annotator + skeleton pose overlay
utils/              config, logging, video I/O, JSON export
evaluation/         detection mAP evaluation
tools/              thesis-figure & final-render generators
tests/              340+ pytest suite (no GPU / no weights needed)
config/config.yaml  every tunable in one place
docs/               architecture, pipeline & workflow docs

🗺️ Roadmap

All six project phases are complete:

  • Phase 1 — Detection (YOLO11m)
  • Phase 2 — Tracking (BoT-SORT + ball tracker, stitch & swap-fix)
  • Phase 3 — Dynamic teams & role refinement (+ manual correction)
  • Phase 4 — Pitch calibration & tactical minimap
  • Phase 5 — Speed & distance
  • Phase 6 — Player performance, tactics, possession & match report

📜 License

Released under the MIT License.

Copyright © 2026 Mohamed Wael. All Rights Reserved.

This project is proprietary software. No permission is granted to copy, modify, distribute, publish, sell, sublicense, deploy, or use this software without prior written authorization from the copyright owner.

See the LICENSE file for full terms.


Built as a graduation project — computer vision for the beautiful game. ⚽
botsort
computer-vision
deep-learning
football
homography
object-tracking
opencv
player-tracking
python
soccer
sports-analytics
yolo

Mhmdwael77/ai-football-analytics

End-to-end football computer-vision analytics: detection, tracking, dynamic teams & roles, pitch calibration, speed/distance, tactics, possession & an AI match report. YOLO11 + BoT-SORT.

Python

8

7 commits

updated Sep 20, 2026

See the code

See what people are saying

SourceMessageScoreDate

I built an end-to-end AI football analytics system using YOLO11 and BoT-SORT (r/computervision)

Hey everyone! I've been working on a computer vision project that turns regular football match footage into player tracking, performance statistics, and tactical insights. It started as my graduation project, but I wanted to go beyond basic object detection and build a complete video analytics…

1

Oct 9, 2026

README

⚽ AI Football Analytics

An end-to-end computer-vision system that turns raw match footage into a full tactical & performance report

Python Ultralytics YOLO11 OpenCV Tests License: MIT

Detection → Tracking → Dynamic teams & roles → Pitch calibration → Speed & distance → Tactics, possession & an AI match report


Full broadcast composite: skeleton overlays, player names, tactical minimap, possession and live stat bars

One command, any match. Skeleton overlays · player names · tactical minimap · live speed/distance bars · possession — all discovered from the footage, nothing hard-coded.


📖 Overview

AI Football Analytics is a graduation project that processes a football video from raw frames all the way to an analyst-grade report. It detects and tracks every player, goalkeeper, referee and the ball, discovers the two teams from their kit colours, projects the action onto a real-metre pitch, and then computes speed, distance, heatmaps, possession, tactical profiles and a per-player rating — finishing with a natural-language match report.

Design principle — nothing is hard-coded. Teams, jersey colours, pitch geometry and player roles are all learned per match from the footage. The same command runs on any match, with no per-video constants.

python main.py --video match.mp4 --all --device cuda:0

That single command runs the entire 12-stage pipeline.


✨ Highlights

  • 🎯 Custom-trained YOLO11m detector for 4 classes (player · goalkeeper · referee · ball).
  • 🔗 Identity-stable tracking — BoT-SORT for people + a dedicated ball tracker (the ball is too small & fast for IoU tracking), plus appearance-based stitching and swap-correction to repair broken/swapped IDs.
  • 🎽 Dynamic team & role discovery — teams are clustered from jersey histograms (numpy-only spherical k-means); goalkeepers/referees split by position & motion. No fixed colours.
  • 🗺️ Automatic pitch calibration — our own trained keypoint model solves the per-frame homography (no manual clicking), smoothed with camera-motion estimation, projecting every player to real pitch metres.
  • 🏃 Speed & distance with smoothing and impossible-jump rejection, shown live under each player.
  • 🧠 Explainable analytics — per-player performance & 0–10 rating, team tactical profiles, heatmaps, ball possession, and a final match report. Every label carries the metric & reason behind it — no external LLM anywhere.
  • 🖐️ Human-in-the-loop (optional) — exactly two reproducible manual touch-points (team multi-select + per-track correction with player names), overlaid on the automatic result so it's never overwritten.
  • 🧪 340+ tests across 39 modules — runs with no GPU and no weights (fake YOLO model + fake tracker).

🎬 Pipeline in pictures

Every figure below is rendered from a real match processed by the system.

DetectionTrackingTeams & roles
DetectionTrackingTeams & roles
Raw YOLO boxes for the 4 classesStable BoT-SORT identitiesDynamic team clustering + GK/ref split + names
Pitch calibrationSkeleton poseTactical minimap
HomographyPoseMinimap
Keypoints + canonical pitch reprojectedPer-player body-pose overlayTop-down team shapes & average lines
Team heatmapSpeed & distanceFinal composite
HeatmapSpeed/distanceComposite
Gaussian positional heatmap per teamLive per-player speed + distanceFull broadcast-style output

🏗️ Architecture

A modular, layered system. Each stage is an independent package that talks to the next only through typed data contracts (dataclasses) and JSON on disk — never by passing raw frames around. Any stage can be re-run on a previous stage's output.

            video
              │
   ┌──────────▼───────────┐
   │ detection            │  YOLO11m → typed Detections
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ tracking             │  BoT-SORT + ball tracker → Tracks (stable ids)
   │   stitch / swap-fix  │  appearance-based identity repair
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ role_refinement      │  dynamic team clustering → roles & teams
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ manual_correction    │  human-in-the-loop overlay (optional)
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ calibration          │  keypoint model → homography → field metres
   │   + minimap          │  + camera-motion smoothing, top-down render
   └──────────┬───────────┘
   ┌──────────▼───────────┐
   │ analytics            │  speed/distance, performance, heatmaps,
   │                      │  tactics, possession, match report
   └──────────────────────┘

   utils  ── config, logging, video I/O, JSON export (shared by all)

📚 Deep dives: Architecture · Full pipeline · Manual workflow


🔬 The 12 stages

#StageWhat it produces
1DetectionPlayer / goalkeeper / referee / ball boxes per frame
2TrackingStable IDs (BoT-SORT + ball tracker, stitch + swap-fix)
3Role refinementDynamically discovered teams + GK/referee split
4Manual correction (optional)Team multi-select + per-track names
5Homography / field projectionPer-frame player positions in pitch metres
6Minimap & final videoTactical top-down map + skeleton broadcast video
7Speed & distanceDistance covered, avg/max speed per player
8Player performanceWork rate, fatigue, 0–10 rating + insight
9HeatmapsPer-team & best-player positional heatmaps
10Team tactical analysisCompactness, press, build-up, attacking zone
11Ball possessionField-space possession %, timeline, dominant team
12Match reportMan of the match, key insights, recommendations

Every analytics artifact is emitted as both machine-readable JSON and human-readable TXT.


🚀 Getting started

1. Clone & install

git clone https://github.com/Mhmdwael77/ai-football-analytics.git
cd ai-football-analytics
python -m venv .venv
.venv\Scripts\activate          # Windows  (use: source .venv/bin/activate on Linux/macOS)
pip install -r requirements.txt

2. Get the model weights

The trained checkpoints are published on the Releases page (too large for git). Download them into weights/:

gh release download v1.0.0 --dir weights/
FilePurpose
weights/best.ptYOLO11m detector
weights/pitch_keypoints_yolo11m_best.pt.ptPitch-keypoint / homography model

See weights/README.md for details. The pose model yolo11m-pose.pt is fetched automatically on first use.

3. Run it

# Full pipeline — detection → tracking → roles → calibration → analytics → report
python main.py --video match.mp4 --all --device cuda:0

# Just detection
python main.py --video match.mp4

# Detection + tracking, with a live preview window
python main.py --video match.mp4 --tracking --display

# Quick validation on the first N frames
python main.py --video match.mp4 --all --max-frames 200

Outputs land in outputs/ (annotated videos, minimap, JSON/TXT reports, heatmaps). All tunables live in config/config.yaml.


📊 Sample output

Real match report produced by the pipeline (see docs/sample_outputs/ for the full set):

MATCH REPORT — input_video
========================================================

Team 0 dominated the match with 59% possession. The standout performer was
Player 21 (Team 1), rated 9.5/10. Tactically: Team 0 counter-attacking,
Team 1 attacking.

Dominant team   : Team 0
Man of the match: Player 21
Weakest player  : Player 37

TEAMS
  Team 0: Counter-Attacking | Mid Block | Compact | Fast transitions
  Team 1: Attacking | High Press | Compact | Fast transitions

KEY INSIGHTS
  - Team 0 controlled possession (59%).
  - Player 21 (Team 1) was the standout at 9.5/10 — Very active and
    frequently involved in play. Covered a lot of ground.

🧪 Tests

python -m pytest tests/ -v

340+ tests across 39 modules. No model weights or GPU required — the detector tests use a fake YOLO model, pipeline tests inject a fake tracker, and the BoT-SORT integration tests run the real tracker on synthetic detections.


🧰 Tech stack

Python 3.12 · Ultralytics YOLO11 (detection · pose · BoT-SORT) · OpenCV · NumPy · PyYAML · pytest · Streamlit (optional manual-correction UI).


📁 Project structure

detection/          YOLO detector + Detection contracts
tracking/           BoT-SORT, ball tracker, stitching, swap-correction
role_refinement/    dynamic team clustering + role assignment
manual_correction/  optional human-in-the-loop tools (Tk + Streamlit)
calibration/        pitch keypoints, homography, camera motion, minimap
analytics/          speed/distance, performance, heatmaps, tactics,
                    possession, match report
visualization/      box annotator + skeleton pose overlay
utils/              config, logging, video I/O, JSON export
evaluation/         detection mAP evaluation
tools/              thesis-figure & final-render generators
tests/              340+ pytest suite (no GPU / no weights needed)
config/config.yaml  every tunable in one place
docs/               architecture, pipeline & workflow docs

🗺️ Roadmap

All six project phases are complete:

  • Phase 1 — Detection (YOLO11m)
  • Phase 2 — Tracking (BoT-SORT + ball tracker, stitch & swap-fix)
  • Phase 3 — Dynamic teams & role refinement (+ manual correction)
  • Phase 4 — Pitch calibration & tactical minimap
  • Phase 5 — Speed & distance
  • Phase 6 — Player performance, tactics, possession & match report

📜 License

Released under the MIT License.

Copyright © 2026 Mohamed Wael. All Rights Reserved.

This project is proprietary software. No permission is granted to copy, modify, distribute, publish, sell, sublicense, deploy, or use this software without prior written authorization from the copyright owner.

See the LICENSE file for full terms.


Built as a graduation project — computer vision for the beautiful game. ⚽
botsort
computer-vision
deep-learning
football
homography
object-tracking
opencv
player-tracking
python
soccer
sports-analytics
yolo