photometric_residual — SPECULAR photometric op

• Data kinds: images → image2d

• Call: import fullseye as fs; fs.ledger.photometric_residual(images, lights, normals=None, albedo=None, normalize=True) (implementation को सीधे call करना हो तो import specularity; specularity.photometric_residual(images, lights, normals=None, albedo=None, normalize=True), registry से लेना हो तो opsspecular.get("photometric_residual"))

उपयोग

हर pixel पर Lambertian model कितनी बुरी तरह विफल होता है। → (H, W) RMS residual।

> नीचे का विस्तृत विवरण मूल text में है — सारांश और headings का अनुवाद हो चुका है।

sqrt(mean_n (albedo * (n.L_n) - I_n)^2) — the root-mean-square disagreement between the linear model and the measurements, in the units of the input radiance. On a synthetic Lambertian surface with the true float64 normals and albedo supplied it measures 1.4e-16 at worst; with them omitted the floor rises to 4.5e-08, because photometric.photometric_stereo returns float32 and that is its precision, not a modelling error (supplying the *same* truth cast to float32 reproduces 4.5e-08 exactly). It is large where the assumption actually broke: 0.50 at worst on the same scene with 3 of 8 lights blocked by a cast shadow — fifteen orders of magnitude above the clean floor. All four numbers measured in tests/test_specularity.py.

This is the diagnostic that tells you *whether* you need photometric_stereo_robust before you reach for it, and it is the map an inspection routine thresholds to find glossy defects.

With *normals* and *albedo* omitted it solves them first with photometric.photometric_stereo and reports the residual of that fit — the honest self-assessment of the plain estimator. Pass them to score an estimate that came from somewhere else (a robust fit, a CAD model, a previous frame).

Note the residual uses n.L without the max(., 0) clamp, because that is the linear system the solver actually inverted; a pixel in attached shadow therefore shows a residual, which is the intended signal rather than an artefact.

Raises ValueError: *images* / *lights* problems as in photometric_stereo_robust; *normals* is not (H, W, 3) matching the images; *albedo* is not (H, W); exactly one of *normals* / *albedo* is given (the pair is meaningless apart — the model is albedo * n).

उपयोग की विस्तृत guide

• specular_photometric family guide

संदर्भ (sample data, साहित्य)

• 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 के स्रोत।

• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• specular_photometric — py -3.11 examples/specular_photometric.py

वे अगले ops जिनसे type जुड़ता है (image2d को input के रूप में लेते हैं)

polarization_render

इसी category के (photometric)

photometric_stereo_robust


*Provenance: specularity.py — SPECULAR operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

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