photometric op• Data kinds: images → normalmap
• Call: import fullseye as fs; fs.ledger.photometric_stereo(images, lights, mask=None, normalize=True, *, lit_only=False, lit_thresh=0.001) (implementation को सीधे call करना हो तो import photometric; photometric.photometric_stereo(images, lights, mask=None, normalize=True, *, lit_only=False, lit_thresh=0.001), registry से लेना हो तो ops3d.get("photometric_stereo"))
• Ledger के ज़रिए return value: fullseye.ledger.photometric_stereo(...) केवल घोषित out type normalmap का value लौटाता है (मूल function सहायक जानकारी भी लौटाता है)। जो हिस्सा छोड़ दिया गया है उसकी ज़रूरत हो तो fullseye.ledger.photometric_stereo.raw(...) का उपयोग करें, या photometric.photometric_stereo को सीधे call करें।
Lambertian photometric stereo: ज्ञात light directions वाली N images से normal और albedo वापस निकालता है। → (normals HxWx3, albedo HxW)।
I_n = albedo * max(N·L_n, 0)। हर pixel पर g = albedo*N को least squares g = pinv(L) @ I से हल किया जाता है, albedo=|g|, normal=g/|g|। N>=3 ज़रूरी है। albedo~0 वाले या mask के बाहर के pixels के लिए normal=(0,0,1)। normalize=True होने पर light vectors को unit direction में normalise किया जाता है (render_lambertian जैसा ही नियम = albedo का absolute मान सही आता है)। intensity-weighted light sources इस्तेमाल करने हों तो normalize=False रखें, और synthesis की तरफ़ भी raw vectors ही इस्तेमाल करें।
lit_only (2026-09-04 को जोड़ा गया): attached shadow को हटाकर हल करता है। model का max(·, 0) non-linear है, इसलिए N·L < 0 वाले observations (true value 0) को सीधे linear least squares में डालने से हल biased हो जाता है ―― मापा गया: बिना shadow और बिना AO वाले sphere पर median 9°, और सिर्फ़ जलती light sources से हल करने पर 0.000°। default False है (पहले का व्यवहार नहीं बदलता)। True करने पर हर pixel को सिर्फ़ I > lit_thresh वाली light sources से फिर से हल किया जाता है। एक ही lighting pattern वाले pixels को एक साथ समूहित करके 1 pseudo-inverse से process किया जाता है, इसलिए अतिरिक्त लागत लगभग light sources की संख्या से बनने वाले patterns की संख्या के अनुपात में ही बढ़ती है (6 lights पर अधिकतम 64 groups)। जिन pixels पर 3 से कम lights जलती हैं वे सभी lights वाले हल पर लौट जाते हैं (fail-open:
हल न हो सकने वाले pixels को NaN करने के बजाय, biased होते हुए भी कोई value होना downstream integration को कम तोड़ता है)।
lit_thresh: "जलती हुई" मानी जाने वाली luminance की निचली सीमा। इसे imaging noise से ऊपर रखें।
• 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 के स्रोत।
• photometric_stereo — py -3.11 examples_3d/photometric_stereo.py
normalmap को input के रूप में लेते हैं)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 operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.