Implementation of original NeRF seems like it is different with rendering implementation from nerf-w https://github.com/kwea123/nerf_pl/blob/nerfw/models/rendering.py Inputs: raw: torch.Tensor() [N_rays, N_samples, 4]
(raw, z_vals, rays_d, raw_noise_std=0, white_bkgd=False, pytest=False)
| 65 | return samples |
| 66 | |
| 67 | def raw2outputs(raw, z_vals, rays_d, raw_noise_std=0, white_bkgd=False, pytest=False): |
| 68 | ''' |
| 69 | Implementation of original NeRF |
| 70 | seems like it is different with rendering implementation from nerf-w |
| 71 | https://github.com/kwea123/nerf_pl/blob/nerfw/models/rendering.py |
| 72 | Inputs: |
| 73 | raw: torch.Tensor() [N_rays, N_samples, 4] |
| 74 | ''' |
| 75 | |
| 76 | # Function for computing density from model prediction. This value is |
| 77 | # strictly between [0, 1]. |
| 78 | raw2alpha = lambda raw, dists, act_fn=F.relu: 1.-torch.exp(-act_fn(raw)*dists) |
| 79 | |
| 80 | # Compute 'distance' (in time) between each integration time along a ray. |
| 81 | dists = z_vals[...,1:] - z_vals[...,:-1] |
| 82 | |
| 83 | # The 'distance' from the last integration time is infinity. |
| 84 | dists = torch.cat([dists, torch.Tensor([1e10]).expand(dists[...,:1].shape)], -1) # [N_rays, N_samples] the last delta is infinity (1e10) |
| 85 | |
| 86 | # Multiply each distance by the norm of its corresponding direction ray |
| 87 | # to convert to real world distance (accounts for non-unit directions). |
| 88 | dists = dists * torch.norm(rays_d[...,None,:], dim=-1) # why raw2outputs_NeRFW doesn't have this step? |
| 89 | |
| 90 | # Extract RGB of each sample position along each ray. (NeRFW sigmoided in network) |
| 91 | rgb = torch.sigmoid(raw[...,:3]) # [N_rays, N_samples, 3] |
| 92 | |
| 93 | # Add noise to model's predictions for density. Can be used to |
| 94 | # regularize network during training (prevents floater artifacts). |
| 95 | noise = 0. |
| 96 | if raw_noise_std > 0.: |
| 97 | noise = torch.randn(raw[...,3].shape) * raw_noise_std |
| 98 | |
| 99 | # Overwrite randomly sampled data if pytest |
| 100 | if pytest: |
| 101 | np.random.seed(0) |
| 102 | noise = np.random.rand(*list(raw[...,3].shape)) * raw_noise_std |
| 103 | noise = torch.Tensor(noise) |
| 104 | |
| 105 | # Predict density of each sample along each ray. Higher values imply |
| 106 | # higher likelihood of being absorbed at this point. |
| 107 | alpha = raw2alpha(raw[...,3] + noise, dists) # [N_rays, N_samples] |
| 108 | |
| 109 | # Compute weight for RGB of each sample along each ray. A cumprod() is |
| 110 | # used to express the idea of the ray not having reflected up to this |
| 111 | # sample yet. |
| 112 | # weights = alpha * tf.math.cumprod(1.-alpha + 1e-10, -1, exclusive=True) |
| 113 | weights = alpha * torch.cumprod(torch.cat([torch.ones((alpha.shape[0], 1)), 1.-alpha + 1e-10], -1), -1)[:, :-1] |
| 114 | |
| 115 | # Computed weighted color of each sample along each ray. |
| 116 | rgb_map = torch.sum(weights[...,None] * rgb, -2) # [N_rays, 3] |
| 117 | |
| 118 | # Estimated depth map is expected distance. |
| 119 | depth_map = torch.sum(weights * z_vals, -1) |
| 120 | |
| 121 | # Disparity map is inverse depth. |
| 122 | disp_map = 1./torch.max(1e-10 * torch.ones_like(depth_map), depth_map / torch.sum(weights, -1)) |
| 123 | |
| 124 | # Sum of weights along each ray. This value is in [0, 1] up to numerical error. |
nothing calls this directly
no outgoing calls
no test coverage detected