Skip to content
NAMEFRAMEApply for Pilot

Occlusion is not obscuration: what a visibility gate cannot see

A visibility threshold answers one question: how much of this object is hidden behind something. It is a geometric question and it has a geometric answer, which is why it can be computed exactly. Shadow is not geometry. Fog is not geometry. Neither is dust, or a dark hour. An object drowned in any of them is scored fully visible, and the frame passes every gate this capture has.

Measured on
The published Parisian street capture
Invisible instances
43 of 412 sampled, 10.44%
Detected by
The run's own labels-vs-rgb check
Status
Measured, since September 2026

Where the two questions come apart

The identity buffer knows where every object is because the engine drew it there. The visibility ratio compares what is drawn against what would be drawn with nothing in front of it, and the difference is occlusion. That number is exact and it is the right number for the question it answers.

It is not the question a model asks. A model asks whether there is anything in the photograph to learn from, and the photograph can be empty where the geometry is full.

The frame averages 43.6 of 255. The pixels under its labels average 22.0The middle panel is the same file brightened five times here, to show that the street is populated

This is the case worth understanding, because nothing about it looks wrong. The frame averages 43.6 of 255, which is a dim but ordinary exposure, and the sky and the lit roofs carry most of that on their own. The street below is in shadow, and that is where the people, the cars and the market stalls are. The pixels under their masks average 22.0 of 255.

The middle panel is the same file with its brightness multiplied by five, done here rather than in the capture, and it is the reason this page exists: there is a populated street in that image. The labels are right about every object in it. Nothing was occluded and no gate was wrong to stay quiet. What a model receives is the left panel.

What it costs, measured on a capture you can download

These numbers come from the Parisian street capture, which is published in full. The check that produces them ships inside the pack, so the claim can be read off the same file a reader downloads rather than taken from this page.

On the published captureCountShare
Frames in the capture300
Labelled instances the check sampled412over 300 frames
Of those, invisible in the photograph4310.44%
Frames affected30one in ten
Frames whose labels sit under 30 of 25514 of 2984.7%
Frames carrying no labels at all2kept by the fallback

The run graded C and publishes that grade. This check is one of the two it failed, and it failed by naming the instances: which class, which pixel box, which frame. A check that says a percentage and not a location cannot be acted on.

Three ways it happens, and they are not the same problem

The object is in shadow while the frame is not. The case above. Nothing in the exposure or the composition signals it, which is what makes it the hard one.

The frame is dark. An overcast evening at 16:40 came out at 4.4 of 255 across the whole image. This one is at least obvious, and a brightness floor on the frame would catch it. That floor is not free either: it reads the rendered image, and a gate that reads the rendered image is what broke reproducibility on this same capture, which is written up in full on the reproducibility page.

Weather thick enough to erase the scene. Two of this project’s thirteen weather presets are sand and dust storms. A dust frame carried thirty-two labelled instances and showed, to the eye, an empty brown rectangle. The labels were correct and nobody could check them, so both presets were dropped from the capture rather than published. That decision is in the recipe, with the reason.

An overcast evening at 16:40. The whole frame averages 4.4 of 255This one is at least visibly dark, which makes it the easier of the two to catch

A second thing this found: the fallback outranks the gate

Two frames of the three hundred carry no labels at all. The capture asks for at least three targets in view and refuses a frame whose segmentation is empty, and both of those rules were on.

They were kept because after twenty-five attempts to find an acceptable viewpoint, the job is told to relax its constraints rather than stop. That is a reasonable default and it was chosen deliberately: a run that halts at frame 180 proves nothing about frames 181 to 300. It is also, stated plainly, a setting that lets a frame through the gate it just failed.

Both frames record their own failure. The viewpoint validation block in each says it was not accepted and says how many attempts it took, so a consumer can filter them out. Nothing is hidden. It is still worth knowing that the count of frames in a capture is not the count of frames that passed.

One of the two: an ordinary frame whose identity mask is entirely emptyIt records that it was not accepted, and it is in the capture

What fixed it, and what it found

The fix took the shape this page predicted: a pass over a finished dump rather than a gate inside the capture. Reading the rendered image inside a gate is what cost this pipeline its reproducibility once already, so the measurement stays out of the decision loop and the capture stays byte-reproducible.

Each labelled instance gets two numbers. How far its pixels sit from a ring of background grown just outside its own mask, and how much the inside of it varies. Two rather than one, because contrast alone gives the wrong answer: an object patterned like its surroundings has no contrast at all and is perfectly visible, since it is the pattern that gives it away. Only when both are low is there genuinely nothing to see.

VerdictInstancesShare
Readable58762.38%
Blended: low contrast, interior still varies31333.26%
Invisible: nothing to check the label against222.34%
Not measurable192.02%

Those are 941 instances across every fifth frame of the same capture, at six grey levels for both thresholds. The twenty-two invisible ones were cropped out and looked at before the number was published; they are black rectangles.

This does not replace the 10.44% above, and the two are not the same measurement. The older check asks whether an instance is dark; this one asks whether anything distinguishes it from what surrounds it, which is a harder thing to fail. The strict answer is 2.3%, the loose one (counting everything with low contrast) is 35.6%, and the older check falls between them. Publishing all three is more use than picking whichever is most flattering.

No threshold is asserted as correct. Whether an object at four grey levels of contrast is usable depends on what the corpus is for, so both numbers are arguments to the command and a run can be failed over the resulting share.