--- title: Kicky AI emoji: ⚽ colorFrom: green colorTo: yellow sdk: gradio sdk_version: 6.18.0 python_version: '3.12' app_file: server.py pinned: false license: apache-2.0 short_description: check if you have the skill to make it the worldcup tags: - track:backyard - sponsor:openbmb - sponsor:openai - sponsor:nvidia - sponsor:modal - achievement:offgrid - achievement:welltuned - achievement:offbrand - achievement:llama - achievement:sharing - achievement:fieldnotes --- # ⚽ Kicky AI β€” Football Shot Analysis **They measure your shot. You fix it.** πŸŽ₯ **Demo video:** https://www.youtube.com/watch?v=knL8shghyBU Β· πŸ“° **Blog:** https://dcrey7.substack.com/p/world-fut-coach Β· 🐦 **X thread:** https://x.com/dcrey77/status/2066331088331358643 Upload a shot clip (or pick a held-out test example). From a single clip, **one small model + pure geometry/physics** produce: | Output | How | |---|---| | **Goal / no-goal + timestamp** | ball ∩ goal + shot physics (kick β†’ flight β†’ settle-in-net vs rebound / over-the-bar) | | **Who shot it** | ball ∩ player possession over time (last touch before the ball reaches goal) | | **Shooting foot (L/R)** | MediaPipe (BlazePose) on the shooter at the kick frame | | **Shot speed (km/h)** | the ball's apparent diameter (real ball = 22 cm) as a pxβ†’m scale | | **AI coaching** | a vision-LLM grades the shot: Verdict β†’ Fix β†’ Fix β†’ Drill | The video shows **player segmentation masks** (with `P1`/`P2`/`P3` labels that flip to `P# BALL` on possession), a **green goal mask**, a smooth **ball trail**, and a red **goal-spot marker** β€” plus a separate **Result** table, **Shot-speed** card and **Pose-Detection** card. ## The approach β€” foundation-model labelling β†’ real-time distillation The interesting part isn't one model, it's a **pipeline that needs zero manual labels**: 1. **Auto-label** every clip with **SAM3** ("ball" / "person" / "goal post"); where SAM3 misses the small/blurred/tilted ball, **NVIDIA LocateAnything-3B** fills the gap. 2. **Derive events geometrically** β€” ball∩player β†’ possession; ball∩goal + trajectory physics β†’ goal (the rest-in-net vs rebound vs over-the-bar rules handle 2D depth ambiguity). 3. **Distil** those auto-labels into one fast **RF-DETR-Seg** model (ball / player / goal) β€” replacing the slow SAM3 + LA stack at inference. The distilled detector runs live on **ZeroGPU**; everything else is CPU geometry. ## The AI coach β€” two vision models, one toggle After the geometry, a **vision-LLM looks at the strike frame** and grades the shot, grounded on the measured stats (goal / foot / speed + pose angles). It streams in separately so the results never wait on it: - ⚑ **Offline** β€” **MiniCPM-V-4.6** (OpenBMB, ~1.3B) runs **fully on this Space's own ZeroGPU**, no external call. - ☁️ **Online** β€” **NVIDIA Nemotron-Nano-12B-v2-VL** (GGUF Q4_K_M + mmproj) served through a **llama.cpp** server on **Modal** (A10G GPU). ## Built with β€” sponsors, models & badges - ⚑ **Modal** *(sponsor)* β€” runtime for the **online Nemotron coach** (llama.cpp server); see `modal_coach.py`. - 🟣 **NVIDIA** *(sponsor)* β€” **Nemotron-Nano-12B-v2-VL** powers the online coach; **LocateAnything-3B** rescues the tiny/tilted ball during auto-labelling. - 🟒 **OpenBMB** *(sponsor)* β€” **MiniCPM-V-4.6** is the **offline, on-device coach**. - πŸ€– **OpenAI Codex** *(sponsor)* β€” built the browser **annotation tools** (Codex-attributed commits in this Space's git history). - πŸ”— **Shared agent trace** *(Sharing is Caring)* β€” the sanitized Codex build trace is on the Hub: [`kicky-ai-codex-trace`](https://huggingface.co/datasets/build-small-hackathon/kicky-ai-codex-trace). - πŸ¦™ **llama.cpp** *(Llama Champion)* β€” runtime for the Nemotron GGUF (Q4_K_M) coach. - 🎨 **Custom UI** *(Off-Brand)* β€” a bespoke football-stadium frontend on **`gradio.Server`** (hand-written HTML/JS + SVG pitch, not default Gradio Blocks). - πŸ› οΈ **Fine-tuned model** *(Well-Tuned)* β€” RF-DETR-Seg, distilled and published at [`kicky-ai-rfdetr-seg`](https://huggingface.co/build-small-hackathon/kicky-ai-rfdetr-seg). - πŸ“΄ **Runs offline** *(Off the Grid)* β€” choose **Offline** and the whole pipeline + coach run **on-device with no cloud API**. - πŸ“ **Write-up** *(Field Notes)* β€” full blog on [Substack](https://dcrey7.substack.com/p/world-fut-coach) + `docs/blog.md`. ## Results (held-out 12-clip test set) | Detector | Goal | Leg | Pose-capture | |---|---|---|---| | SAM3 + LA (teacher, zero-shot) | 83 % | 82 % | 92 % | | **RF-DETR-Seg-Small** (student, distilled) | 75 % | 75 % | **100 %** | > Honest note: goal detection on monocular 2D tops out in the low-to-mid 80s % β€” a ball > *in front of* the goal and a ball *in the net* are the same pixels (depth ambiguity). Model β†’ [`build-small-hackathon/kicky-ai-rfdetr-seg`](https://huggingface.co/build-small-hackathon/kicky-ai-rfdetr-seg) Β· Dataset β†’ [`build-small-hackathon/kicky-ai-spf`](https://huggingface.co/datasets/build-small-hackathon/kicky-ai-spf) Every model is small (RF-DETR-Seg-Small Β· MiniCPM-V-4.6 1.3B Β· Nemotron-Nano-12B), well under the 32B cap. Built for the **Build Small Hackathon** by a Sunday-league player who wanted to know if his strikes have World Cup form.