light_section op• Data kinds: image2d → table
• Call: import fullseye as fs; fs.ledger.laser_line_center_centroid(image, min_peak_rel=0.1, half_window=None, background=0.0, clip_negative=True) (implementation को सीधे call करना हो तो import lightsection; lightsection.laser_line_center_centroid(image, min_peak_rel=0.1, half_window=None, background=0.0, clip_negative=True), registry से लेना हो तो opsoptics.get("laser_line_center_centroid"))
• GPU: नहीं (केवल CPU reference implementation)
हर column में चमकीली laser line का केंद्र intensity centroid से sub-pixel में (table)।
> नीचे का विस्तृत विवरण मूल text में है — सारांश और headings का अनुवाद हो चुका है।
列ごとに最大の行 p を探し、[p − half_window, p + half_window](None = 列全体)の輝度から background を引いて負を 0 にした重みの重心を返す。最大値が画像全体の最大の min_peak_rel 倍以下の列は valid=False(row は NaN)。
For each column the peak row p is found, and the centroid of max(I − background, 0) over [p − half_window, p + half_window] (None = the whole column) is returned. Columns whose peak is at most min_peak_rel × the image maximum are marked valid=False (row NaN). clip_negative=False keeps negative weights (zero-mean noise stays zero-mean: the estimator is then linear in the noise, which is what light_section_uncertainty_budget's read-noise term assumes). Pixel-centre convention of camera: row r is the coordinate v = r exactly.
Returns {"kind": "laser_line_centers", "method": "centroid", "col", "row", "valid", "peak", "n_valid", "saturated", "truncated"}. Ground truth: a symmetric line profile has its centroid at the true centre; the centroid of a column-binned image equals that of the unbinned one (tests/test_lightsection.py). ★Limits: the centroid is biased toward the window's centre when the window cuts an off-centre profile, and a background left in the weights pulls it toward the column's middle.
★Saturation: the "peak" is the plateau of rows within 1e-9 of the column maximum that is connected to the first maximum; the window is [lo − half_window, hi + half_window] around that plateau (one row for an unclipped line: the same as before). A clipped, flat-topped line used to be windowed at the plateau's first row (−6.7 px at 20× over full scale, still valid). saturated marks the columns whose plateau has ≥ 3 rows, or ≥ 2 rows at the image's maximum (the ceiling); only those columns get the plateau window, every other column is windowed at its first maximum exactly as before (bit for bit). Two equal rows below the ceiling are common in quantised, unclipped lines (uint8, σ 3 px: 6 % of the columns at a peak of 200, 15 % at 60) and are not a plateau. The result in a saturated column is a centroid of clipped data, so treat it as degraded. ★Not detected: a plateau broken by a dip (dark-frame or flat-field correction after clipping leaves 1 LSB dips) — the plateau ends at the dip and the window shifts toward it again (measured 3.5 px, gauss 3.2 px, valid; 5.6 px before the plateau window); pass uncorrected data or clip it back to the ceiling first. truncated marks the columns whose weight at either end of the window (or of the image) is still ≥ max(min_peak_rel, 1e-3) × the column's peak weight — the profile was cut, so the centroid is pulled toward the window's middle (measured: σ 2 px, true 0.4 → 1.48). valid is not changed by either flag.
optics के सभी ops गणना से पहले input की जाँच करते हैं (कुछ भी चुपचाप पास नहीं होता):
• Unit argument के नाम में ही लिखी होती है — _mm / _um / _deg / _mrad। mm और µm की गड़बड़ी crash नहीं करती, बल्कि "सही दिखने वाला पर गलत उत्तर" देती है, इसलिए नाम से इसे रोका जाता है। मान के आकार से unit का अनुमान बिल्कुल नहीं लगाया जाता।
• String से ValueError — float('50') सफल हो जाता है, इसलिए बिना parse किया config value length के रूप में निकल जाता (मापा गया: thin_lens('50', '200') सही दिखने वाला 66.667 mm लौटा रहा था)। bool को भी True == 1 वाले implicit promotion के रूप में अस्वीकार किया जाता है।
• complex / masked array से ValueError (केवल real-valued slots; imaginary part को चुपचाप छोड़ना या mask हटाना अस्वीकार)। हर input पर NaN/Inf से ValueError। घोषित अपवाद: bottle_fit_from_pattern का u_map न मापे जा सके पिक्सेल को NaN के रूप में लेता है (अनंत अब भी अस्वीकार)।
• शून्य से भाग और उससे जुड़े मामलों को नाम लेकर अस्वीकार किया जाता है: focal length 0, radius of curvature 0, refractive index <= 0, पूरी तरह opaque aperture (सब 0, इसलिए normalisation 0/0), ऐसा PSF जिसका योग <= 0 हो, S0 = 0 वाला Stokes vector, और front focal point पर रखा object (image अनंत पर)।
• केवल 2 ops non-finite value लौटाते हैं, और वह भी contract के रूप में लिखा हुआ: depth_of_field hyperfocal distance से आगे far_mm = inf (hyperfocal distance की परिभाषा यही है) और gaussian_beam waist पर wavefront_radius_mm = inf (plane wavefront की radius of curvature)। दोनों साथ में एक finite साथी (far_is_infinite / curvature_per_mm) भी लौटाते हैं। इसके अलावा कोई भी चुपचाप आया NaN/Inf अंदर ही पकड़ा जाता है और ValueError देता है — "float64 overflow हुआ" और "उत्तर अनंत है" अलग-अलग दावे हैं, इसलिए पहले को दूसरे का चेहरा पहनाकर नहीं लौटाया जाता। घोषित अपवाद: bottle_background_map जिन पिक्सेल की किरण अनुपयोगी है (पूर्ण आंतरिक परावर्तन आदि) उनके लिए u_mm में NaN लौटाता है, साथ में valid मास्क और गिनती भी।
• Size की सीमा: generate होने वाले grid के लिए optics.MAX_GRID (4096), दिए गए field/PSF/aperture के लिए optics.MAX_FIELD_ELEMENTS (2^24), ABCD element chain के लिए optics.MAX_SYSTEM_ELEMENTS (1024), Zernike के लिए MAX_ZERNIKE_TERMS (512) / MAX_ZERNIKE_ORDER (40) / MAX_ZERNIKE_BASIS (2^25)। छोटे argument से बहुत बड़ा internal allocation होने वाले रास्तों (मापा गया: n_max=40 × 4096² पर 108 GB) को fail-closed ढंग से बंद किया गया है।
• भौतिक रूप से असंभव states भी अस्वीकार: degree of polarisation > 1 वाला Stokes vector, ऋणात्मक transmittance, ऋणात्मक intensity, और n-|m| odd जैसे अमान्य Zernike indices।
• 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 में दिए गए हैं।
• poc_3d_sensor_modalities — py -3.11 examples/poc_3d_sensor_modalities.py
• poc_weld_bead_profile — py -3.11 examples/poc_weld_bead_profile.py
table को input के रूप में लेते हैं)abcd_matrix · wavefront_stats · sfr_from_edge · paraxial_trace · seidel_coefficients · spot_stats · tolerance_analysis · wavefront_from_opd
light_section)laser_line_center_gauss · laser_line_center_steger · light_section_rig · light_section_targets · light_section_render · light_plane_calibrate · light_section_profile · light_section_scan
*Provenance: lightsection.py — OPTICS operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.