crt_displacement — RESIDUE image op

• Data kinds: image2d × image2d → table

• Call: import fullseye as fs; fs.ledger.crt_displacement(image0, image1, periods=(5.0, 7.0, 9.0, 11.0, 13.0, 16.0), sigma_px=40.0, max_disp=40.0, axis='x', refine=2) -> 'dict' (implementation को सीधे call करना हो तो import residue; residue.crt_displacement(image0, image1, periods=(5.0, 7.0, 9.0, 11.0, 13.0, 16.0), sigma_px=40.0, max_disp=40.0, axis='x', refine=2) -> 'dict', registry से लेना हो तो opsresidue.get("crt_displacement"))

उपयोग

कई wavelengths पर band phases से local displacement, CRT से unwrap किया हुआ -> dict।

> नीचे का विस्तृत विवरण मूल text में है — सारांश और headings का अनुवाद हो चुका है।

A band of wavelength p measures the local shift only modulo p, so any single-band phase method breaks at |d| = p/2 (motionmag.phase_displacement reports this as wrap_limit_px). Bands at *coprime* wavelengths each break there too, but together they fix d over the least common multiple — 693 px for 7/9/11 — so the limit becomes max_disp, the search half-width.

image1 is image0 with its content moved by d(y, x) along axis ("x" = columns, "y" = rows; positive towards increasing index) — image1 = np.roll(image0, +d) gives +d. Note that filters_freq.phase_correlation_fft(image0, image1) uses the *opposite* sign (it returns -d); flip one when swapping methods. For each wavelength a Gaussian band-pass (analytic, one-sided, spatial std sigma_px) gives a local phase and a *local* wavelength (measured, not nominal — see _band_measure); their phase differences are residues of d; amplitude products are the weights; every pixel is solved by the phasor-agreement search

of residue_crt. refine iterations then warp image1 back by the current estimate and add the (now small, wrap-free) weighted residual.

Returns {"d", "weight", "margin", "residual", "valid", "wrap_limit_single_px"}. valid = enough contrast in the bands *and* a margin above 0.05; a pixel that fails is still returned but should not be trusted.

Where it applies: textured regions that each move (nearly) rigidly by a large amount — measured on two regions of the public scikit-image textures moving +20 / -15 px, pixels farther than 1.5 sigma_px from the region boundary are off by more than 1 px on 2 % (grass) / 5 % (gravel) / 6 % (brick), where the best pyramid Lucas-Kanade (3-6 levels) is off on 49 / 50 / 67 %.

Where it does not: within ~1.5 sigma_px of a motion boundary; where the displacement changes inside the window (a 6 px field with gradient 0.07 is already off on half the pixels — a band narrow enough to keep the local frequency stable needs a window too wide to follow the field); flat regions (weight and valid say where); occlusions. A single global translation is better served by phase correlation. Numbers: examples/poc_residue_crt.py.

संदर्भ (sample data, साहित्य)

• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।

• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।

• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• poc_residue_crt — py -3.11 examples/poc_residue_crt.py

वे अगले ops जिनसे type जुड़ता है (table को input के रूप में लेते हैं)

—

इसी category के (image)

harmonic_rotation


*Provenance: residue.py — RESIDUE operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.