in lib/model/HGPIFuMRNet.py [0:0]
def calc_normal(self, points, calib_local, calib_global, transforms=None, labels=None, delta=0.001, fd_type='forward'):
'''
return surface normal in 'model' space.
it computes normal only in the last stack.
note that the current implementation use forward difference.
args:
points: [B1, B2, 3, N] 3d points in world space
calibs_local: [B1, B2, 4, 4] calibration matrices for each image
calibs_global: [B1, 4, 4] calibration matrices for each image
transforms: [B1, 2, 3] image space coordinate transforms
labels: [B1, B2, 3, N] ground truth normal
delta: perturbation for finite difference
fd_type: finite difference type (forward/backward/central)
'''
B = calib_local.size(1)
if labels is not None:
self.labels_nml = labels.view(-1,*labels.size()[2:])
im_feat = self.im_feat_list[-1].view(-1,B,*self.im_feat_list[-1].size()[1:])
nmls = []
for i in range(B):
points_sub = points[:,i]
pdx = points_sub.clone()
pdx[:,0,:] += delta
pdy = points_sub.clone()
pdy[:,1,:] += delta
pdz = points_sub.clone()
pdz[:,2,:] += delta
points_all = torch.stack([points_sub, pdx, pdy, pdz], 3)
points_all = points_all.view(*points_sub.size()[:2],-1)
xyz = self.projection(points_all, calib_local[:,i], transforms)
xy = xyz[:, :2, :]
self.netG.query(points=points_all, calibs=calib_global, update_pred=False)
z_feat = self.netG.phi
if not self.opt.train_full_pifu:
z_feat = z_feat.detach()
point_local_feat_list = [self.index(im_feat[:,i], xy), z_feat]
point_local_feat = torch.cat(point_local_feat_list, 1)
pred = self.mlp(point_local_feat)[0]
pred = pred.view(*pred.size()[:2],-1,4) # (B, 1, N, 4)
# divide by delta is omitted since it's normalized anyway
dfdx = pred[:,:,:,1] - pred[:,:,:,0]
dfdy = pred[:,:,:,2] - pred[:,:,:,0]
dfdz = pred[:,:,:,3] - pred[:,:,:,0]
nml = -torch.cat([dfdx,dfdy,dfdz], 1)
nml = F.normalize(nml, dim=1, eps=1e-8)
nmls.append(nml)
self.nmls = torch.stack(nmls,1).view(-1,3,points.size(3))