|
import torch |
|
import numpy as np |
|
import cv2 |
|
from hloc import matchers, extractors |
|
from hloc.utils.base_model import dynamic_load |
|
from hloc import match_dense, match_features, extract_features |
|
from .plotting import draw_matches, fig2im |
|
from .visualize_util import plot_images, plot_color_line_matches |
|
|
|
device = "cuda" if torch.cuda.is_available() else "cpu" |
|
|
|
|
|
def get_model(match_conf): |
|
Model = dynamic_load(matchers, match_conf["model"]["name"]) |
|
model = Model(match_conf["model"]).eval().to(device) |
|
return model |
|
|
|
|
|
def get_feature_model(conf): |
|
Model = dynamic_load(extractors, conf["model"]["name"]) |
|
model = Model(conf["model"]).eval().to(device) |
|
return model |
|
|
|
|
|
def display_matches(pred: dict): |
|
img0 = pred["image0_orig"] |
|
img1 = pred["image1_orig"] |
|
|
|
num_inliers = 0 |
|
if "keypoints0_orig" in pred.keys() and "keypoints1_orig" in pred.keys(): |
|
mkpts0 = pred["keypoints0_orig"] |
|
mkpts1 = pred["keypoints1_orig"] |
|
num_inliers = len(mkpts0) |
|
if "mconf" in pred.keys(): |
|
mconf = pred["mconf"] |
|
else: |
|
mconf = np.ones(len(mkpts0)) |
|
fig_mkpts = draw_matches( |
|
mkpts0, |
|
mkpts1, |
|
img0, |
|
img1, |
|
mconf, |
|
dpi=300, |
|
titles=["Image 0 - matched keypoints", "Image 1 - matched keypoints"], |
|
) |
|
fig = fig_mkpts |
|
if "line0_orig" in pred.keys() and "line1_orig" in pred.keys(): |
|
|
|
mtlines0 = pred["line0_orig"] |
|
mtlines1 = pred["line1_orig"] |
|
num_inliers = len(mtlines0) |
|
fig_lines = plot_images( |
|
[img0.squeeze(), img1.squeeze()], |
|
["Image 0 - matched lines", "Image 1 - matched lines"], |
|
dpi=300, |
|
) |
|
fig_lines = plot_color_line_matches([mtlines0, mtlines1], lw=2) |
|
fig_lines = fig2im(fig_lines) |
|
|
|
|
|
mkpts0 = pred["line_keypoints0_orig"] |
|
mkpts1 = pred["line_keypoints1_orig"] |
|
|
|
if mkpts0 is not None and mkpts1 is not None: |
|
num_inliers = len(mkpts0) |
|
if "mconf" in pred.keys(): |
|
mconf = pred["mconf"] |
|
else: |
|
mconf = np.ones(len(mkpts0)) |
|
fig_mkpts = draw_matches(mkpts0, mkpts1, img0, img1, mconf, dpi=300) |
|
fig_lines = cv2.resize(fig_lines, (fig_mkpts.shape[1], fig_mkpts.shape[0])) |
|
fig = np.concatenate([fig_mkpts, fig_lines], axis=0) |
|
else: |
|
fig = fig_lines |
|
return fig, num_inliers |
|
|
|
|
|
|
|
matcher_zoo = { |
|
"gluestick": {"config": match_dense.confs["gluestick"], "dense": True}, |
|
"sold2": {"config": match_dense.confs["sold2"], "dense": True}, |
|
|
|
|
|
|
|
|
|
"loftr": {"config": match_dense.confs["loftr"], "dense": True}, |
|
"topicfm": {"config": match_dense.confs["topicfm"], "dense": True}, |
|
"aspanformer": {"config": match_dense.confs["aspanformer"], "dense": True}, |
|
"dedode": { |
|
"config": match_features.confs["Dual-Softmax"], |
|
"config_feature": extract_features.confs["dedode"], |
|
"dense": False, |
|
}, |
|
"superpoint+superglue": { |
|
"config": match_features.confs["superglue"], |
|
"config_feature": extract_features.confs["superpoint_max"], |
|
"dense": False, |
|
}, |
|
"superpoint+lightglue": { |
|
"config": match_features.confs["superpoint-lightglue"], |
|
"config_feature": extract_features.confs["superpoint_max"], |
|
"dense": False, |
|
}, |
|
"disk": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["disk"], |
|
"dense": False, |
|
}, |
|
"disk+dualsoftmax": { |
|
"config": match_features.confs["Dual-Softmax"], |
|
"config_feature": extract_features.confs["disk"], |
|
"dense": False, |
|
}, |
|
"superpoint+dualsoftmax": { |
|
"config": match_features.confs["Dual-Softmax"], |
|
"config_feature": extract_features.confs["superpoint_max"], |
|
"dense": False, |
|
}, |
|
"disk+lightglue": { |
|
"config": match_features.confs["disk-lightglue"], |
|
"config_feature": extract_features.confs["disk"], |
|
"dense": False, |
|
}, |
|
"superpoint+mnn": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["superpoint_max"], |
|
"dense": False, |
|
}, |
|
"sift+sgmnet": { |
|
"config": match_features.confs["sgmnet"], |
|
"config_feature": extract_features.confs["sift"], |
|
"dense": False, |
|
}, |
|
"sosnet": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["sosnet"], |
|
"dense": False, |
|
}, |
|
"hardnet": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["hardnet"], |
|
"dense": False, |
|
}, |
|
"d2net": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["d2net-ss"], |
|
"dense": False, |
|
}, |
|
"d2net-ms": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["d2net-ms"], |
|
"dense": False, |
|
}, |
|
"alike": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["alike"], |
|
"dense": False, |
|
}, |
|
"lanet": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["lanet"], |
|
"dense": False, |
|
}, |
|
"r2d2": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["r2d2"], |
|
"dense": False, |
|
}, |
|
"darkfeat": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["darkfeat"], |
|
"dense": False, |
|
}, |
|
"sift": { |
|
"config": match_features.confs["NN-mutual"], |
|
"config_feature": extract_features.confs["sift"], |
|
"dense": False, |
|
}, |
|
"roma": {"config": match_dense.confs["roma"], "dense": True}, |
|
"DKMv3": {"config": match_dense.confs["dkm"], "dense": True}, |
|
} |
|
|