Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

xG Vision: A Context-Aware Expected Goals Model with Player-Specific Skill Calibration

Python License XGBoost YOLOv8 RT-DETR Streamlit PyTorch OpenCV

Thesis Project by Rishabh Vats LinkedIn


Table of Contents


The Problem with Standard xG

Expected Goals (xG) is a probabilistic metric that quantifies the quality of a scoring opportunity in football. A value of 0.0 means no chance of scoring, while 1.0 represents a near-certain goal. Every modern football analytics platform (StatsBomb, Opta, FBref, Understat) relies on xG to evaluate players, teams, and tactical approaches.

However, standard xG models are fundamentally limited. They rely almost exclusively on spatial features -- the distance and angle from goal, the body part used, and whether the shot is a penalty. These models treat every player identically and ignore the dynamic context surrounding each shot.

What Standard xG Sees What It Misses
Distance to goal Goalkeeper position (on line? off line? out of position?)
Angle to goal Defensive pressure intensity (how many blockers? how close?)
Body part (head/foot) Build-up sequence context (counter-attack? set piece? solo run?)
Is it a penalty? Game state (is the team chasing? protecting a lead?)
Is it a big chance? Player-specific finishing skill

Research from KU Leuven (Davis & Robberechts, 2024) quantified this problem: standard xG underestimates Messi's finishing ability by 17%. Elite finishers consistently "outperform" their xG -- but this is not variance or luck. It is measurable skill that standard models cannot capture.

Three Specific Limitations

  1. Goalkeeper positioning is ignored. A 1v1 where the goalkeeper is 5 meters off the goal line receives the same xG as one where the goalkeeper is perfectly positioned on the line. In reality, the first scenario is a near-certain goal.

  2. Defensive pressure is underweighted. A shot with 4 defenders blocking the shooting lane and a nearest defender 1 meter away gets roughly the same xG as a shot with a clear path to goal, as long as the distance and angle are similar.

  3. All players are treated identically. Erling Haaland's one-on-one receives the same xG as a center-back's one-on-one, despite Haaland converting these at approximately 80% and the average player at around 45%.


The xG Vision Solution - Three-Layer Architecture

xG Vision addresses all three limitations through a three-layer prediction system:

+-------------------------------------------------------------+
|                    THREE-LAYER ARCHITECTURE                   |
+-------------------------------------------------------------+
|                                                               |
|  LAYER 1: Context-Aware Base xG                              |
|  -----------------------------------                         |
|  54 engineered features across 5 categories:                 |
|  - Spatial features (distance, angle, centrality)            |
|  - GK positioning (off line? out of position?)               |
|  - Defensive pressure (blockers, nearest defender)           |
|  - Sequence context (counter-attack? fast break?)            |
|  - Game state (minute, score differential)                   |
|                                                               |
|                         |                                     |
|                         v                                     |
|                                                               |
|  LAYER 2: Player Skill Modifier                              |
|  ----------------------------------                          |
|  Shot-type specific Bayesian calibration:                    |
|  - Long range proficiency (Szoboszlai: 2.0x)                |
|  - 1v1 finishing (Haaland: 1.45x)                            |
|  - Free kick conversion (Ward-Prowse: 2.0x)                 |
|  - Tight angle shooting (Salah: 1.26x)                      |
|                                                               |
|                         |                                     |
|                         v                                     |
|                                                               |
|  LAYER 3: Final xG Vision                                    |
|  --------------------------                                  |
|  xg_vision = base_xg x player_modifier                      |
|  Clamped to [0.01, 0.99] with confidence weighting           |
|                                                               |
+-------------------------------------------------------------+

Layer 1: Context-Aware Base xG (54 Features)

The first layer extracts 54 engineered features organized into 5 categories. This is implemented in src/analytics/features.py using the XGFeatureExtractor class.

Category Count Key Features What It Captures
Spatial 13 Distance to goal, angle to goal, centrality, zone classification, distance-angle interaction Shot location geometry and interaction effects between distance and angle
Defensive 10 GK off-line score, blockers in shooting triangle, pressure gradient, nearest defender distance, open goal factor How exposed the goal is and how much defensive interference exists
Shot Context 14 Body part encoding (4 types), technique (8 types), assist type (7 types), first-time shot flag, big chance flag The biomechanics and situation leading to the shot
Game State 11 Match minute, goal difference, home/away, extra time, chasing game factor, protecting lead interaction Psychological and tactical context of the match
Sequence 7 Counter-attack flag, fast break flag, buildup speed, sequence length and duration, distance covered How the attacking move developed before the shot

The defensive features represent the largest innovation. The GK off-line score quantifies how far the goalkeeper is from optimal positioning (0 = on the line, 1 = completely out of position). The blockers in shooting triangle counts how many defenders occupy the geometric triangle between the ball and both goalposts. The pressure gradient captures how quickly defensive pressure builds as the attacker approaches goal.

