Recover surface albedo given known surface normal and light observation.
From the Lambertian equation:
I=ρ⋅(n⋅l)
where:
I is the observed intensity
ρ is the surface albedo (reflectance)
n is the unit surface normal vector
l is the unit light direction vector
We can solve for albedo:
ρ=n⋅lI
This is only valid when n⋅l>0 (the surface faces the light). For backlit surfaces where the dot product is zero or negative, albedo cannot be recovered from that observation.
In practice, we average albedo estimates from multiple light sources for robustness.
Example
Input
recover_albedo(0.4, [0, 0, 1], [0, 0, 1])
Output
0.4
Reasoning
Normal parallel to light:
dot(n, l) = 1.0
albedo = 0.4 / 1.0 = 0.4
When n·l = 1, intensity equals albedo.
Constraints
intensity: observed intensity
normal: surface normal [nx, ny, nz]
light_dir: light direction [lx, ly, lz]
Return albedo rounded to 4 decimal places, or 0 if dot product ≤ 0
Photometric stereo uses shading variation under known lights to recover both surface normals and albedo (intrinsic reflectance) of a surface. In the Lambertian model, each pixel’s intensity is modeled as the product of albedo and the cosine of the angle between the light direction and the surface normal. This separates geometry (normals) from material (albedo): the normal controls how much light a point receives; the albedo scales how much it reflects.
For a single light, the Lambertian equation is
I=ρ(n⋅l)
where I is the observed intensity, ρ the scalar albedo, n a unit normal, and l a unit light direction. If n and l are known and the surface is front-lit (n⋅\mathbf{l}>0), this becomes a simple scalar equation in ρ. With multiple light sources, you get several independent measurements of the same ρ, which allows you to reduce noise by averaging or doing a least-squares fit.
2. Algorithm / Approach
General pattern for recovering albedo from known normal(s) and intensities:
Use the Lambertian model to express each observation as:
Ik=ρ(n⋅lk)
For each valid light (front-lit), solve for an estimate of ρ:
ρk=n⋅lkIk
Combine multiple estimates {ρk} into a single robust albedo, typically by:
simple average, or
weighted average (e.g., weights based on n⋅\mathbf{l}k or confidence).
Backlit or grazing-angle observations (dot product ≤0 or very small) are discarded since they provide unreliable or undefined albedo estimates.
3. Step-by-Step Strategy
Assume for each pixel you are given:
observed intensities: I[k] for lights k = 0 … K-1
unit surface normal: n (3D vector)
unit light directions: L[k] (3D vectors)
Per pixel:
Initialize
sum_rho = 0
count = 0 (or sum_weight = 0 if using weighted averaging)
Loop over lights
Compute dot product: d = dot(n, L[k])
If d <= 0:
skip this light (backlit or edge-on).
Else:
Compute per-light albedo estimate: rho_k = I[k] / d
Option A (simple average):
sum_rho += rho_k
count += 1
Option B (weighted average, e.g. weight = d):
w = d
sum_rho += w * rho_k
sum_weight += w
PRO
Continue the full explanation
You're reading the free preview. Unlock the complete walkthrough, the code editor, test runner and reference solution with Premium.
PRO
Editor locked
The code editor is locked for Pro problems. It is only available for free problems. Please upgrade to gain access to the code editor for all problems.