How thanksmors/pbvision works
1. Repository shape
- The repo is split into a portable analysis engine under engine/pbengine/ and a thin application layer under api/.
- The engine can run standalone from the command line to produce result.json; the API wraps that engine for uploads and local viewing.
2. End-to-end purpose
- The system analyzes a pickleball match video at the point level.
- The main output is a structured JSON result containing rallies/points, serve and bounce events, winner calls, and confidence / review flags.
3. Top-level data flow
- The pipeline is: video probe → court detection/homography → player tracking → ball tracking → rally segmentation → serve/bounce/winner inference → JSON export.
- The key architectural boundary is between video/ML-heavy perception stages and the deterministic logic stages that operate on rectified coordinates and tracked events.
4. Engine subsystem
- engine/pbengine/pipeline.py is the orchestration entry point.
- It ties together IO, court, player, ball, and rally stages and is designed to run both with real models and with synthetic fixtures.
- Model-backed stages are dependency-injected and can be swapped for test fixtures, which is why the engine is usable without weights for demos and tests.
5. Court geometry subsystem
- court/detector.py, court/homography.py, and court/court_model.py handle court finding and coordinate normalization.
- This subsystem maps camera-space detections into a normalized pickleball court frame, which is crucial because later heuristics assume a stable court coordinate system.
6. Player tracking subsystem
- detect/players.py uses Ultralytics YOLO26 plus ByteTrack.
- Its role is to identify and track players across frames, feeding contextual signals into later rally and serve logic rather than directly producing the final point result.
7. Ball tracking subsystem
- ball/tracker.py and ball/kalman.py handle the highest-risk stage: locating the ball and smoothing its trajectory.
- The README notes this stage uses WASB-SBDT plus jump gating and Kalman smoothing, and the architecture treats it as the most failure-prone component.
- Output from this stage is a rectified ball path used by the rally logic.
8. Rally / point logic subsystem
- rally/segmentation.py, rally/serve.py, and rally/winner.py convert the tracked trajectory into point boundaries and outcomes.
- This layer is mostly heuristic and deterministic: it decides where rallies start/end, how serves are identified, and who won each rally.
- bounce/heuristic.py supports bounce inference, which is a core input to winner classification.
9. Schema and contract
- schema/models.py defines the structured result contract used by both the engine and the API/viewer.
- The JSON schema is the integration boundary: the engine writes it, and the app/front end renders it.
- This contract is what allows the demo fixture pipeline, CLI pipeline, and UI to share one representation.
10. API and viewer
- api/app/main.py exposes the FastAPI service; api/app/jobs.py manages job execution/state.
- The app does not appear to run the ML pipeline inline; instead it spawns the engine as a subprocess and polls a status file, which keeps the web layer thin and isolates the analysis runtime.
- api/frontend/index.html is a single-page viewer for displaying the uploaded video and per-point analysis results.
11. Fixtures and synthetic demo path
- fixtures.py provides scripted stand-ins for the model-backed stages.
- This enables a fully CPU-only demo run and exercises the full pipeline, including segmentation and winner reasoning, without requiring model weights or real footage.
- The tests also lean on this boundary to validate logic independently of ML inference.
12. Testing and support tooling
- engine/tests/ covers the pure-logic pieces: bounce, homography, Kalman, rally, schema, winner, and fixtures.
- scripts/download_weights.sh and scripts/run_local.sh support two modes of use: local app development and model-backed analysis with downloaded weights.
- pyproject.toml likely separates core, API, ML, and dev dependencies, matching the engine/app boundary.
13. Architectural takeaway
- The repo is intentionally organized around a “portable engine + thin UI wrapper” pattern.
- All expensive or uncertain perception work is isolated in the engine, while the API and frontend only coordinate runs and present the resulting point-level analysis.
Main entry points: pipeline.py Pipeline · segmentation.py Rally split · fixtures.py Fixtures · jobs.py Job state
Components 17
Engine
Portable analysis engine and point-level inference pipeline
- Pipeline · Coordinates the end-to-end analysis flow and stage injection
engine/pbengine/pipeline.py - Video probe · Loads and probes input video frames and metadata
engine/pbengine/io/video.py - Court detect · Finds court geometry in the source video
engine/pbengine/court/detector.py - Homography · Maps camera-space observations into a normalized court frame
engine/pbengine/court/homography.py - Court model · Represents the canonical pickleball court coordinate system
engine/pbengine/court/court_model.py - Player track · Detects and tracks players to provide context for point logic
engine/pbengine/detect/players.py - Ball track · Locates the ball and produces a rectified trajectory
engine/pbengine/ball/tracker.py - Kalman · Smooths ball motion and stabilizes noisy detections
engine/pbengine/ball/kalman.py - Rally split · Finds rally boundaries from the tracked events
engine/pbengine/rally/segmentation.py - Serve logic · Identifies serve events and serve-related state transitions
engine/pbengine/rally/serve.py - Bounce heuristic · Infers bounce events used by rally outcome logic
engine/pbengine/bounce/heuristic.py - Winner logic · Classifies rally winners and review flags
engine/pbengine/rally/winner.py
API / UI
Thin FastAPI wrapper and local viewer
Support
Fixtures, schema, and tooling used across runtimes
- Result schema · Defines the structured output shared by engine, API, and viewer
engine/pbengine/schema/models.py - Fixtures · Provides stand-ins for model-backed stages for demo and tests
engine/pbengine/fixtures.py
Connections 21
- API app → Job state: delegates runs · The web service hands analysis requests to job management
- Job state → Pipeline: launches engine · Jobs execute the analysis pipeline as a separate runtime
- API app → Viewer: serves UI · The API exposes the local viewer for uploaded videos and results
- Pipeline → Video probe: reads video · Pipeline begins by probing the input media
- Pipeline → Court detect: detects court · Finds the playing surface before rectification
- Court detect → Homography: feeds geometry · Court detections are normalized into a stable frame
- Homography → Court model: maps to court · Rectified coordinates are expressed in the canonical court model
- Pipeline → Player track: tracks players · Player detections provide context for later reasoning
- Pipeline → Ball track: tracks ball · Ball localization is the highest-risk perception stage
- Ball track → Kalman: smooths path · Ball trajectories are stabilized before point logic
- Pipeline → Rally split: splits rallies · The pipeline converts trajectories into rally segments
- Rally split → Serve logic: identifies serves · Serve detection helps mark rally starts
- Rally split → Bounce heuristic: infers bounces · Bounce events support downstream winner reasoning
- Rally split → Winner logic: classifies outcome · Rally boundaries and events feed point outcome logic
- Bounce heuristic → Winner logic: supports decisions · Bounce inference is a key input to winner classification
- Pipeline → Result schema: writes result · The engine emits the shared structured JSON contract
- Fixtures → Pipeline: swap stages · Synthetic stand-ins can replace model-backed components
- Fixtures → Rally split: drives demos · Fixtures allow the deterministic rally logic to run without weights
- Fixtures → Winner logic: drives demos · Synthetic inputs exercise point outcome reasoning end to end
- Job state → Result schema: reads result · The web layer consumes the same structured output written by the engine
- Viewer → Result schema: renders result · The viewer presents the shared result model to users