Everyframe · computer vision

One swing over another.

The engine cuts a reference golfer out of their clip. The pass scales the cutouts to the student's build, puts the hips together at address, and warps time so address, top, impact and finish meet. The ghost then plays over the student's swing. An overlay to look at. Nothing is measured.

pipeline cutout → align → time warp scaled by torso length 4 phases meet anchor hips nothing measured
01

The overlay

Left, the student's swing with the ghost over it; the readout names the phase and both clocks, since the ghost runs at its own pace between phases. Right, the three moments that matter, side by side, the hands' paths drawn: the student in amber, the ghost in blue.

setup phase
0.00 s student
0.00 s ghost
1.0× ghost pace

The pair

Top, impact and finish with the ghost over the student
Top, impact, finish

Student in amber, ghost in blue, both hands' paths

The ghost is the reference golfer's cutout from the strobe read, keyed back out of the engine's render. It is tinted and desaturated so it never passes for the student, and the hips anchor keeps it on the student's body from address to finish; the reference's own sway is taken out, which is the price of an overlay that stays put.

02

Lining two swings up

Three moves, all from the pose the tempo read already had. Scale: the ghost's torso is stretched to the student's, shoulder centre to hip centre. Place: the hips meet at address, and with the hips anchor they keep meeting every frame. Time: the ghost plays at whatever pace makes its four phases land on the student's.

1.00× scale
no mirrored
student tempo
ghost tempo
Segment Student Ghost Ghost pace

Mirroring is decided from the pose: which side of the hips the hands hang at address. A pace above 1 means the ghost's segment is longer than the student's and plays faster to fit.

03

Pipeline

The strobe read's cutout pass on the reference, then one numpy pass that aligns and renders.

1

Cut the reference out golf_cutout.rs

The same pass the strobe read uses: segment with SAM2 and one centred prompt on a square around a body anchor, mask_composite painting the rest magenta, three anchors so every frame of the swing has a plausible mask.

2

Align golf_ghost.py

Scale by torso length, mirror if the two face opposite ways, put the hip centres together at address. With the hips anchor, an extra shift per frame keeps them together through the swing.

scale  = torso(student) / torso(reference)
mirror = facing(student) != facing(reference)
offset = hip(student, address) - scale * hip(reference, address)
shift[i] = hip(student, i) - place(hip(reference, warp(i)))   # the hips anchor
3

Warp time and render golf_ghost.py

For every student frame, its time maps to the reference's between matching phases, the nearest reference frame is keyed out, tinted, scaled, shifted and pasted at 55% over the student. A clip, a poster and the triptych.

t_ref = interp(t, [address, top, impact, finish](student), [...](reference))
tile  = tint(scale(cutout[nearest(t_ref)]))
frame = paste(student[i], tile, alpha * 0.55, origin + shift[i])
04

What it does not do

An overlay is not a comparison. These are the honest edges.

Different clubs, different shots

The reference and the student were not filmed for each other. A wedge and a driver put the hands in different places at address, and the ghost shows that gap as if it were technique.

One body, two builds

Torso length sets the scale, so the ghost's legs land wherever the reference's leg-to-torso ratio puts them. Feet a little off is the reference's build, not the student's stance.

The anchor hides the sway

With the hips anchor the ghost follows the student's hips every frame, so the reference's own weight shift is removed. The address anchor keeps it, and the ghost then drifts a torso length by impact.

Nothing is measured

No angles, no distances, no verdict. The tempo and stroke reads measure; this one shows two swings on one frame and stops there.