Layer 2: Player Skill Modifier (Bayesian Calibration)

The second layer applies player-specific skill adjustments using Bayesian hierarchical modeling, implemented in src/analytics/player_profiler.py.

8 Shot Types Tracked:

Shot Type Definition Example Specialist
Long Range > 20m from goal Szoboszlai (2.0x modifier)
One-on-One Only GK to beat Haaland (1.45x modifier)
Header Headed attempts Van Dijk
Free Kick Direct free kicks Ward-Prowse (2.0x modifier)
Penalty Penalty kicks Penalty specialists
Tight Angle < 20 degree angle to goal Salah (1.26x modifier)
Big Chance High xG opportunity Elite finishers
Regular All other shots General shooters

Bayesian Shrinkage with Position Priors:

Not all players have enough shot data for reliable estimates. The system uses hierarchical Bayesian shrinkage with 6 position-based priors (striker, attacking midfielder, winger, midfielder, defender, goalkeeper):

  • High sample count (50+ shots of that type): Player's own observed conversion rate dominates the estimate.
  • Medium sample count (10-50 shots): Blended between the player's rate and the positional average.
  • Low sample count (< 10 shots): Heavily shrunk toward the position group's average for that shot type.
  • New player (0 shots): Uses position baseline (modifier = 1.0).

The modifier is clamped to [0.5, 2.0] to prevent extreme values from dominating predictions.

Layer 3: Final xG Vision

The final prediction combines both layers:

xg_vision = base_xg * player_modifier

The result is clamped to [0.01, 0.99] to maintain valid probability bounds.


Results -- Where xG Vision Outperforms

Scenario Standard xG xG Vision Difference Key Driver
Counter-attack, GK out of position (Haaland) 0.17 0.99 +486% GK 5m off goal line + 0 blockers + Haaland 1v1 skill (1.45x)
Long range shot (Szoboszlai) 0.01 0.06 +512% Long-range specialist modifier (2.0x) applied to base xG
Crowded box, high defensive pressure 0.10 0.06 -40% 4 defenders blocking + pressure score 0.9 + first-time cross
Tight angle 1v1 (Salah) 0.03 0.27 +829% Tight-angle skill (1.26x) + solo run counter-attack context

Key Insight: Standard xG systematically underestimates the quality of elite chances (where skill and context create near-certain goals) AND overestimates the quality of blocked or pressured chances (where defensive context makes scoring far harder). xG Vision corrects in both directions.


Computer Vision Pipeline

The project includes a full real-time computer vision pipeline for analyzing match footage. This enables xG Vision to be applied to broadcast video rather than requiring manual event data.

Architecture

Video Frame
     |
     v
Detection (RT-DETR or YOLOv8)
     |
     v
Multi-Object Tracking (ByteTrack via supervision)
     |
     v
Team Classification (SigLIP Embeddings + K-Means Clustering)
     |
     v
Homography Transformation (Pixel -> Pitch Coordinates)
     |
     v
xG Calculation (Standard + xG Vision with Player Multipliers)
     |
     v
GNN Tactical Analysis (optional)
     |
     v
Annotated Frame with Overlays

Detection Engines

The system supports two detection backends:

  • RT-DETR (Real-Time Detection Transformer): Transformer-based architecture from rtdetr-l.pt. Higher accuracy in crowded scenes due to attention mechanisms. Integrated via Ultralytics and optionally through a Roboflow Inference Server at localhost:9001.

  • YOLOv8 (You Only Look Once v8): CNN-based architecture from yolov8n.pt. Faster inference, suitable for real-time processing. Detects 4 classes: player, ball, goalkeeper, referee.

Tracking and Team Classification

  • ByteTrack (via supervision library) maintains consistent player IDs across frames, handling occlusions and re-appearances.
  • Team classification uses SigLIP (Sigmoid Language-Image Pre-training) embeddings with UMAP dimensionality reduction and K-Means clustering to distinguish home vs. away players by jersey color. Manual color seeding is supported for known team colors.
  • Goalkeeper assignment uses a nearest-team-centroid heuristic based on the Roboflow Football AI approach.

Homography Transformation

The HomographyTransformer class (src/cv_integration.py) maps pixel coordinates from broadcast footage to real-world pitch coordinates in meters using cv2.findHomography(). The standard pitch dimensions are 105m x 68m. This enables the analytics engine to compute real distances and angles from detected player positions.

Real-Time xG Overlay

