Skip to content

Instantly share code, notes, and snippets.

@jinja12
Created August 10, 2024 07:19
Show Gist options
  • Save jinja12/9240110c3a2066b96c46fe2c62272cdd to your computer and use it in GitHub Desktop.
Save jinja12/9240110c3a2066b96c46fe2c62272cdd to your computer and use it in GitHub Desktop.
from mast3r.model import AsymmetricMASt3R
from mast3r.fast_nn import fast_reciprocal_NNs
import mast3r.utils.path_to_dust3r
from dust3r.inference import inference
from dust3r.utils.image import load_images
import os
import numpy as np
import torch
import torchvision.transforms.functional as F
import torch.nn.functional as tnf
from matplotlib import pyplot as plt
from PIL import Image
import cv2
import roma
from scipy.spatial.transform import Rotation as R
from transforms3d.quaternions import qinverse, rotate_vector, qmult
from transforms3d.quaternions import quat2mat
from typing import List, Tuple
import re
import copy
from tqdm import tqdm
def extract_frame_number(img_path):
"""Extract frame number from image path using regex."""
match = re.search(r'frame_(\d+)\.jpg', img_path)
if match:
return match.group(1)
else:
raise ValueError("Frame number not found in image path")
def get_mask_paths(frame_number, seq_folder):
"""Construct paths for the masks based on the frame number."""
mask1_path = os.path.join(base_dir, f'/home2/swayam_421/indoor_loc/expts/dataset/upd_dataset/mapfree_subset/{seq_folder}/output_v2/seg_pix_confidences/query_pix_confidences_rframe_{frame_number}.pt')
mask2_path = os.path.join(base_dir, f'/home2/swayam_421/indoor_loc/expts/dataset/upd_dataset/mapfree_subset/{seq_folder}/output_v2/seg_pix_confidences/ref_pix_confidences_rframe_{frame_number}.pt')
# mask1 -> seq0, mask2 -> seq1 frames
return mask1_path, mask2_path
def get_2d_3d_correspondences(matches_im0, matches_im1, pointmap1, pointmap2):
pts2d = []
pts3d = []
for (x0, y0), (x1, y1) in zip(matches_im0, matches_im1):
pts2d.append([x1, y1]) # The corresponding 2D point in image 2 -> query image
pts3d.append(pointmap1[y0, x0]) # 3D point from the pointmap of image 1 -> reference image
pts2d = np.array(pts2d, dtype=np.float32)
pts3d = np.array(pts3d, dtype=np.float32)
return pts2d, pts3d
# Conversion functions
def quaternion_to_matrix(qw, qx, qy, qz):
r = R.from_quat([qx, qy, qz, qw])
rotation_matrix = r.as_matrix()
return rotation_matrix
def pose_to_matrix(qw, qx, qy, qz, tx, ty, tz):
rotation_matrix = quaternion_to_matrix(qw, qx, qy, qz)
translation_vector = np.array([tx, ty, tz])
transformation_matrix = np.eye(4)
transformation_matrix[:3, :3] = rotation_matrix
transformation_matrix[:3, 3] = translation_vector
return transformation_matrix
def compute_ground_truth_pose(pose2):
ground_truth_pose = pose_to_matrix(*pose2)
return ground_truth_pose
def pose_error_torch(R, t, Tgt, reduce=None):
"""Compute angular, scale and euclidean error of translation vector (metric). Compute angular rotation error."""
Rgt = Tgt[:, :3, :3] # [B, 3, 3]
tgt = Tgt[:, :3, 3:].transpose(1, 2) # [B, 1, 3]
scale_t = torch.linalg.norm(t, dim=-1)
scale_tgt = torch.linalg.norm(tgt, dim=-1)
cosine = (t @ tgt.transpose(1, 2)).squeeze(-1) / (scale_t * scale_tgt + 1e-9)
cosine = torch.clip(cosine, -1.0, 1.0) # handle numerical errors
t_ang_err = torch.rad2deg(torch.acos(cosine))
t_ang_err = torch.minimum(t_ang_err, 180 - t_ang_err)
t_scale_err = scale_t / scale_tgt
t_scale_err_sym = torch.maximum(scale_t / scale_tgt, scale_tgt / scale_t)
t_euclidean_err = torch.linalg.norm(t - tgt, dim=-1)
residual = R.transpose(1, 2) @ Rgt
trace = torch.diagonal(residual, dim1=-2, dim2=-1).sum(-1)
cosine = (trace - 1) / 2
cosine = torch.clip(cosine, -1., 1.) # handle numerical errors
R_err = torch.rad2deg(torch.acos(cosine))
if reduce is None:
def fn(x): return x
elif reduce == 'mean':
fn = torch.mean
elif reduce == 'median':
fn = torch.median
t_ang_err = fn(t_ang_err)
t_scale_err = fn(t_scale_err)
t_euclidean_err = fn(t_euclidean_err)
R_err = fn(R_err)
errors = {'t_err_ang': t_ang_err,
't_err_scale': t_scale_err,
't_err_scale_sym': t_scale_err_sym,
't_err_euc': t_euclidean_err,
'R_err': R_err}
return errors
def rvec_tvec_to_matrix(rvec, tvec):
rotation_matrix, _ = cv2.Rodrigues(rvec)
transformation_matrix = np.eye(4)
transformation_matrix[:3, :3] = rotation_matrix
transformation_matrix[:3, 3] = tvec.flatten()
return transformation_matrix
def convert_world2cam_to_cam2world(q, t):
"""Converts a world2cam pose to cam2world pose."""
qinv = qinverse(q)
tinv = -rotate_vector(t, qinv)
return qinv, tinv
def project(pts: np.ndarray, K: np.ndarray, img_size: List[int] or Tuple[int] = None) -> np.ndarray:
"""Projects 3D points to image plane.
Args:
- pts [N, 3/4]: points in camera coordinates (homogeneous or non-homogeneous)
- K [3, 3]: intrinsic matrix
- img_size (width, height): optional, clamp projection to image borders
Outputs:
- uv [N, 2]: coordinates of projected points
"""
assert len(pts.shape) == 2, 'incorrect number of dimensions'
assert pts.shape[1] in [3, 4], 'invalid dimension size'
assert K.shape == (3, 3), 'incorrect intrinsic shape'
uv_h = (K @ pts[:, :3].T).T
uv = uv_h[:, :2] / uv_h[:, -1:]
if img_size is not None:
uv[:, 0] = np.clip(uv[:, 0], 0, img_size[0])
uv[:, 1] = np.clip(uv[:, 1], 0, img_size[1])
return uv
def get_grid_multipleheight() -> np.ndarray:
# create grid of points
ar_grid_step = 0.3
ar_grid_num_x = 7
ar_grid_num_y = 4
ar_grid_num_z = 7
ar_grid_z_offset = 1.8
ar_grid_y_offset = 0
ar_grid_x_pos = np.arange(0, ar_grid_num_x)-(ar_grid_num_x-1)/2
ar_grid_x_pos *= ar_grid_step
ar_grid_y_pos = np.arange(0, ar_grid_num_y)-(ar_grid_num_y-1)/2
ar_grid_y_pos *= ar_grid_step
ar_grid_y_pos += ar_grid_y_offset
ar_grid_z_pos = np.arange(0, ar_grid_num_z).astype(float)
ar_grid_z_pos *= ar_grid_step
ar_grid_z_pos += ar_grid_z_offset
xx, yy, zz = np.meshgrid(ar_grid_x_pos, ar_grid_y_pos, ar_grid_z_pos)
ones = np.ones(xx.shape[0]*xx.shape[1]*xx.shape[2])
eye_coords = np.concatenate([c.reshape(-1, 1)
for c in (xx, yy, zz, ones)], axis=-1)
return eye_coords
def read_intrinsics(intrinsics_file, image_path):
with open(intrinsics_file, 'r') as f:
for line in f:
parts = line.strip().split()
if parts[0] == image_path:
fx = float(parts[1])
fy = float(parts[2])
cx = float(parts[3])
cy = float(parts[4])
K = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])
return K, parts[5], parts[6]
return None, None, None
def read_pose(pose_file, image_path):
with open(pose_file, 'r') as f:
for line in f:
parts = line.strip().split()
if parts[0] == image_path:
pose = list(map(float, parts[1:]))
return pose
return None
# global variable, avoids creating it again
eye_coords_glob = get_grid_multipleheight()
def reprojection_error(
q_est: np.ndarray, t_est: np.ndarray, q_gt: np.ndarray, t_gt: np.ndarray, K: np.ndarray,
W: int, H: int) -> float:
eye_coords = eye_coords_glob
# obtain ground-truth position of projected points
uv_gt = project(eye_coords, K, (W, H))
# residual transformation
cam2w_est = np.eye(4)
cam2w_est[:3, :3] = quat2mat(q_est)
cam2w_est[:3, -1] = t_est
cam2w_gt = np.eye(4)
cam2w_gt[:3, :3] = quat2mat(q_gt)
cam2w_gt[:3, -1] = t_gt
# residual reprojection
eyes_residual = (np.linalg.inv(cam2w_est) @ cam2w_gt @ eye_coords.T).T
uv_pred = project(eyes_residual, K, (W, H))
# get reprojection error
repr_err = np.linalg.norm(uv_gt - uv_pred, ord=2, axis=1)
mean_repr_err = float(repr_err.mean().item())
return mean_repr_err
def load_mask(mask_path: str, size: tuple):
mask_tensor = torch.load(mask_path).unsqueeze(0).unsqueeze(0)
# print("Mask tensor shape: ", mask_tensor.shape)
mask = tnf.interpolate(mask_tensor, size, mode='bilinear')
# print("Mask shape after interpolation: ", mask.shape)
mask = mask.squeeze()
return mask.numpy()
def is_point_in_mask(point, mask):
return mask[point[1], point[0]] > 0
def filter_matches_within_mask(matches_im0, matches_im1, mask1, mask2):
"""Filter matches that are within the mask given matches and masks."""
matches_in_mask = []
for m1, m2 in zip(matches_im0, matches_im1):
if is_point_in_mask(m1, mask1) and is_point_in_mask(m2, mask2):
matches_in_mask.append((m1, m2))
return np.array(matches_in_mask)
def compute_metrics(pts2d, pts3d, K, gt_pose, img0, output_dir):
success, r_pose, t_pose, _ = cv2.solvePnPRansac(pts3d, pts2d, K, None, flags=cv2.SOLVEPNP_SQPNP,
confidence=0.9999)
r_pose = cv2.Rodrigues(r_pose)[0] # world2cam == world2cam2
RT = np.r_[np.c_[r_pose, t_pose], [(0,0,0,1)]] # world2cam2
computed_pose = np.linalg.inv(RT) # cam2toworld
if success:
# print(f"PnP with RANSAC succeeded")
q = np.array((gt_pose[0], gt_pose[1], gt_pose[2], gt_pose[3]), dtype=np.float64)
t = np.array((gt_pose[4], gt_pose[5], gt_pose[6]), dtype=np.float64)
assert len(q) == 4 and len(t) == 3
q, t = convert_world2cam_to_cam2world(q, t)
R_est = computed_pose[:3, :3]
t_est = computed_pose[:3, 3]
errors = pose_error_torch(torch.from_numpy(R_est).unsqueeze(0), torch.from_numpy(t_est).unsqueeze(0),
torch.from_numpy(pose_to_matrix(*q, *t)).unsqueeze(0))
np.savetxt(os.path.join(output_dir, 'computed_pose.txt'), computed_pose)
ground_truth_pose = pose_to_matrix(*q, *t)
np.savetxt(os.path.join(output_dir, 'ground_truth_pose.txt'), ground_truth_pose)
abs_transl_error = errors['t_err_euc'].item()
abs_angular_error = errors['R_err'].item()
abs_transl_error_deg = errors['t_err_ang'].item()
abs_transl_error_scale = errors['t_err_scale'].item()
abs_transl_error_scale_sym = errors['t_err_scale_sym'].item()
# get q_est and t_est in qw, qx, qy, qz format
q_est = R.from_matrix(R_est).as_quat()
t_est = t_est
width = img0.shape[1]
height = img0.shape[0]
reproj_err = reprojection_error(q_est, t_est, q, t, K, width, height)
with open(os.path.join(output_dir, 'errors.txt'), 'w') as f:
f.write(f"Absolute translation error: {abs_transl_error}\n")
f.write(f"Absolute angular error: {abs_angular_error}\n")
f.write(f"Absolute translation error in degrees: {abs_transl_error_deg}\n")
f.write(f"Absolute translation error in scale: {abs_transl_error_scale}\n")
f.write(f"Absolute translation error in scale symmetric: {abs_transl_error_scale_sym}\n")
f.write(f"Reprojection error: {reproj_err}\n")
errors = {}
errors['abs_transl_error'] = abs_transl_error
errors['abs_angular_error'] = abs_angular_error
errors['abs_transl_error_deg'] = abs_transl_error_deg
errors['abs_transl_error_scale'] = abs_transl_error_scale
errors['abs_transl_error_scale_sym'] = abs_transl_error_scale_sym
errors['reproj_err'] = reproj_err
return errors
else:
print("PnP with RANSAC failed")
return None
def match_images(img1_path, img2_path, mask1_path, mask2_path, output_dir):
device = 'cuda'
model_name = "naver/MASt3R_ViTLarge_BaseDecoder_512_catmlpdpt_metric"
model = AsymmetricMASt3R.from_pretrained(model_name).to(device)
images = load_images([img1_path, img2_path], size=512)
output = inference([tuple(images)], model, device, batch_size=1, verbose=False)
view1, pred1 = output['view1'], output['pred1']
view2, pred2 = output['view2'], output['pred2']
desc1, desc2 = pred1['desc'].squeeze(0).detach(), pred2['desc'].squeeze(0).detach()
print(f"Desc1 shape: {desc1.shape}")
print(f"Desc2 shape: {desc2.shape}")
matches_im0, matches_im1 = fast_reciprocal_NNs(desc1, desc2, subsample_or_initxy1=8,
device=device, dist='dot', block_size=2**13)
H0, W0 = view1['true_shape'][0]
valid_matches_im0 = (matches_im0[:, 0] >= 3) & (matches_im0[:, 0] < int(W0) - 3) & (
matches_im0[:, 1] >= 3) & (matches_im0[:, 1] < int(H0) - 3)
H1, W1 = view2['true_shape'][0]
valid_matches_im1 = (matches_im1[:, 0] >= 3) & (matches_im1[:, 0] < int(W1) - 3) & (
matches_im1[:, 1] >= 3) & (matches_im1[:, 1] < int(H1) - 3)
valid_matches = valid_matches_im0 & valid_matches_im1
matches_im0, matches_im1 = matches_im0[valid_matches], matches_im1[valid_matches]
sav_matches_im0 = copy.deepcopy(matches_im0)
sav_matches_im1 = copy.deepcopy(matches_im1)
conf_list = [pred1['desc_conf'].squeeze(0).cpu().numpy(), pred2['desc_conf'].squeeze(0).cpu().numpy()]
matches_confs = np.minimum(
conf_list[1][matches_im0[:, 1], matches_im0[:, 0]],
conf_list[0][matches_im1[:, 1], matches_im1[:, 0]]
)
# if len(matches_confs) > 0:
# mask = matches_confs > 0.7
# matches_im0, matches_im1 = matches_im0[mask], matches_im1[mask]
# if matches_im0.shape[0] == 0:
# matches_im0 = sav_matches_im0
# matches_im1 = sav_matches_im1
mask1, mask2 = load_images([mask1_path, mask2_path], size=(512))
mask1_img = F.to_pil_image(mask1['img'])
mask1_img.save(os.path.join(output_dir, 'mask1VIZ.png'))
mask2_img = F.to_pil_image(mask2['img'])
mask2_img.save(os.path.join(output_dir, 'mask2VIZ.png'))
assert mask1 is not None and mask2 is not None
matches_in_mask = filter_matches_within_mask(matches_im0, matches_im1, mask1['img'], mask2['img'])
image_mean = torch.as_tensor([0.5, 0.5, 0.5], device='cpu').reshape(1, 3, 1, 1)
image_std = torch.as_tensor([0.5, 0.5, 0.5], device='cpu').reshape(1, 3, 1, 1)
viz_imgs = []
for i, view in enumerate([view1, view2]):
rgb_tensor = view['img'] * image_std + image_mean
viz_imgs.append(rgb_tensor.squeeze(0).permute(1, 2, 0).cpu().numpy())
H0, W0, H1, W1 = *viz_imgs[0].shape[:2], *viz_imgs[1].shape[:2]
img0 = np.pad(viz_imgs[0], ((0, max(H1 - H0, 0)), (0, 0), (0, 0)), 'constant', constant_values=0)
img1 = np.pad(viz_imgs[1], ((0, max(H0 - H1, 0)), (0, 0), (0, 0)), 'constant', constant_values=0)
img = np.concatenate((img0, img1), axis=1)
plt.figure()
plt.imshow(img)
cmap = plt.get_cmap('jet')
for m0, m1 in matches_in_mask:
(x0, y0), (x1, y1) = m0.T, m1.T
plt.plot([x0, x1 + W0], [y0, y1], '-+', scalex=False, scaley=False)
plt.savefig(os.path.join(output_dir, 'matched_images.png')) # Save the image to a file
plt.close()
pointmap1 = pred1['pts3d'].squeeze(0).detach().cpu().numpy() # 3D points of image 1 in the coordinate system of camera 1
pointmap2 = pred2['pts3d_in_other_view'].squeeze(0).detach().cpu().numpy() # 3D points of image 2 in the coordinate system of camera 1
assert pointmap1.shape[2] == 3 and pointmap2.shape[2] == 3
matches_im0 = matches_in_mask[:, 0]
matches_im1 = matches_in_mask[:, 1]
pts2d, pts3d = get_2d_3d_correspondences(matches_im0, matches_im1, pointmap1, pointmap2)
pts2d_vanilla, pts3d_vanilla = get_2d_3d_correspondences(sav_matches_im0, sav_matches_im1, pointmap1, pointmap2)
assert len(pts2d) == len(pts3d) and len(pts2d) >= 4
img2_modif_path = os.path.join(*img2_path.split('/')[-2:])
intrinsics_file = os.path.join(os.path.dirname(os.path.dirname(img2_path)), 'intrinsics.txt')
K1, width, height = read_intrinsics(intrinsics_file, img2_modif_path)
poses_file = os.path.join(os.path.dirname(os.path.dirname(img2_path)), 'poses.txt')
pose2 = read_pose(poses_file, img2_modif_path)
if pose2 is None:
raise ValueError(f"Pose for {img2_path} not found in {poses_file}")
if K1 is None:
raise ValueError(f"Intrinsics not found in {intrinsics_file}")
mask_results_dir = os.path.join(output_dir, 'mask_results')
os.makedirs(mask_results_dir, exist_ok=True)
vanilla_results_dir = os.path.join(output_dir, 'vanilla_results')
os.makedirs(vanilla_results_dir, exist_ok=True)
metrics_with_mask = compute_metrics(pts2d, pts3d, K1, pose2, viz_imgs[0], mask_results_dir)
metrics_vanilla = compute_metrics(pts2d_vanilla, pts3d_vanilla, K1, pose2, viz_imgs[0], vanilla_results_dir)
return metrics_with_mask, metrics_vanilla
def process_sequences(base_dir):
global_results_abs_transl = []
global_results_abs_angular = []
global_results_abs_transl_deg = []
global_results_abs_transl_scale = []
global_results_abs_transl_scale_sym = []
global_results_reproj = []
global_results_abs_transl_vanilla = []
global_results_abs_angular_vanilla = []
global_results_abs_transl_deg_vanilla = []
global_results_abs_transl_scale_vanilla = []
global_results_abs_transl_scale_sym_vanilla = []
global_results_reproj_vanilla = []
sequences = [sequence_folder for sequence_folder in os.listdir(base_dir) if os.path.isdir(os.path.join(base_dir, sequence_folder))]
sequences.sort(key=lambda x: int(x[1:]))
for sequence_folder in tqdm(sequences, desc="Processing sequences"):
sequence_path = os.path.join(base_dir, sequence_folder)
if os.path.isdir(sequence_path):
img1_path = os.path.join(sequence_path, 'seq0', 'frame_00000.jpg')
seq1_folder = os.path.join(sequence_path, 'seq1')
if not os.path.exists(img1_path) or not os.path.isdir(seq1_folder):
print("Warning: Required files/folders do not exist!!!")
continue
results = []
results_vanilla = []
for img2_file in os.listdir(seq1_folder):
img2_path = os.path.join(seq1_folder, img2_file)
if img2_file.endswith('.jpg'):
output_dir = os.path.join(sequence_path, 'results', os.path.splitext(img2_file)[0])
os.makedirs(output_dir, exist_ok=True)
frame_number = extract_frame_number(img2_file)
mask1_path, mask2_path = get_mask_paths(frame_number, sequence_folder)
errors_with_mask, errors_vanilla = match_images(img1_path, img2_path, mask1_path, mask2_path, output_dir)
results.append(errors_with_mask)
results_vanilla.append(errors_vanilla)
abs_transl_errors = [errors['abs_transl_error'] for errors in results]
abs_angular_errors = [errors['abs_angular_error'] for errors in results]
abs_transl_errors_deg = [errors['abs_transl_error_deg'] for errors in results]
abs_transl_errors_scale = [errors['abs_transl_error_scale'] for errors in results]
abs_transl_errors_scale_sym = [errors['abs_transl_error_scale_sym'] for errors in results]
reproj_errors = [errors['reproj_err'] for errors in results]
abs_transl_errors_vanilla = [errors['abs_transl_error'] for errors in results_vanilla]
abs_angular_errors_vanilla = [errors['abs_angular_error'] for errors in results_vanilla]
abs_transl_errors_deg_vanilla = [errors['abs_transl_error_deg'] for errors in results_vanilla]
abs_transl_errors_scale_vanilla = [errors['abs_transl_error_scale'] for errors in results_vanilla]
abs_transl_errors_scale_sym_vanilla = [errors['abs_transl_error_scale_sym'] for errors in results_vanilla]
reproj_errors_vanilla = [errors['reproj_err'] for errors in results_vanilla]
global_results_abs_transl.append(abs_transl_errors)
global_results_abs_angular.append(abs_angular_errors)
global_results_abs_transl_deg.append(abs_transl_errors_deg)
global_results_abs_transl_scale.append(abs_transl_errors_scale)
global_results_abs_transl_scale_sym.append(abs_transl_errors_scale_sym)
global_results_reproj.append(reproj_errors)
global_results_abs_transl_vanilla.append(abs_transl_errors_vanilla)
global_results_abs_angular_vanilla.append(abs_angular_errors_vanilla)
global_results_abs_transl_deg_vanilla.append(abs_transl_errors_deg_vanilla)
global_results_abs_transl_scale_vanilla.append(abs_transl_errors_scale_vanilla)
global_results_abs_transl_scale_sym_vanilla.append(abs_transl_errors_scale_sym_vanilla)
global_results_reproj_vanilla.append(reproj_errors_vanilla)
with open(os.path.join(sequence_path, 'median_errors.txt'), 'w') as f:
f.write(f"Median absolute translation error: {np.median(abs_transl_errors)}\n")
f.write(f"Median absolute angular error: {np.median(abs_angular_errors)}\n")
f.write(f"Median absolute translation error in degrees: {np.median(abs_transl_errors_deg)}\n")
f.write(f"Median absolute translation error in scale: {np.median(abs_transl_errors_scale)}\n")
f.write(f"Median absolute translation error in scale symmetric: {np.median(abs_transl_errors_scale_sym)}\n")
f.write(f"Median reprojection error: {np.median(reproj_errors)}\n")
with open(os.path.join(sequence_path, 'mean_errors.txt'), 'w') as f:
f.write(f"Mean absolute translation error: {np.mean(abs_transl_errors)}\n")
f.write(f"Mean absolute angular error: {np.mean(abs_angular_errors)}\n")
f.write(f"Mean absolute translation error in degrees: {np.mean(abs_transl_errors_deg)}\n")
f.write(f"Mean absolute translation error in scale: {np.mean(abs_transl_errors_scale)}\n")
f.write(f"Mean absolute translation error in scale symmetric: {np.mean(abs_transl_errors_scale_sym)}\n")
f.write(f"Mean reprojection error: {np.mean(reproj_errors)}\n")
with open(os.path.join(sequence_path, 'median_errors_vanilla.txt'), 'w') as f:
f.write(f"Median absolute translation error: {np.median(abs_transl_errors_vanilla)}\n")
f.write(f"Median absolute angular error: {np.median(abs_angular_errors_vanilla)}\n")
f.write(f"Median absolute translation error in degrees: {np.median(abs_transl_errors_deg_vanilla)}\n")
f.write(f"Median absolute translation error in scale: {np.median(abs_transl_errors_scale_vanilla)}\n")
f.write(f"Median absolute translation error in scale symmetric: {np.median(abs_transl_errors_scale_sym_vanilla)}\n")
f.write(f"Median reprojection error: {np.median(reproj_errors_vanilla)}\n")
with open(os.path.join(sequence_path, 'mean_errors_vanilla.txt'), 'w') as f:
f.write(f"Mean absolute translation error: {np.mean(abs_transl_errors_vanilla)}\n")
f.write(f"Mean absolute angular error: {np.mean(abs_angular_errors_vanilla)}\n")
f.write(f"Mean absolute translation error in degrees: {np.mean(abs_transl_errors_deg_vanilla)}\n")
f.write(f"Mean absolute translation error in scale: {np.mean(abs_transl_errors_scale_vanilla)}\n")
f.write(f"Mean absolute translation error in scale symmetric: {np.mean(abs_transl_errors_scale_sym_vanilla)}\n")
f.write(f"Mean reprojection error: {np.mean(reproj_errors_vanilla)}\n")
with open(os.path.join(base_dir, 'global_median_errors.txt'), 'w') as f:
f.write(f"Median absolute translation error: {np.median(np.concatenate(global_results_abs_transl))}\n")
f.write(f"Median absolute angular error: {np.median(np.concatenate(global_results_abs_angular))}\n")
f.write(f"Median absolute translation error in degrees: {np.median(np.concatenate(global_results_abs_transl_deg))}\n")
f.write(f"Median absolute translation error in scale: {np.median(np.concatenate(global_results_abs_transl_scale))}\n")
f.write(f"Median absolute translation error in scale symmetric: {np.median(np.concatenate(global_results_abs_transl_scale_sym))}\n")
f.write(f"Median reprojection error: {np.median(np.concatenate(global_results_reproj))}\n")
with open(os.path.join(base_dir, 'global_mean_errors.txt'), 'w') as f:
f.write(f"Mean absolute translation error: {np.mean(np.concatenate(global_results_abs_transl))}\n")
f.write(f"Mean absolute angular error: {np.mean(np.concatenate(global_results_abs_angular))}\n")
f.write(f"Mean absolute translation error in degrees: {np.mean(np.concatenate(global_results_abs_transl_deg))}\n")
f.write(f"Mean absolute translation error in scale: {np.mean(np.concatenate(global_results_abs_transl_scale))}\n")
f.write(f"Mean absolute translation error in scale symmetric: {np.mean(np.concatenate(global_results_abs_transl_scale_sym))}\n")
f.write(f"Mean reprojection error: {np.mean(np.concatenate(global_results_reproj))}\n")
with open(os.path.join(base_dir, 'global_median_errors_vanilla.txt'), 'w') as f:
f.write(f"Median absolute translation error: {np.median(np.concatenate(global_results_abs_transl_vanilla))}\n")
f.write(f"Median absolute angular error: {np.median(np.concatenate(global_results_abs_angular_vanilla))}\n")
f.write(f"Median absolute translation error in degrees: {np.median(np.concatenate(global_results_abs_transl_deg_vanilla))}\n")
f.write(f"Median absolute translation error in scale: {np.median(np.concatenate(global_results_abs_transl_scale_vanilla))}\n")
f.write(f"Median absolute translation error in scale symmetric: {np.median(np.concatenate(global_results_abs_transl_scale_sym_vanilla))}\n")
f.write(f"Median reprojection error: {np.median(np.concatenate(global_results_reproj_vanilla))}\n")
with open(os.path.join(base_dir, 'global_mean_errors_vanilla.txt'), 'w') as f:
f.write(f"Mean absolute translation error: {np.mean(np.concatenate(global_results_abs_transl_vanilla))}\n")
f.write(f"Mean absolute angular error: {np.mean(np.concatenate(global_results_abs_angular_vanilla))}\n")
f.write(f"Mean absolute translation error in degrees: {np.mean(np.concatenate(global_results_abs_transl_deg_vanilla))}\n")
f.write(f"Mean absolute translation error in scale: {np.mean(np.concatenate(global_results_abs_transl_scale_vanilla))}\n")
f.write(f"Mean absolute translation error in scale symmetric: {np.mean(np.concatenate(global_results_abs_transl_scale_sym_vanilla))}\n")
f.write(f"Mean reprojection error: {np.mean(np.concatenate(global_results_reproj_vanilla))}\n")
print("All Processing Done!!!")
if __name__ == "__main__":
base_dir = "/home2/swayam_421/indoor_loc/expts/dataset/upd_dataset/mapfree_subset"
process_sequences(base_dir)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment