I rebuilt the bald-head failure on purpose
In October 2020, a Pixellot automated camera at an Inverness Caledonian Thistle match tracked a linesman's bald head instead of the ball for the entire game, and I rebuilt that failure on purpose because it is the cleanest example I know of a vision system being confidently, uselessly wrong. Under floodlights a shiny scalp reads to a detector like a bright round object, so the model scored the head as a "ball" at high confidence, and a camera told to follow the highest-confidence box walked off the pitch and stayed there.
When I ran my layer on a real broadcast clip, I reproduced the incident honestly rather than pretending I had caught it live: real YOLO11x already finds the ball and the people on every frame, and I promoted the linesman's head detection into a high-confidence "ball" candidate for one window, the way the floodlights did it for real in 2020. Then I let two trackers fight over the same detections. The naive follow-highest-confidence tracker locked onto that injected head candidate. My layer, called Plumbline, rejected the same box on geometry and kinematics and stayed on the actual ball. Plumbline sits downstream of the detector and asks the one question the detector never asks: given where a real ball was a moment ago, is this detection physically possible?
On real YOLO11x detections, the naive tracker follows the injected head candidate off the pitch; the same physics gates reject it and hold the actual ball.
Watching three gates reject a detection the model loved
I did not trust the rejection until I could read the reason for it, so the first thing I built after the two trackers was a live gate feed that prints why each candidate lives or dies. On the synthetic bald-linesman scenario, where I rendered the scene and therefore know the true ball position on every frame, the injected head impostor climbs up to 98 percent confidence and the feed rejects it three ways at once. The kinematic gate, an Unscented Kalman filter running a projectile model, scores the head dozens of standard deviations off the ball's predicted path, reaching 82.3 sigma at the worst frame in that clip, against a reject line of 5. The optical-flow gate notices the "ball" is standing still in open play. The geometric gate computes that a 22 cm ball at that depth should be about 22 pixels wide, not the fifty the head spans.
I built those three checks as plain numpy and scipy, thresholds I set and can read, sitting outside any model, because a trust layer whose own trust rests on a second model's word has not removed the problem, only moved it. Across the full synthetic run the gates rejected all 18 impostor detections and kept the real ball, which passed at 0.87 confidence and 0.4 sigma. The accept rule is boring on purpose: under 3 sigma passes, over 5 sigma is rejected, and the 3-to-5 band is flagged for review rather than trusted.
On the synthetic scenario, the gate feed rejects the injected head on all three gates at once, while the real ball passes every gate and is accepted.
The 97.7% I didn't want to ship alone
I had a number I was proud of and did not fully believe. On the synthetic scenarios, with perfect ground truth and seed 7, Plumbline held 97.7 percent time-on-target against 80.3 percent for follow-highest-confidence and 40.2 percent for the industry's usual fix of raising the confidence threshold. That last comparison is the one worth dwelling on: on the clean set, raising the threshold drops 43.2 percent of the real low-confidence balls while still grabbing the impostor, and my gates hold their clean-set miss to 2.3 percent, which is a single frame of acquisition latency rather than a lost ball. The physics works orthogonally to the confidence knob, so reaching for that knob was never going to solve this.
But 97.7 percent was measured on a scene I rendered myself, where I knew exactly where every ball was because I had put it there. So I took the same three gates, unchanged, and pointed them at a real broadcast clip with real YOLO11x detections, 240 frames I did not author. They held the ball 68.3 percent of the time, against 43.8 percent for the naive tracker and 30.0 percent for the raised-threshold one, with 26 pixels of mean error against the naive tracker's 193.
The honest real-footage scoreboard: 68% on target versus 44% for the naive tracker, on 240 frames of real YOLO11x detections.
Why I refused to fake the depth
I could have made the real-footage number look better, and the way to do it would have been a lie. The synthetic path runs a full 3-D Unscented Kalman filter because I built that scene with a calibrated pinhole camera and I know its geometry exactly. A single uncalibrated broadcast clip gives me no metric depth, so a world-space 3-D filter there would have been a prop tuned to flatter a demo. I ran the gates in the image plane instead, on a 2-D Kalman filter, and I labeled it as image-space right in the app. The three gates are the same code; the filter beneath them is honestly smaller.
That choice is why the real number is 68 and not 97, and I would rather defend a 68 than qualify a 97 in every conversation. Real footage is harder, and the honest direction, physics beating both baselines, holds on detections I never scripted. These are tracking-quality metrics regardless, independent of how good the detector is, because a ball that is physically impossible is wrong no matter how sharp the pixels become. The detector itself is swappable behind a one-function interface, a simulated black box on the synthetic scenes and real YOLO11x on the clip; the value was always in the layer around it.
What a physics reason on file is actually for
I kept returning to a question a buyer carrying real liability would ask, and it is not "how accurate is it." It is "when your camera made that call, what was the reason, and can you show me." SoccerNet, the reference tracking benchmark, calls multi-object soccer tracking "far from solved" and notes that no physics-aware method is integrated into its benchmarks yet (WP43 research, 2026). In a field where 95 percent of computer-vision projects never reach production and edge cases are, in that same research, "100 percent of the liability exposure" (WP43 research, 2026), a decision you cannot explain is a decision you cannot deploy.
So every call Plumbline makes is written to a file: the seed, the thresholds, each candidate's confidence, and each gate's numeric verdict with a plain reason, exportable as JSON or HTML. There is an optional narrator that turns that telemetry into an English summary, but it only describes what already happened; the record is the arithmetic itself. You can run the whole thing and read the log at veriprajna.com/demos/physics-constrained-computer-vision.
The exported decision log: every frame's candidates with each gate's numeric verdict and plain reason, seed and thresholds in the header.
I think the honest 68 is worth more than the pretty 97.7, and not only for the obvious reason. A vendor accountable for an automated camera does not need the highest number on a slide. It needs to know, before the camera swings off the pitch on live television, which detections its system will refuse to believe and exactly why it refused.