import torch import numpy as np from utils.reconstruction import ReconstructionUtil from utils.pose import PoseUtil from utils.pts import PtsUtil from utils.render import RenderUtil import PytorchBoot.stereotype as stereotype import PytorchBoot.namespace as namespace from PytorchBoot.utils.log_util import Log @stereotype.evaluation_method("pose_diff") class PoseDiff: def __init__(self, _): pass def evaluate(self, output_list, data_list): results = {namespace.TensorBoard.SCALAR: {}} rot_angle_list = [] trans_dist_list = [] for output, data in zip(output_list, data_list): gt_pose_9d = data['best_to_world_pose_9d'] pred_pose_9d = output['pred_pose_9d'] gt_rot_6d = gt_pose_9d[:, :6] gt_trans = gt_pose_9d[:, 6:] pred_rot_6d = pred_pose_9d[:, :6] pred_trans = pred_pose_9d[:, 6:] gt_rot_mat = PoseUtil.rotation_6d_to_matrix_tensor_batch(gt_rot_6d) pred_rot_mat = PoseUtil.rotation_6d_to_matrix_tensor_batch(pred_rot_6d) rotation_angles = PoseUtil.rotation_angle_distance(gt_rot_mat, pred_rot_mat) rot_angle_list.extend(list(rotation_angles)) trans_dist = torch.norm(gt_trans-pred_trans, dim=1).mean().item() trans_dist_list.append(trans_dist) results[namespace.TensorBoard.SCALAR]["rot_diff"] = float(sum(rot_angle_list) / len(rot_angle_list)) results[namespace.TensorBoard.SCALAR]["trans_diff"] = float(sum(trans_dist_list) / len(trans_dist_list)) return results @stereotype.evaluation_method("coverage_rate_increase") class ConverageRateIncrease: def __init__(self, config): self.config = config self.renderer_path = config["renderer_path"] def evaluate(self, output_list, data_list): results = {namespace.TensorBoard.SCALAR: {}} gt_coverate_increase_list = [] pred_coverate_increase_list = [] cr_diff_list = [] for output, data in zip(output_list, data_list): scanned_cr = data['scanned_coverage_rate'] gt_cr = data["best_coverage_rate"] scene_path_list = data['scene_path'] model_points_normals_list = data['model_points_normals'] scanned_view_pts_list = data['scanned_target_pts_list'] pred_pose_9ds = output['pred_pose_9d'] nO_to_nL_pose_batch = data["nO_to_nL_pose"] voxel_threshold_list = data["voxel_threshold"] filter_degree_list = data["filter_degree"] first_frame_to_world = data["first_frame_to_world"] pred_n_to_world_pose_mats = torch.eye(4, device=pred_pose_9ds.device).unsqueeze(0).repeat(pred_pose_9ds.shape[0], 1, 1) pred_n_to_world_pose_mats[:,:3,:3] = PoseUtil.rotation_6d_to_matrix_tensor_batch(pred_pose_9ds[:, :6]) pred_n_to_world_pose_mats[:,:3,3] = pred_pose_9ds[:, 6:] pred_n_to_world_pose_mats = torch.matmul(first_frame_to_world, pred_n_to_world_pose_mats) for idx in range(len(scanned_cr)): model_points_normals = model_points_normals_list[idx] scanned_view_pts = scanned_view_pts_list[idx] voxel_threshold = voxel_threshold_list[idx] model_pts = model_points_normals[:,:3] down_sampled_model_pts = PtsUtil.voxel_downsample_point_cloud(model_pts, voxel_threshold) old_scanned_cr = self.compute_coverage_rate(scanned_view_pts, None, down_sampled_model_pts, threshold=voxel_threshold) gt_coverate_increase_list.append(gt_cr[idx]-old_scanned_cr) scene_path = scene_path_list[idx] pred_pose = pred_n_to_world_pose_mats[idx] filter_degree = filter_degree_list[idx] nO_to_nL_pose = nO_to_nL_pose_batch[idx] try: new_pts, _ = RenderUtil.render_pts(pred_pose, scene_path, self.renderer_path, model_points_normals, voxel_threshold=voxel_threshold, filter_degree=filter_degree, nO_to_nL_pose=nO_to_nL_pose) pred_cr = self.compute_coverage_rate(scanned_view_pts, new_pts, down_sampled_model_pts, threshold=voxel_threshold) except Exception as e: Log.warning(f"Error in scene {scene_path}, {e}") pred_cr = old_scanned_cr pred_coverate_increase_list.append(pred_cr-old_scanned_cr) cr_diff_list.append(gt_cr[idx]-pred_cr) results[namespace.TensorBoard.SCALAR]["gt_cr_increase"] = float(sum(gt_coverate_increase_list) / len(gt_coverate_increase_list)) results[namespace.TensorBoard.SCALAR]["pred_cr_increase"] = float(sum(pred_coverate_increase_list) / len(pred_coverate_increase_list)) results[namespace.TensorBoard.SCALAR]["cr_diff"] = float(sum(cr_diff_list) / len(cr_diff_list)) return results def compute_coverage_rate(self, scanned_view_pts, new_pts, model_pts, threshold=0.005): if new_pts is not None: new_scanned_view_pts = scanned_view_pts + [new_pts] else: new_scanned_view_pts = scanned_view_pts combined_point_cloud = np.vstack(new_scanned_view_pts) down_sampled_combined_point_cloud = PtsUtil.voxel_downsample_point_cloud(combined_point_cloud,threshold) return ReconstructionUtil.compute_coverage_rate(model_pts, down_sampled_combined_point_cloud, threshold)