shape_from_polarization op• 資料種類:table → normalmap
• 呼叫: import fullseye as fs; fs.ledger.sfp_disambiguate(candidates, prior='convex', mask=None, center=None, prior_normals=None, coarse_depth=None, brewster_tol=0.02, invalid='raise')(要直接呼叫實作,import sfpolar; sfpolar.sfp_disambiguate(candidates, prior='convex', mask=None, center=None, prior_normals=None, coarse_depth=None, brewster_tol=0.02, invalid='raise');從台帳取用則 opsoptics.get("sfp_disambiguate"))
用明確的先驗從 sfp_normals 的候選中為每個像素選 1 個法線 —— 凸性 + Brewster 脊線分割,或粗略深度/法線(normalmap)。
> 以下的詳細說明為原文 —— 摘要與標題已翻譯。
prior="convex" (an object bulging toward the camera, such as a dome, a lens or a cap): the azimuth is the candidate pointing away from *center* (default: the centroid of *mask*). For the specular model the two zenith branches are separated by the Brewster ridge — the pixels whose DoLP is within *brewster_tol* of 1: the connected region of the mask that contains *center* (minus the ridge) takes the branch below Brewster's angle, the rest of the mask the branch above. Inside the ridge band the branch is read from the radial slope of the DoLP (a convex surface tilts more toward its rim, so the DoLP rises outward below Brewster's angle and falls outward above it). If the object never reaches Brewster's angle there is no ridge and every pixel stays on the low branch, which is right for a shallow dome. If noise breaks the ridge, the outside leaks in and takes the low branch — measured in the tests, not hidden.
prior="normals" / prior="depth": per pixel, the candidate closest in angle to *prior_normals* (H, W, 3) — or to the normals of *coarse_depth* (H, W) (height toward the camera, pixel units, photometric.surface_normals). This resolves both ambiguities at once, and a coarse depth needs to be right only to within the angular distance between candidates.
Pixels outside *mask* (default candidates["valid"]) are set to (0, 0, 1) (flat background, the convention of photometric.integrate_normals). Invalid pixels inside the mask (valid is False: dark, physically impossible, or out of the model's
reach): invalid="raise" refuses (fail-closed), "exclude" drops them to the background.
Returns an (H, W, 3) float64 unit normal map (the normalmap sort).
Raises ValueError: *candidates* not an sfp_normals result; unknown *prior* / *invalid*; a prior's array missing or of the wrong shape; an empty mask; invalid pixels inside the mask with invalid="raise".
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。
• 逐項點名拒絕除零及其近親:焦距 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 溢位了」和「答案是無窮大」是兩種不同的主張,不能拿後者的臉去交付前者。
• 尺寸上限:生成網格受 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_shape_from_polarization — py -3.11 examples/poc_shape_from_polarization.py
normalmap 作為輸入)grating_rgb · thin_film_rgb · ward_anisotropic · micro_normals · blast_normals · finish_shade · oren_nayar · clearcoat_shade
shape_from_polarization)sfp_dolp_model · dolp_to_zenith · aolp_to_azimuth · sfp_render · sfp_normals · sfp_estimate_index · sfp_height
*Provenance: sfpolar.py — OPTICS 運算子登記表。本條目由 tools/opdocs.py md 自動產生(請勿手動編輯)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.