Skip to main content

Module motion

Module motion 

Source
Expand description

Photometric motion evidence on analysis and native images: hypothesis generation from matches, patch errors, audits and integer refinement. Every threshold is the historical one; tie-breaking (first minimum, distance to the guess) is preserved so reconstructions stay reproducible.

Structs§

Audit
ExtractedPatch
One extractPatches output patch: region-local native pixels plus its size × size luma data.
Gray
MatchPoints
Matched point pairs (a.x, a.y, b.x, b.y, unique) in analysis pixels.
Motion
MotionField
NativeRefinement
Patch
Keyframe patch (region-local origin, size×size native luma).
PatchError
Point

Constants§

MOTION_CELL
Fixed motion-field cell size (analysis pixels per side). Shared with abi::ls_layout selector 9 so the TS binding’s layout assertion actually guards it instead of duplicating a bare literal.
TRIMMED_KEEP
Share of the per-point errors NativeRefinement::trimmed keeps. On real steps the plain mean rejected (a sidebar at 14.3, a tab bar at 14.9) 70, 75 and 80 % trims gave 2.5–5.7 at the true offset and at least 15.7 at offsets 3 or 10 px off or at zero; 75 % is the middle one.

Functions§

audit_translation
Held-out photometric evidence on textured pixels with both observations clamped to the pane.
detect_scale
RANSAC similarity probe over unique matches; a change detector, never a licence to rescale pixels.
estimate_motion
Per-cell motion labelling of b against a from pre-computed matches (current b → previous a).
extract_patches
Native-resolution texture samples around features (analysis-resolution points, scaled by factor), non-overlapping, clamped to region, first count accepted in feature order. native is the FULL native luma plane (native_width × native_height); a caller-supplied region that would read outside it is rejected (empty result) instead of indexing past the plane — the historical TS never validated this because a JS typed-array read past the end just returns undefined, but a Rust slice index would panic.
patch_error
Clipped robust error of b against a shifted by (dx, dy), sampled every step pixels inside r.
probe_scale
When translation fails, asks explicitly whether previous (resampled at each candidate scale) explains current — fuses resampleGray + extractFeatures(320) + matchFeatures + translationHypotheses(4) + the support/audit gates into one call per candidate scale, exactly the historical TS loop’s order. First strict minimum by agreeingError in scale order (matches the TS !best || audit.agreeingError < best.error).
refine_native
Native-pixel refinement on textured luma edges of b inside region, matching against a at integer offsets. labels/code (region atlas membership) restrict both frames when given. Composes select_native_points and refine_native_at; a caller evaluating several candidates over the same b/region/mask should call those directly to select once and reuse the points (see track::odometry).
refine_native_at
Native-pixel refinement of b against a at integer offsets, given points already chosen by select_native_points for this b/region/mask. Split out of refine_native so a caller with several hypotheses over the same region (track::odometry) selects the points once and reuses them.
refine_patches
Aligns keyframe patches in the current native luma frame at integer offsets around guess (current → keyframe).
refine_spatial_patches
Re-acquisition must represent the whole pane: many patches on one fixed control are not many independent votes for its motion. Weight each patch by its nearest-neighbour cell’s area, sampled at the patch scale. Drift refinement keeps its original texture-weighted residual.
refine_translation
Integer refinement of p within radius by patch error; ties resolve toward the original guess.
resample_gray
Bilinear resample of an analysis image (probe only; output pixels are never resampled).
sampling_insensitive_error
refine_native_at’s cost of the points at offset, and its runner-up (the lowest cost at an offset more than two pixels from it, within radius), with each point compared by Birchfield and Tomasi’s sampling-insensitive dissimilarity (“A Pixel Dissimilarity Measure That Is Insensitive to Image Sampling”, 1998) instead of the plain difference. Each value is compared with the range the other image spans within half a pixel of the matching position (the halfway points to its four neighbours), and the smaller of the two directions counts, so content that moved by a fraction of a pixel costs what it would at whole-pixel motion. Displacements of a pixel or more still cost in full. Infinite where fewer than 12 points fall inside both frames, as in the plain cost.
screen_fixed_split_error
The cost of the points at offset and its runner-up (the lowest cost more than two pixels away, within radius), when the region may hold a screen-fixed part: each point costs the smaller of its plain error at zero (refine_native_at’s per-point cost) and its sampling-insensitive error at the offset (sampling_insensitive_error’s per-point cost). A point that stayed where it was on screen (a search bar or status bar floating over a map, a sticky panel) then does not count against the offset the rest moved by, and the rest may have moved by a fraction of a pixel, as a decelerating fling does. A frame that did not move matches at zero everywhere, so every offset then costs about the same as the runner-up. Infinite where fewer than 12 points fall inside both frames, as in the plain cost. The third value is the share of the points the offset explains better than zero, among those one of the two explains better: the part that moved, against the part that stayed.
select_native_points
Picks the native-refinement sample points for b inside region: a step×step cell grid, keeping one point per cell rather than sampling only the pixel at the cell’s corner (its lattice node). A node-only sampler finds an edge with probability proportional to local edge density, so a sparse page (few edges anywhere) starves the sample (< 12 points → Infinity, the true step read as “static”) and a screen-fixed line that happens to align with a lattice row or column dominates it (every node on that row is an edge, nothing else is) — see docs/ARCHITECTURE.md §五/§十. Depends only on b, region, mask and guide, not on any hypothesis, so a caller evaluating several candidate displacements can select once and reuse the points for all of them.
translation_hypotheses
Candidate translations (current → previous) from binned match displacements, strongest first.
verify_translation
Retained-75% mean of 48px block errors: ordinary page content must agree, not a single logo.