def generate_pointnet_features()

in contactopt/hand_object.py [0:0]


    def generate_pointnet_features(self, obj_sampled_idx):
        """Calculates per-point features for pointnet. DeepContact uses these features"""
        obj_mesh = Meshes(verts=[torch.Tensor(self.obj_verts)], faces=[torch.Tensor(self.obj_faces)])
        hand_mesh = Meshes(verts=[torch.Tensor(self.hand_verts)], faces=[torch.Tensor(util.get_mano_closed_faces())])

        obj_sampled_verts_tensor = obj_mesh.verts_padded()[:, obj_sampled_idx, :]
        _, _, obj_nearest = pytorch3d.ops.knn_points(obj_sampled_verts_tensor, hand_mesh.verts_padded(), K=1, return_nn=True)  # Calculate on object
        _, _, hand_nearest = pytorch3d.ops.knn_points(hand_mesh.verts_padded(), obj_sampled_verts_tensor, K=1, return_nn=True)  # Calculate on hand

        obj_normals = obj_mesh.verts_normals_padded()
        obj_normals = torch.nn.functional.normalize(obj_normals, dim=2, eps=1e-12)    # Because buggy mistuned value in Pytorch3d, must re-normalize
        norms = torch.sum(obj_normals * obj_normals, dim=2)  # Dot product
        obj_normals[norms < 0.8] = 0.6   # TODO hacky get-around when normal finding fails completely
        self.obj_normals = obj_normals.detach().squeeze().numpy()

        obj_sampled_verts = self.obj_verts[obj_sampled_idx, :]
        obj_sampled_normals = obj_normals[0, obj_sampled_idx, :].detach().numpy()
        hand_normals = hand_mesh.verts_normals_padded()[0, :, :].detach().numpy()

        hand_centroid = np.mean(self.hand_verts, axis=0)
        obj_centroid = np.mean(self.obj_verts, axis=0)

        # Hand features
        hand_one_hot = np.ones((self.hand_verts.shape[0], 1))
        hand_vec_to_closest = hand_nearest.squeeze().numpy() - self.hand_verts
        hand_dist_to_closest = np.expand_dims(np.linalg.norm(hand_vec_to_closest, 2, 1), axis=1)
        hand_dist_along_normal = np.expand_dims(np.sum(hand_vec_to_closest * hand_normals, axis=1), axis=1)
        hand_dist_to_joint = np.expand_dims(self.hand_verts, axis=1) - np.expand_dims(self.hand_joints, axis=0)   # Expand for broadcasting
        hand_dist_to_joint = np.linalg.norm(hand_dist_to_joint, 2, 2)
        hand_dot_to_centroid = np.expand_dims(np.sum((self.hand_verts - obj_centroid) * hand_normals, axis=1), axis=1)

        # Object features
        obj_one_hot = np.zeros((obj_sampled_verts.shape[0], 1))
        obj_vec_to_closest = obj_nearest.squeeze().numpy() - obj_sampled_verts
        obj_dist_to_closest = np.expand_dims(np.linalg.norm(obj_vec_to_closest, 2, 1), axis=1)
        obj_dist_along_normal = np.expand_dims(np.sum(obj_vec_to_closest * obj_sampled_normals, axis=1), axis=1)
        obj_dist_to_joint = np.expand_dims(obj_sampled_verts, axis=1) - np.expand_dims(self.hand_joints, axis=0)   # Expand for broadcasting
        obj_dist_to_joint = np.linalg.norm(obj_dist_to_joint, 2, 2)
        obj_dot_to_centroid = np.expand_dims(np.sum((obj_sampled_verts - hand_centroid) * obj_sampled_normals, axis=1), axis=1)

        # hand_feats = np.concatenate((hand_one_hot, hand_normals, hand_vec_to_closest, hand_dist_to_closest, hand_dist_along_normal, hand_dist_to_joint), axis=1)
        # obj_feats = np.concatenate((obj_one_hot, obj_sampled_normals, obj_vec_to_closest, obj_dist_to_closest, obj_dist_along_normal, obj_dist_to_joint), axis=1)
        hand_feats = np.concatenate((hand_one_hot, hand_dot_to_centroid, hand_dist_to_closest, hand_dist_along_normal, hand_dist_to_joint), axis=1)
        obj_feats = np.concatenate((obj_one_hot, obj_dot_to_centroid, obj_dist_to_closest, obj_dist_along_normal, obj_dist_to_joint), axis=1)

        return hand_feats, obj_feats