google / nerfactor

Neural Factorization of Shape and Reflectance Under an Unknown Illumination
https://xiuming.info/projects/nerfactor/
Apache License 2.0
437 stars 56 forks source link

about spherify_poses #8

Closed bring728 closed 2 years ago

bring728 commented 3 years ago
def spherify_poses(poses):
    """poses: Nx3x5 (final column contains H, W, and focal length)."""
    rays_d = poses[:, :3, 2:3]
    rays_o = poses[:, :3, 3:4] # because pose is camera-to-world

  def p34_to_44(p):
      """p: Nx3x4."""
      return np.concatenate((
          p,
          np.tile(
              np.reshape(np.eye(4)[-1, :], (1, 1, 4)),
              (p.shape[0], 1, 1)),
      ), 1)

  def min_line_dist(rays_o, rays_d):
      a_i = np.eye(3) - rays_d * np.transpose(rays_d, [0, 2, 1])
      b_i = -a_i @ rays_o
      pt_mindist = np.squeeze(-np.linalg.inv(
          (np.transpose(a_i, [0, 2, 1]) @ a_i).mean(0)) @ (b_i).mean(0))
      return pt_mindist

pt_mindist = min_line_dist(rays_o, rays_d)
center = pt_mindist
up = (poses[:, :3, 3] - center).mean(0)
vec0 = normalize(up)
vec1 = normalize(np.cross([.1, .2, .3], vec0))
vec2 = normalize(np.cross(vec0, vec1))
pos = center
c2w = np.stack([vec1, vec2, vec0, pos], 1)
poses_reset = (
    np.linalg.inv(p34_to_44(c2w[None])) @ p34_to_44(poses[:, :3, :4]))
rad = np.sqrt(np.mean(np.sum(np.square(poses_reset[:, :3, 3]), -1)))
sc = 1. / rad
poses_reset[:, :3, 3] *= sc
rad *= sc
centroid = np.mean(poses_reset[:, :3, 3], 0)
zh = centroid[2]
radcircle = np.sqrt(rad ** 2 - zh ** 2)

new_poses = []
for th in np.linspace(0., 2. * np.pi, 120):
    camorigin = np.array([
        radcircle * np.cos(th), radcircle * np.sin(th), zh])
    up = np.array([0, 0, -1.])
    vec2 = normalize(camorigin)
    vec0 = normalize(np.cross(vec2, up))
    vec1 = normalize(np.cross(vec2, vec0))
    pos = camorigin
    p = np.stack([vec0, vec1, vec2, pos], 1)
    new_poses.append(p)
new_poses = np.stack(new_poses, 0)
new_poses = np.concatenate([
    new_poses,
    np.broadcast_to(poses[0, :3, -1:], new_poses[:, :3, -1:].shape)
], -1)
poses_reset = np.concatenate([
    poses_reset[:, :3, :4],
    np.broadcast_to(poses[0, :3, -1:], poses_reset[:, :3, -1:].shape)
], -1)
return poses_reset, new_poses

Can you explain a little bit about min_line_dist in this function? I think this problem is about "Find the point minimizing the distance from a set of N lines".

And I don't think this is an easy problem. The min_dist_line function seems to have implemented it quite simply. Could you explain a little bit?

gkouros commented 2 years ago

This code comes from the original NeRF repo, so you had better ask there. https://github.com/bmild/nerf/blob/18b8aebda6700ed659cb27a0c348b737a5f6ab60/load_llff.py#L184