Nawaz Labs

Ring

JTON · one signal that survives a spinning hand

July 2026

The story

A hand is the most restless thing a camera will ever track. It spins, tilts, closes, comes near, pulls away. A ring try-on has to survive all of it: stay on the finger, face the right way, and know whether the camera is looking at your palm or the back of your hand. There is no depth sensor to ask. The inherited logic could not hold through a rotation, so the engine was rebuilt from the hand's own geometry up.

video pendingdrop at public/jton/ring/media/rotation-demo.mp4
Placement and face detection holding through full hand rotation.

The orientation signal

The whole engine rests on one measurement. Take two vectors across the palm, cross them to get the palm's normal, then normalize by the spread itself. The result behaves like the sine of the palm's angle to the camera, and it has the property that makes everything work: distance cancels out. A flat hand reads the same near or far. The value collapses toward zero only when the hand is genuinely edge-on. No calibration, no depth.

From landmarks to a face decision, with nothing that flickers.

Around the raw signal:

  • A three-state latch, front, back, and edge-on, with asymmetric thresholds (commit at 0.35, edge-on under 0.2), so the shown face never strobes at a boundary.
  • A ten-frame hold before accepting a left-right hand flip, so one bad frame cannot mirror the ring.
  • Separate smoothing channels for angle, scale, and center, each tuned on its own, so fine motion survives and noise does not.

Placement

The ring anchors at 72 percent along the first segment of the ring finger, between the knuckle and the first joint, rotated to the finger's axis and scaled to the hand. Front and back of each ring are separate images per variant, swapped by the latch, with a distinct back-of-hand offset matching the asset framing.

Stability, found forensically

The hard bugs in this engine were runtime bugs, not math bugs, and they were hunted with instrumentation rather than guesses.

  • Crashes traced to competing render loops. Ownership of the animation frame was made explicit, one owner, kick and cancel, and the double-loop state disappeared.
  • A picture-in-picture video element was surviving teardown and holding the camera. Explicit teardown fixed re-entry.
  • Crop blending was doing detection-rate work at display rate. Moving it where it belonged removed a stall.
  • Loss of tracking now degrades to a soft re-acquire instead of a restart.

Numbers

Landmark source21 hand landmarks per hand
Orientation latchcommit 0.35 · edge-on 0.20 · 3-state with hold
Handedness debounce10 consecutive frames
Anchor72% along the finger's first segment, axis-rotated

Open items

  • A placement bias is logged with its root cause identified and not yet corrected: the ring sits slightly high and left on both webcam and mobile. The analysis points at the anchor position combined with a fixed vertical offset that is not display-scaled.
  • A sustained-use freeze and memory issue is under active investigation, with live performance counters shipped in the current build to capture it in the act.

Both are shown here on purpose. Knowing exactly what remains is part of the standard.