fullseye

sfp_normals — OPTICS shape_from_polarization op

使い方

From a polariser sweep to the explicit set of candidate surface normals per pixel — 2 for the diffuse model, 4 for the specular model (2 zeniths x 2 azimuths).

sweep is an (N, H, W) stack through linear analysers at angles_deg (the polsweep sort; :func:optics.polarization_demosaic gives it from a raw mosaic). Per pixel the sinusoid I(t) = a0 + a1 cos 2t + a2 sin 2t is fitted (the same least-squares fit as :func:specularity.polarization_dolp_map), giving DoLP = hypot(a1, a2)/a0 and AoLP = 0.5 atan2(a2, a1); then :func:dolp_to_zenith and :func:aolp_to_azimuth give the zenith and azimuth candidates.

A fitted minimum below zero (modulation above the mean, DoLP > 1) is impossible for light. Near Brewster’s angle the true minimum is ~0, so sensor noise pushes it slightly negative; violation_tol is the largest excess DoLP - 1 that is read as noise (DoLP clipped to 1). A larger excess marks the pixel invalid — the frames do not match angles_deg, or the pixel saw something other than a polariser sweep. Such a pixel is reported in violation, never silently clipped. (:func:specularity.polarization_dolp_map refuses the whole image instead; a shape map with one hot pixel is still a shape map, so here the decision is per pixel and :func:sfp_disambiguate refuses invalid pixels inside its mask by default.)

out_of_range: a DoLP that no zenith produces (diffuse model, above (n^2-1)/(n^2+1)) makes the pixel "invalid" (default) or is "clamp"-ed to the reachable limit and kept, flagged in clamped.

Returns a dict (a table, marked kind == "sfp_candidates"):

Nothing here chooses among the candidates; a single “best” normal map returned at this stage would be a guess dressed as a measurement.

Raises ValueError: not an (N, H, W) stack of >= 3 finite non-negative frames; angles that do not match or do not determine the fit; violation_tol outside [0, 1]; index not > 1; unknown model / out_of_range.

ファミリ共通の入力契約(fail-closed)

optics の全 op は入力を検証してから計算する(黙って通さない):

詳しい使い方ガイド

参考(サンプルデータ・文献)

実行できる例(この op を実際に呼ぶ検証済みサンプル)

型が繋がる次の op(table を入力に取れる)

abcd_matrix · wavefront_stats · sfr_from_edge · paraxial_trace · seidel_coefficients · spot_stats · tolerance_analysis · wavefront_from_opd

同カテゴリ(shape_from_polarization)

sfp_dolp_model · dolp_to_zenith · aolp_to_azimuth · sfp_render · sfp_disambiguate · sfp_estimate_index · sfp_height


Provenance: sfpolar.py — OPTICS operator registry. この per-op ノートは tools/opdocs.py md が自動生成(手編集しない)。

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