match_phase_3d — 3D match_pose op

• Data kinds: voxel × voxel → shift

• Call: import fullseye as fs; fs.ledger.match_phase_3d(a, b, device='cpu', window='tukey', whitening=0.25) (implementation को सीधे call करना हो तो import match3d; match3d.match_phase_3d(a, b, device='cpu', window='tukey', whitening=0.25), registry से लेना हो तो ops3d.get("match_phase_3d"))

• GPU: इस op का GPU path है (device="cuda")

उपयोग

3D phase correlation (FFT)। b को a से align करने वाला integer shift (dz,dy,dx) लौटाता है।

Reddy & Chatterji का 3D रूप। cross-power spectrum R = A·conj(B) को |R|^whitening से भाग देकर inverse FFT करने पर मिला peak = translation। template की ज़रूरत नहीं, पूरा volume, O(N log N)। rotation/scale अलग से संभाले जाते हैं (PCA / log-polar)।

Arguments: a, b समान shape के 3-D array हैं (अलग हों तो ValueError)। FFT के लिए इन्हें float32 में बदला जाता है। window: "tukey" (default, α 0.5), "hann", None (window नहीं) —— window mean घटाने के बाद लगाई जाती है, और 8 से छोटी लंबाई वाले axis पर नहीं लगती। whitening: |R| का exponent (0 से 1, 1 = classic phase correlation का पूरा whitening, 0 = सामान्य cross-correlation, default 0.25)। Return value: int का tuple (dz, dy, dx), हर axis (−N/2, N/2] में wrap किया हुआ। अर्थ:

np.roll(b, (dz,dy,dx), axis=(0,1,2)) ≈ a (b को इतना खिसकाने पर वह a पर बैठ जाता है)।

★default बदलने का कारण (2026-10-06, filters_freq.phase_correlation_fft जैसा ही जाल): 0.4.0 तक का "window नहीं + पूरा whitening (eps 1e-9)", band-limited volume के non-periodic crop पर (सामान्य उपयोग: 2 acquisition जो केवल आंशिक रूप से overlap करते हैं), बिना signal वाले frequency bin (crop के किनारे की discontinuity से leakage और rounding) को whitening से signal वाले bin जितना ही weight देता था, और सही shift नहीं लौटाता था —— low-pass किए गए 32³ crop पर 10 shift में 0 / 10, 64³ पर भी 0 / 10। np.roll के periodic shift पर यह exact है, इसलिए केवल उन्हीं वाला gate इसे नहीं देख पाया। 3 आयाम में, 2 आयाम (default Hann + 0.5) की तुलना में window overlap को ज़्यादा काटती है और whitening noise bin को आसानी से ऊपर उठाता है: मापे गए hit (10 shift × 3 seed) में, 32³, shift ±6 वाले low-pass crop पर Hann + 0.5 को 11 / 30, Hann + 0.25 को 19 / 30, Tukey + 0.25 को 28 / 30; periodic shift पर क्रमशः 9 / 30, 18 / 30, 27 / 30 (पुराना 30 / 30)। 64³ और (1, 256, 256) पर तीनों (3) सब hit करते हैं (पुराना low-pass crop पर 0)। इससे भी नीचे के band (cutoff 0.10) पर 32³ सभी के लिए 6 / 10 या कम रहता है; यहाँ यह कठिन ही बना रहता है। इसलिए default Tukey (α 0.5) + 0.25 है। पुराना व्यवहार window=None, whitening=1.0 है (numeric path भी वही)।

• circular correlation है, इसलिए बाहर निकला हिस्सा उलटी तरफ़ से घूमकर आता है। shift volume के आधे से ज़्यादा हो तो sign उलटा दिखता है। window वाले default में छोटे volume (32³) पर बड़े periodic shift (किनारे का 2/10) में चूक हो सकती है (ऊपर का 27 / 30) —— यदि पता हो कि shift periodic है, तो window=None, whitening=1.0 लें।

• पूरी तरह 0 वाला volume 0 देता है और index 0 लौटाता है।

• integer precision। sub-voxel के लिए refine_translation_lk / refine_peak_newton का उपयोग करें।

• rotation या scale मौजूद हो तो काम नहीं करता (क्रम: match_logpolar_z → rotation correction → यह op)।

Raises ValueError: shape अलग, window की spelling गलत, whitening [0, 1] से बाहर, torch के बिना वाले environment में device cpu के अलावा।

संदर्भ (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 के स्रोत।

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

• shape_desc_pose — py -3.11 examples_3d/shape_desc_pose.py

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

fuse_to_voxel

इसी category के (match_pose)

match_pca · moment_axes · match_logpolar_z


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

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