in run_nerf_helpers.py [0:0]
def visualize_disparity_with_blinn_phong(depth_map):
# follows https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model
lightPos = np.array([1.0, 1.0, 1.0])
lightColor = np.array([1.0, 1.0, 1.0])
lightPower = 2.0 # 40.0
ambientColor = np.array([0.1, 0.0, 0.0])
diffuseColor = np.array([0.5, 0.0, 0.0])
specColor = np.array([1.0, 1.0, 1.0])
shininess = 2.0 # 16.0
height, width = depth_map.shape
# normals from depth map
# https://stackoverflow.com/questions/53350391/surface-normal-calculation-from-depth-map-in-python
spacing = 2.0 / (height - 1)
zy, zx = np.gradient(depth_map, spacing)
normal = np.dstack(
(-zx, zy, np.ones_like(depth_map))
) # need to flip zy because OpenGL indexes bottom left as (0,0) (this is a guess, it simply turns out to work if zy is flipped)
normal_length = np.linalg.norm(normal, axis=2, keepdims=True)
normal /= normal_length # height x width x 3
i, j = np.meshgrid(
np.arange(width, dtype=np.float32) / width,
np.arange(height, dtype=np.float32) / width,
indexing="xy",
) # note: if height != width then dividing the second argument by height would lead to anisotropic scaling
vertPos = np.stack(
[i, j, depth_map], axis=-1
) # height x width x 3. note that (x,y) and (depth) have different scaling factors and offsets because we don't do proper unprojection - might need to adjust them
lightDir = -vertPos + lightPos.reshape(1, 1, 3) # height x width x 3
distance = np.linalg.norm(lightDir, axis=2, keepdims=True) # height x width x 1
lightDir /= distance
# distance = distance ** 2
distance = (distance + 1.0) ** 2
def dot_product(A, B):
return np.sum(A * B, axis=-1)
lightDir_x_normal = dot_product(lightDir, normal)
lambertian = np.clip(lightDir_x_normal, a_max=None, a_min=0.0).reshape(
height, width, 1
) # height x width x 1
invalid_mask = lambertian <= 0.0
def normalize(image):
return image / np.linalg.norm(image, axis=-1, keepdims=True)
viewDir = normalize(-vertPos) # height x width x 3
halfDir = normalize(lightDir + viewDir) # height x width x 3
# specAngle = np.clip(dot_product(halfDir, normal), a_max=None, a_min=0.).reshape(height, width, 1) # height x width x 1
specAngle = np.clip(dot_product(halfDir, -normal), a_max=None, a_min=0.0).reshape(
height, width, 1
) # height x width x 1
specular = specAngle ** shininess
specular[invalid_mask] = 0.0
colorLinear = (
lambertian
* diffuseColor.reshape(1, 1, 3)
* lightColor.reshape(1, 1, 3)
* lightPower
/ distance
+ specular
* specColor.reshape(1, 1, 3)
* lightColor.reshape(1, 1, 3)
* lightPower
/ distance
+ ambientColor.reshape(1, 1, 3)
) # height x width x 3
return colorLinear