megadepth_pose_estimation_benchmark_poselib.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import numpy as np
  2. import torch
  3. from romatch.utils import *
  4. from PIL import Image
  5. from tqdm import tqdm
  6. import torch.nn.functional as F
  7. import romatch
  8. import kornia.geometry.epipolar as kepi
  9. # wrap cause pyposelib is still in dev
  10. # will add in deps later
  11. import poselib
  12. class Mega1500PoseLibBenchmark:
  13. def __init__(self, data_root="data/megadepth", scene_names = None, num_ransac_iter = 5, test_every = 1) -> None:
  14. if scene_names is None:
  15. self.scene_names = [
  16. "0015_0.1_0.3.npz",
  17. "0015_0.3_0.5.npz",
  18. "0022_0.1_0.3.npz",
  19. "0022_0.3_0.5.npz",
  20. "0022_0.5_0.7.npz",
  21. ]
  22. else:
  23. self.scene_names = scene_names
  24. self.scenes = [
  25. np.load(f"{data_root}/{scene}", allow_pickle=True)
  26. for scene in self.scene_names
  27. ]
  28. self.data_root = data_root
  29. self.num_ransac_iter = num_ransac_iter
  30. self.test_every = test_every
  31. def benchmark(self, model, model_name = None):
  32. with torch.no_grad():
  33. data_root = self.data_root
  34. tot_e_t, tot_e_R, tot_e_pose = [], [], []
  35. thresholds = [5, 10, 20]
  36. for scene_ind in range(len(self.scenes)):
  37. import os
  38. scene_name = os.path.splitext(self.scene_names[scene_ind])[0]
  39. scene = self.scenes[scene_ind]
  40. pairs = scene["pair_infos"]
  41. intrinsics = scene["intrinsics"]
  42. poses = scene["poses"]
  43. im_paths = scene["image_paths"]
  44. pair_inds = range(len(pairs))[::self.test_every]
  45. for pairind in (pbar := tqdm(pair_inds, desc = "Current AUC: ?")):
  46. idx1, idx2 = pairs[pairind][0]
  47. K1 = intrinsics[idx1].copy()
  48. T1 = poses[idx1].copy()
  49. R1, t1 = T1[:3, :3], T1[:3, 3]
  50. K2 = intrinsics[idx2].copy()
  51. T2 = poses[idx2].copy()
  52. R2, t2 = T2[:3, :3], T2[:3, 3]
  53. R, t = compute_relative_pose(R1, t1, R2, t2)
  54. T1_to_2 = np.concatenate((R,t[:,None]), axis=-1)
  55. im_A_path = f"{data_root}/{im_paths[idx1]}"
  56. im_B_path = f"{data_root}/{im_paths[idx2]}"
  57. dense_matches, dense_certainty = model.match(
  58. im_A_path, im_B_path, K1.copy(), K2.copy(), T1_to_2.copy()
  59. )
  60. sparse_matches,_ = model.sample(
  61. dense_matches, dense_certainty, 5_000
  62. )
  63. im_A = Image.open(im_A_path)
  64. w1, h1 = im_A.size
  65. im_B = Image.open(im_B_path)
  66. w2, h2 = im_B.size
  67. kpts1, kpts2 = model.to_pixel_coordinates(sparse_matches, h1, w1, h2, w2)
  68. kpts1, kpts2 = kpts1.cpu().numpy(), kpts2.cpu().numpy()
  69. for _ in range(self.num_ransac_iter):
  70. shuffling = np.random.permutation(np.arange(len(kpts1)))
  71. kpts1 = kpts1[shuffling]
  72. kpts2 = kpts2[shuffling]
  73. try:
  74. threshold = 1
  75. camera1 = {'model': 'PINHOLE', 'width': w1, 'height': h1, 'params': K1[[0,1,0,1], [0,1,2,2]]}
  76. camera2 = {'model': 'PINHOLE', 'width': w2, 'height': h2, 'params': K2[[0,1,0,1], [0,1,2,2]]}
  77. relpose, res = poselib.estimate_relative_pose(
  78. kpts1,
  79. kpts2,
  80. camera1,
  81. camera2,
  82. ransac_opt = {"max_reproj_error": 2*threshold, "max_epipolar_error": threshold, "min_inliers": 8, "max_iterations": 10_000},
  83. )
  84. Rt_est = relpose.Rt
  85. R_est, t_est = Rt_est[:3,:3], Rt_est[:3,3:]
  86. mask = np.array(res['inliers']).astype(np.float32)
  87. T1_to_2_est = np.concatenate((R_est, t_est), axis=-1) #
  88. e_t, e_R = compute_pose_error(T1_to_2_est, R, t)
  89. e_pose = max(e_t, e_R)
  90. except Exception as e:
  91. print(repr(e))
  92. e_t, e_R = 90, 90
  93. e_pose = max(e_t, e_R)
  94. tot_e_t.append(e_t)
  95. tot_e_R.append(e_R)
  96. tot_e_pose.append(e_pose)
  97. pbar.set_description(f"Current AUC: {pose_auc(tot_e_pose, thresholds)}")
  98. tot_e_pose = np.array(tot_e_pose)
  99. auc = pose_auc(tot_e_pose, thresholds)
  100. acc_5 = (tot_e_pose < 5).mean()
  101. acc_10 = (tot_e_pose < 10).mean()
  102. acc_15 = (tot_e_pose < 15).mean()
  103. acc_20 = (tot_e_pose < 20).mean()
  104. map_5 = acc_5
  105. map_10 = np.mean([acc_5, acc_10])
  106. map_20 = np.mean([acc_5, acc_10, acc_15, acc_20])
  107. print(f"{model_name} auc: {auc}")
  108. return {
  109. "auc_5": auc[0],
  110. "auc_10": auc[1],
  111. "auc_20": auc[2],
  112. "map_5": map_5,
  113. "map_10": map_10,
  114. "map_20": map_20,
  115. }