new_nbv_rec/core/evaluation.py
2025-05-13 09:03:38 +08:00

109 lines
5.5 KiB
Python

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)