The processed video output includes:

  • Corner-style bounding boxes around detected players (color-coded by team)
  • A persistent xG/pG banner near the ball during shot situations
  • A cumulative header bar showing home/away xG and pG totals
  • EMA (Exponential Moving Average) ball position fallback when detection fails (8-frame lookback)
  • Shot cooldown timer (150 frames) to prevent duplicate shot events
  • Player brilliance multipliers loaded from data/player_multipliers.json

GNN Tactical Analysis

The pG_vision/gnn_tactical.py module implements a Graph Neural Network for real-time tactical scoring during video analysis.

Spatial Graph Construction

Each video frame generates a player interaction graph:

  • Nodes: Each detected player becomes a node with 6 features: [x, y, team_encoding, distance_to_ball, distance_to_goal, is_defender]
  • Edges: Players within a configurable radius (default: 200 pixels) are connected, representing spatial interaction potential.

GCN Architecture

When PyTorch Geometric is available, the system uses a 2-layer Graph Convolutional Network:

  • Input: 6 node features
  • Hidden: 32 channels
  • Output: 3 tactical scores (sigmoid-activated, scaled to 0-100)

When PyTorch Geometric is not installed, the system falls back to geometry-based heuristic scoring that approximates the GCN's behavior.

Three Tactical Scores (0-100)

Score Measures High Value Means
Defensive Shape Formation organization and compactness Well-organized defensive line, minimal gaps
Pressing Intensity Rate of space closure by defenders toward ball Aggressive high press, defenders closing quickly
Passing Lane Quality Number and quality of open passing options Multiple passing outlets available to ball carrier

All scores are smoothed with EMA (alpha=0.3) for frame-to-frame stability.


Streamlit Dashboard -- pG Vision

The pG_vision/app.py file provides an interactive web dashboard for video analysis.

Features

  • Video Upload: Accepts MP4, AVI, MOV, and MKV formats for processing
  • Detection Engine Selection: Toggle between RT-DETR (higher accuracy) and YOLOv8 (faster)
  • GNN Tactical Toggle: Enable or disable tactical analysis overlay
  • Team Color Customization: Color picker controls for manual home/away team color seeding
  • Frame Skip Configuration: Adjustable frame skip interval (1-5) for performance tuning
  • Real-Time Metrics: Live cumulative xG and pG tracking with tactical score progress bars
  • GPU Detection: Automatic CUDA detection with FP16 half-precision support
  • Processed Video Download: One-click download of annotated output video

Theme

