Overruled
A computer-vision line judge for tennis: one fixed camera, four clicked court corners, and an automatic IN/OUT/TOO CLOSE call on every bounce.
- Tech
- Next.js, TypeScript, Python, YOLOv8, OpenCV, AWS Lambda, Amazon S3
- Date
- Jul 24 to 25, 2026
- Status
- Hackathon Build — Live Demo
Hawk-Eye costs six figures per court, so high school and college tennis matches get no automated line-calling at all, calls depend entirely on whoever happens to have the best angle. Working with a teammate over one overnight hackathon, I built Overruled, a virtual line judge that takes a single fixed-camera video clip, has the user click the four court corners once, and calls each bounce IN, OUT, or TOO CLOSE with a margin in centimeters, running on one ordinary camera and no specialized hardware.
Architecture
Detection Pipeline
A YOLOv8 model detects the player and ball per frame; when its ball-detection rate falls below a set threshold, which stock YOLO hits often on a fast-moving tennis ball, the clip automatically re-runs through a fallback tracker built on HSV color thresholding and frame differencing that recovered the large majority of frames the trained model missed. The whole thing runs as an async AWS Lambda invocation behind S3, so upload and inference are decoupled: the browser uploads directly to S3 via a presigned URL, and the analysis endpoint returns immediately rather than blocking on a multi-minute detection pass.
Bounce Detection & Scoring
The four clicked court corners solve an 8x8 linear system, hand-rolled Gaussian elimination, no OpenCV.js dependency, that maps pixel coordinates to real court coordinates in meters. Bounce detection looks for a sustained velocity flip, not just a single sign change, so a racket hit or a lob's peak doesn't get misread as a bounce, and a phantom-detection guard rejects any candidate bounce with no real, non-interpolated detection nearby, so a gap in tracking can never fabricate a call.
Technical Challenges
Bounce detection's first version looked for a local minimum in screen coordinates, the wrong direction, since screen-y increases downward and a bounce is actually a local maximum. Fixing the sign then exposed a second bug where smoothing flattened the true single-frame peak into a plateau that broke a strict monotonicity check, resolved with a non-strict comparison that collapses adjacent candidate frames into one event. A torch/torchvision version mismatch that built cleanly but crashed only on a live Lambda invocation, not locally, got caught by adding a build-time smoke test that actually calls the failing operator, so a future mismatch fails the Docker build instead of a production call.
Other
- Deployed with a real AWS backend (S3, Lambda, ECR) behind the live demo, not a local-only prototype.
- 13 automated tests cover trajectory interpolation, bounce detection, homography correctness, and score-boundary classification.
- Built and shipped in roughly 20 hours across one overnight hackathon with a teammate.