cyclegraph

Instrument check

The hand box was measuring the wall

Ask a dense optical flow estimator for a hand's speed and it answers correctly until the hand box moves further than it can follow. Then it reports the background, at a gain equal to the ratio of their depths. The ego-motion correction that should catch this subtracts the background, so the two failures cancel and the residual looks like a slow hand rather than a broken measurement.

Drag it

Watch the estimator lose the hand

One rendered scene, one variable: how far the hand box travels between the two frames. The camera translates over a static scene, so the near hand plane moves further than the far background. Pale arrows are the true motion, red arrows are what the estimator recovered. Drag the slider and watch the red stop growing.

The curve

The knee belongs to the estimator. The floor belongs to the geometry.

Estimator

Your geometry

Does this reach your setup?

The floor is the ratio of two distances, so it moves with the bench. The knee moves with the estimator and the decode. Put your numbers in and the harness rule answers. Passing is not gain near 1.0 everywhere; nothing does that. Passing is your knee sitting outside the displacements your work actually produces.

Decode

More pixels is not more signal

Click a row to highlight that decode in the curve above.

The lens

A scalar cannot cancel a field that varies with radius

Under pure camera rotation a correct model cancels the flow exactly, because rotational flow carries no depth information. The rule subtracts the median flow outside the box, which is one number, and on a fisheye the field it is cancelling is not uniform. This is closed-form geometry with no estimator involved, so it is a property of the rule and the lens. Drag to see what a given head rotation leaves behind.

Limits

What this cannot tell you

Reproduce

Run it against your own estimator

The harness needs numpy and nothing else. No corpus, no token, no GPU.

pip install huggingface_hub && hf download \
  caiotheodoro/cyclegraph-flow-gain --repo-type dataset --local-dir .

from cyclegraph_flow_gain import gain_curve

def my_estimator(first, second):   # -> (H, W, 2) float32, or None on failure
    ...

curve = gain_curve(my_estimator, width=960)
print(curve.knee_px, curve.floor_gain, curve.floor_ratio_expected)
print(curve.verdict(operating_displacement_px=12.0))