The dashboard uses a Manchester United-inspired dark theme with red accent colors (#c70000), gradient backgrounds, custom metric cards, and hidden Streamlit branding for a clean presentation.


Project Structure

xg-vision/
|-- src/
|   |-- analytics/                    # Core xG analytics engine
|   |   |-- __init__.py               # Module exports
|   |   |-- features.py               # 54 engineered features across 5 categories
|   |   |-- player_profiler.py        # Bayesian player skill calibration (8 shot types)
|   |   |-- xg_models.py             # Standard xG & three-layer xG Vision models
|   |   +-- demo.py                   # Analytics demonstration script
|   |-- cv_integration.py             # Base CV pipeline (YOLOv8 + homography + xG overlay)
|   |-- cv_advanced.py                # Advanced CV (K-Means team colors, ByteTrack Re-ID)
|   +-- keypoint_tracker.py           # YOLO-Pose pitch keypoint detection
|
|-- pG_vision/                        # Posterior Goals Vision (Transformer-based pipeline)
|   |-- __init__.py
|   |-- app.py                        # Streamlit dashboard
|   |-- processor.py                  # RT-DETR video processor with GNN overlay
|   |-- transformer_tracker.py        # Roboflow + RT-DETR + SigLIP team classification
|   +-- gnn_tactical.py              # Graph Neural Network tactical analysis
|
|-- scripts/
|   +-- train_pitch_keypoints.py      # YOLO-Pose training script for pitch keypoints
|
|-- data/
|   |-- player_multipliers.json       # Per-player finishing multipliers (City vs Brentford 2024/25)
|   |-- City_Brent.mp4                # Manchester City vs Brentford match footage
|   |-- Barca_Joan.mp4                # FC Barcelona match footage
|   +-- football_ai_nb.txt            # Reference notes
|
|-- tests/
|   |-- test_advanced_pipeline.py     # Advanced CV pipeline tests
|   |-- test_pg_vision.py             # pG Vision integration tests
|   |-- generate_synthetic_video.py   # Synthetic match video generator for testing
|   +-- synthetic_match.mp4           # Generated test video
|
|-- outputs/                           # Processed videos with xG overlays
|   |-- figures/                       # Generated charts and visualizations
|   +-- [processed match videos]
|
|-- models/                            # Directory for trained model weights
|-- generate_thesis.py                 # ReportLab-based thesis PDF generator
|-- requirements.txt                   # Python dependencies
+-- README.md

Getting Started

Prerequisites

  • Python 3.10 or higher
  • pip package manager
  • GPU with CUDA support (recommended for video processing, not required)

Installation

# Clone the repository
git clone https://github.com/vatsinaname/xg-vision.git
cd xg-vision

# Create and activate virtual environment
python -m venv .venv
.venv\Scripts\activate        # Windows
# source .venv/bin/activate   # Linux / macOS

# Install dependencies
pip install -r requirements.txt

Optional Dependencies

# For full GNN tactical analysis (PyTorch Geometric)
pip install torch-geometric

# For SigLIP-based team classification
pip install sports

# For Roboflow cloud inference (alternative to local detection)
pip install inference

Usage

1. Analytics Demo (No GPU Required)

Run the analytics demonstration to see the three-layer model in action with example scenarios:

python src/analytics/demo.py

This runs three demonstrations:

  • Feature extraction showcase with a sample shot
  • Player skill profiling with Bayesian calibration
  • Side-by-side comparison of Standard xG vs. xG Vision across key scenarios

2. Streamlit Dashboard (Web UI)

Launch the interactive dashboard for video upload and processing:

streamlit run pG_vision/app.py

Open http://localhost:8501 in your browser. Upload a match video, configure detection settings, and process the footage with real-time xG overlay.

3. Video Processing (Programmatic)

Process a video file directly via the processor module:

from pG_vision.processor import PGVideoProcessor

processor = PGVideoProcessor(model_type="rtdetr")
processor.load_video("data/City_Brent.mp4", "outputs/result.mp4")
# Process frames in a loop with processor.draw_overlay()

4. Generate Thesis PDF

Generate the full academic thesis document:

python generate_thesis.py

Model Weights

Pre-trained model weights are not included in this repository due to file size. The Ultralytics library will automatically download them on first use, or you can download manually:

Model Size Purpose Auto-Download
yolov8n.pt 6.5 MB CNN-based player/ball detection (faster) Yes (via ultralytics)
rtdetr-l.pt 66.5 MB Transformer-based detection (more accurate) Yes (via ultralytics)

Place the downloaded weights in the project root directory.


Tech Stack

Component Technology Purpose
Core ML XGBoost, scikit-learn xG model training, evaluation, and calibration
Explainability SHAP Feature importance and model interpretability
Object Detection YOLOv8, RT-DETR (Ultralytics) Real-time player, ball, and goalkeeper detection
Object Tracking ByteTrack (supervision) Multi-object tracking with ID persistence
Team Classification SigLIP + UMAP + K-Means Jersey color-based team assignment
Tactical Analysis PyTorch Geometric (GCNConv) Graph Neural Network for formation analysis
Homography OpenCV Pixel-to-pitch coordinate transformation
Dashboard Streamlit Interactive web UI for video processing
Pitch Visualization mplsoccer Football pitch plots and shot maps
Charting Matplotlib, Seaborn, Plotly Static and interactive data visualizations
Football Data statsbombpy Open football event data from StatsBomb
Video I/O OpenCV, MoviePy Video reading, processing, and composition
Thesis Generation ReportLab Programmatic PDF document creation
Environment python-dotenv Environment variable management

Data Sources

  • StatsBomb Open Data via statsbombpy -- Historical shot event data with freeze frames, used for model development and validation.
  • Player Multipliers (data/player_multipliers.json) -- Pre-computed finishing skill multipliers for Manchester City vs. Brentford (2024/25 season), including players like Haaland (1.38x), De Bruyne (1.22x), Foden (1.18x), Toney (1.30x), and Mbeumo (1.28x).
  • Match Footage -- Sample broadcast videos for demonstration. The system accepts any standard football broadcast footage in MP4/AVI/MOV/MKV format.

References

  1. Davis, J. & Robberechts, P. (2024). Biases in Expected Goals Models. KU Leuven.
  2. StatsBomb (2025). Upgrading Expected Goals. StatsBomb R&D.
  3. Rahimian, P. et al. (2025). Automated Explanation of Machine Learning xG Models. Research Paper.
  4. Cavus, M. & Biecek, P. (2022). Explainable Expected Goal Models for Performance Analysis in Football Analytics. IEEE DSAA.
  5. Roboflow (2025). Track Football Players with Computer Vision. Technical Blog.
  6. StatsBomb (2024). AI and Homography Estimation in Football. Technical Report.

License

MIT License -- feel free to use and build upon this work.


Author

Rishabh Vats Analyst, AI Pod at Slice | Former Integrations Engineer at Robylon AI

LinkedIn | GitHub

About

Three-layer Expected Goals model with Bayesian player calibration, real-time CV pipeline (YOLOv8/RT-DETR + ByteTrack), GNN tactical analysis, and Streamlit dashboard.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages