light_section op• 数据种类:image2d → table
• 调用: 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)(要直接调用实现,import lightsection; lightsection.laser_line_center_centroid(image, min_peak_rel=0.1, half_window=None, background=0.0, clip_negative=True);从台账取用则 opsoptics.get("laser_line_center_centroid"))
• GPU:无(仅 CPU 参考实现)
按列用亮度重心以亚像素精度求明亮激光条纹的中心(table)。
> 以下的详细说明为原文 —— 摘要与标题已翻译。
列ごとに最大の行 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 的每个算子都先校验输入再计算(不让任何东西无声通过):
• 单位写进参数名 —— _mm / _um / _deg / _mrad。把 mm 和 µm 弄混不会崩溃,而是给出「看着合理却是错的答案」,所以用命名来防。这里绝不从数值大小去猜单位。
• 字符串一律 ValueError —— float('50') 会成功,于是未解析的配置值会被当成长度混进来(实测:thin_lens('50', '200') 曾返回看着合理的 66.667 mm)。bool 也按 True == 1 的隐式提升拒绝。
• complex / masked array 一律 ValueError(仅接受实数槽位;拒绝无声丢弃虚部或剥掉掩码)。所有输入中的 NaN/Inf 一律 ValueError。但已声明的缺测除外:bottle_fit_from_pattern 的 u_map 以 NaN 接收未能测得的像素(∞ 仍被拒绝)。
• 逐项点名拒绝除零及其近亲:焦距 0、曲率半径 0、折射率 <= 0、全不透明光阑(全为 0,归一化变成 0/0)、总和 <= 0 的 PSF、S0 = 0 的 Stokes 矢量、物体位于前焦点(像在无穷远)。
• 只有两个算子会返回非有限值,而且都写进了契约:depth_of_field 在超焦距以外返回 far_mm = inf(这正是超焦距的定义),gaussian_beam 在束腰处返回 wavefront_radius_mm = inf(平面波前的曲率半径)。两者都同时返回一个有限的搭档(far_is_infinite / curvature_per_mm)。除此之外的无声 NaN/Inf 都在内部检出并 ValueError ——「float64 溢出了」和「答案是无穷大」是两种不同的主张,不能拿后者的脸去交付前者。但已声明的缺测除外:bottle_background_map 对光线不可用的像素(全反射等)在 u_mm 中返回 NaN,并同时返回 valid 掩码和数量。
• 尺寸上限:生成网格受 optics.MAX_GRID(4096)限制,传入的场/PSF/光阑受 optics.MAX_FIELD_ELEMENTS(2^24),ABCD 元件序列受 optics.MAX_SYSTEM_ELEMENTS(1024),Zernike 受 MAX_ZERNIKE_TERMS(512)/ MAX_ZERNIKE_ORDER(40)/ MAX_ZERNIKE_BASIS(2^25)。以 fail-closed 堵住「小参数引发巨大内部分配」的路径(实测:n_max=40 × 4096² 需要 108 GB)。
• 物理上不可能的状态同样拒绝:偏振度 > 1 的 Stokes 矢量、负透过率、负强度、n-|m| 为奇数等非法 Zernike 指标。
• 示例数据目录(下载 URL / 许可证) —— 2-D 用 skimage.data(BSD/公有领域)加合成图,3-D 给出真实数据源(Stanford/PDS 等)的下载 URL。
• 算子来历与参考文献 —— 该算子族所依据的研究/方法出处。
• 算法的正典(作者、年份)与用途见上面的族使用指南。
• 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 作为输入)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 算子登记表。本条目由 tools/opdocs.py md 自动生成(请勿手工编辑)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.