photometric op• 数据种类:images → normalmap
• 调用: import fullseye as fs; fs.ledger.photometric_stereo(images, lights, mask=None, normalize=True, *, lit_only=False, lit_thresh=0.001)(要直接调用实现,import photometric; photometric.photometric_stereo(images, lights, mask=None, normalize=True, *, lit_only=False, lit_thresh=0.001);从台账取用则 ops3d.get("photometric_stereo"))
• 经台账调用的返回值: fullseye.ledger.photometric_stereo(...) 只返回声明的 out 类型 normalmap 的值(底层函数还会返回辅助信息)。需要被丢弃的部分时,使用 fullseye.ledger.photometric_stereo.raw(...),或直接调用 photometric.photometric_stereo。
Lambert 光度立体:由已知光源方向的 N 张图恢复法线与反照率。→ (normals HxWx3, albedo HxW)。
I_n = albedo * max(N·L_n, 0)。在每个像素用最小二乘 g = pinv(L) @ I 求解 g = albedo*N, albedo=|g|, normal=g/|g|。需要 N>=3。albedo~0 或 mask 外的像素 normal=(0,0,1)。normalize=True 时将光源向量归一化为单位方向(与 render_lambertian 相同的约定 = 反照率绝对值能正确得出)。若使用带强度权重的光源,请设 normalize=False,合成侧也统一使用原始向量。
lit_only(2026-09-04 新增):去除附着阴影(attached shadow)后求解。模型的 max(·, 0) 是非线性的,把 N·L < 0 的观测(真值为 0)直接放进线性最小二乘会使解产生偏差 ―― 实测:在既无阴影也无 AO 的球上中位数为 9°,只用点亮的光源求解则为 0.000°。默认为 False(不改变以往行为)。设为 True 时对每个像素只用 I > lit_thresh 的光源重新求解。把点亮模式相同的像素归为一组, 用 1 次伪逆处理,因此额外开销大致只与光源数对应的模式数成正比(6 灯时最多 64 组)。点亮光源少于 3 个的像素退回全光源的解(fail-open:
与其把无法求解的像素设为 NaN,不如保留即使有偏差的值,这样下游的积分不会崩坏)。
lit_thresh:视为"点亮"的亮度下限。应设在拍摄噪声之上。
• 示例数据目录(下载 URL / 许可证) —— 2-D 用 skimage.data(BSD/公有领域)加合成图,3-D 给出真实数据源(Stanford/PDS 等)的下载 URL。
• 算子来历与参考文献 —— 该算子族所依据的研究/方法出处。
• photometric_stereo — py -3.11 examples_3d/photometric_stereo.py
normalmap 作为输入)fuse_to_voxel · render_shaded · phong_shade · matcap_shade · brdf_lommel_seeliger · brdf_hapke · bump_normals_fbm · integrate_normals
photometric)surface_normals · integrate_normals · render_lambertian
*Provenance: photometric.py — 3D 算子登记表。本条目由 tools/opdocs.py md 自动生成(请勿手工编辑)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.