structured_light op• Data kinds: image2d × image2d → image2d
• Call: import fullseye as fs; fs.ledger.absolute_phase(wrapped, coarse) -> 'np.ndarray' (implementation को सीधे call करना हो तो import fringe; fringe.absolute_phase(wrapped, coarse) -> 'np.ndarray', registry से लेना हो तो ops3d.get("absolute_phase"))
• GPU: केवल chain के भीतर (allow-list का mechanical GPU path, CuPy)। पड़ोसी stage भी allow-list में हो तभी GPU पर resident रहता है। अकेली call CPU पर चलती है
wrapped phase को, मोटे पर absolute phase estimate से "order तय" करके absolute phase बनाता है।
Φ = wrapped + 2π·round((coarse − wrapped) / 2π)
wrapped: wrapped_phase का output, (-π,π] का 2D array (उच्च precision, absolute order नहीं)।
coarse: उसी shape का 2D array। absolute लेकिन coarse phase अनुमान [rad]। आम तौर पर Gray code से decode किया गया projector
column number, phase में बदला हुआ (2π·freq·col/width)। NaN चल सकता है (output भी NaN)।
return value: absolute phase [rad] (2D float64)। invalid pixels (दोनों में से कोई NaN) NaN होते हैं।
यह क्यों ज़रूरी है (spatial unwrapping से अंतर): unwrap_phase_2d पड़ोसी pixels के सहारे 2π jumps को जोड़ता है, इसलिए (a) global offset +2πm बचा रहता है, और (b) occlusion से कटे islands के बीच order propagate नहीं हो पाता। यह op हर pixel के लिए स्वतंत्र रूप से order तय करता है, इसलिए islands में बँटे दृश्यों में भी absolute रहता है, और propagation की ज़रूरत नहीं होती। बदले में coarse की error आधे period (π) से कम होनी चाहिए।
शर्त (fail-closed): |coarse − Φ_true| < π। यह टूटे तो round पड़ोसी order चुन लेता है, और सिर्फ़ वह pixel चुपचाप 2π (= 1 fringe जितनी depth) खिसक जाता है। fringes की संख्या freq ऐसे चुनें कि Gray code की coarseness (±0.5 column) phase में बदलने पर आधे period से ज़्यादा न हो (उदाहरण: projector width 512 px, freq 24 → 1 period 21.3 px, Gray का ±0.5 px आराम से अंदर है)।
★order की ग़लती return value से पहचानी नहीं जा सकती (2026-11-09 मापा): multi-frequency temporal unwrapping (16/4/1 mm, अनुपात 4, 2 लाख pixels) में phase noise σφ = 0.10/0.20/0.30/0.40/0.60 rad पर 0/0.097/2.57/11.6/36.8 % pixels 2π order ग़लत चुनते हैं, और सब finite values के रूप में लौटते हैं। residual देखें:
Phi = absolute_phase(w, c); resid = c - Phi लें और लगभग |resid| > 0.8π वाले pixels को संदिग्ध मानकर हटा दें (ऊपर की स्थिति में यह 33–74 % ग़लतियाँ पकड़ता है; यह शर्त |coarse − Φ| < π के टूटने का संकेत है)। coarse की इकाई (radian) भी जाँची नहीं जाती —— degree देने पर 1106 rad (सही 19.35) जैसे values चुपचाप लौटते हैं। order जाँचने वाला अलग op अभी नहीं है (residual और flag लौटाने वाला op, op जोड़ने की प्रक्रिया से आएगा)।
Raises: shape mismatch, 2D न होना, या wrapped का (-π,π] से बहुत बाहर होना पर ValueError।
स्रोत (सार्वजनिक literature): Gray code और phase shifting को मिलाकर absolute phase पाने की combined विधि — Sansoni et al., *Appl. Opt.* 38(31) 1999 / Zhang, *Opt. Lasers Eng.* 48 2010 (review)। Gray code का ख़ुद का projection: Inokuchi et al., *ICPR* 1984।
• depth_sensors — Depth sensors — ranging के सिद्धांत, असली devices के आँकड़े, dropouts कैसे दिखते हैं
• 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 के स्रोत।
• structured_light_scan — py -3.11 examples_3d/structured_light_scan.py
image2d को input के रूप में लेते हैं)fuse_to_voxel · fit_poly_surface · eval_poly_surface · surface_form_error · background_flatten · polar_unwrap · fit_zernike · matcap_shade
structured_light)wrapped_phase · unwrap_phase_2d · graycode_decode · decode_fringe · fringe_ftp_phase · depth_from_focus · synthesize_fringes · triangulate_column
*Provenance: fringe.py — 3D operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.