Vincentqyw
fix: roma
c74a070
import numpy as np
import sys
import os
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, ROOT_DIR)
from utils import evaluation_utils, metrics, fm_utils
import cv2
class auc_eval:
def __init__(self, config):
self.config = config
self.err_r, self.err_t, self.err = [], [], []
self.ms = []
self.precision = []
def run(self, info):
E, r_gt, t_gt = info["e"], info["r_gt"], info["t_gt"]
K1, K2, img1, img2 = info["K1"], info["K2"], info["img1"], info["img2"]
corr1, corr2 = info["corr1"], info["corr2"]
corr1, corr2 = evaluation_utils.normalize_intrinsic(
corr1, K1
), evaluation_utils.normalize_intrinsic(corr2, K2)
size1, size2 = max(img1.shape), max(img2.shape)
scale1, scale2 = self.config["rescale"] / size1, self.config["rescale"] / size2
# ransac
ransac_th = 4.0 / (
(K1[0, 0] + K1[1, 1]) * scale1 + (K2[0, 0] + K2[1, 1]) * scale2
)
R_hat, t_hat, E_hat = self.estimate(corr1, corr2, ransac_th)
# get pose error
err_r, err_t = metrics.evaluate_R_t(r_gt, t_gt, R_hat, t_hat)
err = max(err_r, err_t)
if len(corr1) > 1:
inlier_mask = metrics.compute_epi_inlier(
corr1, corr2, E, self.config["inlier_th"]
)
precision = inlier_mask.mean()
ms = inlier_mask.sum() / len(info["x1"])
else:
ms = precision = 0
return {
"err_r": err_r,
"err_t": err_t,
"err": err,
"ms": ms,
"precision": precision,
}
def res_inqueue(self, res):
self.err_r.append(res["err_r"]), self.err_t.append(
res["err_t"]
), self.err.append(res["err"])
self.ms.append(res["ms"]), self.precision.append(res["precision"])
def estimate(self, corr1, corr2, th):
num_inlier = -1
if corr1.shape[0] >= 5:
E, mask_new = cv2.findEssentialMat(
corr1, corr2, method=cv2.RANSAC, threshold=th, prob=1 - 1e-5
)
if E is None:
E = [np.eye(3)]
for _E in np.split(E, len(E) / 3):
_num_inlier, _R, _t, _ = cv2.recoverPose(
_E, corr1, corr2, np.eye(3), 1e9, mask=mask_new
)
if _num_inlier > num_inlier:
num_inlier = _num_inlier
R = _R
t = _t
E = _E
else:
E, R, t = np.eye(3), np.eye(3), np.zeros(3)
return R, t, E
def parse(self):
ths = np.arange(7) * 5
approx_auc = metrics.approx_pose_auc(self.err, ths)
exact_auc = metrics.pose_auc(self.err, ths)
mean_pre, mean_ms = np.mean(np.asarray(self.precision)), np.mean(
np.asarray(self.ms)
)
print("auc th: ", ths[1:])
print("approx auc: ", approx_auc)
print("exact auc: ", exact_auc)
print("mean match score: ", mean_ms * 100)
print("mean precision: ", mean_pre * 100)
class FMbench_eval:
def __init__(self, config):
self.config = config
self.pre, self.pre_post, self.sgd = [], [], []
self.num_corr, self.num_corr_post = [], []
def run(self, info):
corr1, corr2 = info["corr1"], info["corr2"]
F = info["f"]
img1, img2 = info["img1"], info["img2"]
if len(corr1) > 1:
pre_bf = fm_utils.compute_inlier_rate(
corr1,
corr2,
np.flip(img1.shape[:2]),
np.flip(img2.shape[:2]),
F,
th=self.config["inlier_th"],
).mean()
F_hat, mask_F = cv2.findFundamentalMat(
corr1,
corr2,
method=cv2.FM_RANSAC,
ransacReprojThreshold=1,
confidence=1 - 1e-5,
)
if F_hat is None:
F_hat = np.ones([3, 3])
mask_F = np.ones([len(corr1)]).astype(bool)
else:
mask_F = mask_F.squeeze().astype(bool)
F_hat = F_hat[:3]
pre_af = fm_utils.compute_inlier_rate(
corr1[mask_F],
corr2[mask_F],
np.flip(img1.shape[:2]),
np.flip(img2.shape[:2]),
F,
th=self.config["inlier_th"],
).mean()
num_corr_af = mask_F.sum()
num_corr = len(corr1)
sgd = fm_utils.compute_SGD(
F, F_hat, np.flip(img1.shape[:2]), np.flip(img2.shape[:2])
)
else:
pre_bf, pre_af, sgd = 0, 0, 1e8
num_corr, num_corr_af = 0, 0
return {
"pre": pre_bf,
"pre_post": pre_af,
"sgd": sgd,
"num_corr": num_corr,
"num_corr_post": num_corr_af,
}
def res_inqueue(self, res):
self.pre.append(res["pre"]), self.pre_post.append(
res["pre_post"]
), self.sgd.append(res["sgd"])
self.num_corr.append(res["num_corr"]), self.num_corr_post.append(
res["num_corr_post"]
)
def parse(self):
for seq_index in range(len(self.config["seq"])):
seq = self.config["seq"][seq_index]
offset = seq_index * 1000
pre = np.asarray(self.pre)[offset : offset + 1000].mean()
pre_post = np.asarray(self.pre_post)[offset : offset + 1000].mean()
num_corr = np.asarray(self.num_corr)[offset : offset + 1000].mean()
num_corr_post = np.asarray(self.num_corr_post)[
offset : offset + 1000
].mean()
f_recall = (
np.asarray(self.sgd)[offset : offset + 1000]
< self.config["sgd_inlier_th"]
).mean()
print(seq, "results:")
print("F_recall: ", f_recall)
print("precision: ", pre)
print("precision_post: ", pre_post)
print("num_corr: ", num_corr)
print("num_corr_post: ", num_corr_post, "\n")