Spaces:
Running
Running
Realcat
commited on
Commit
•
b7f7f2c
1
Parent(s):
7acaad7
add: xfeat: https://github.com/verlab/accelerated_features
Browse files- common/config.yaml +4 -0
- common/utils.py +5 -3
- common/viz.py +6 -1
- hloc/extract_features.py +11 -0
- hloc/extractors/disk.py +2 -1
- hloc/extractors/xfeat.py +32 -0
common/config.yaml
CHANGED
@@ -28,6 +28,10 @@ matcher_zoo:
|
|
28 |
aspanformer:
|
29 |
matcher: aspanformer
|
30 |
dense: true
|
|
|
|
|
|
|
|
|
31 |
dedode:
|
32 |
matcher: Dual-Softmax
|
33 |
feature: dedode
|
|
|
28 |
aspanformer:
|
29 |
matcher: aspanformer
|
30 |
dense: true
|
31 |
+
xfeat:
|
32 |
+
matcher: NN-mutual
|
33 |
+
feature: xfeat
|
34 |
+
dense: false
|
35 |
dedode:
|
36 |
matcher: Dual-Softmax
|
37 |
feature: dedode
|
common/utils.py
CHANGED
@@ -18,6 +18,8 @@ from .viz import (
|
|
18 |
display_matches,
|
19 |
plot_color_line_matches,
|
20 |
)
|
|
|
|
|
21 |
|
22 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
23 |
|
@@ -462,7 +464,7 @@ def run_matching(
|
|
462 |
# update match config
|
463 |
match_conf["model"]["match_threshold"] = match_threshold
|
464 |
match_conf["model"]["max_keypoints"] = extract_max_keypoints
|
465 |
-
|
466 |
matcher = get_model(match_conf)
|
467 |
if model["dense"]:
|
468 |
pred = match_dense.match_images(
|
@@ -534,9 +536,9 @@ def run_matching(
|
|
534 |
{"geom_info": geom_info},
|
535 |
choice_estimate_geom,
|
536 |
)
|
537 |
-
|
538 |
del pred
|
539 |
-
|
540 |
return (
|
541 |
output_keypoints,
|
542 |
output_matches_raw,
|
|
|
18 |
display_matches,
|
19 |
plot_color_line_matches,
|
20 |
)
|
21 |
+
import time
|
22 |
+
import matplotlib.pyplot as plt
|
23 |
|
24 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
25 |
|
|
|
464 |
# update match config
|
465 |
match_conf["model"]["match_threshold"] = match_threshold
|
466 |
match_conf["model"]["max_keypoints"] = extract_max_keypoints
|
467 |
+
t1 = time.time()
|
468 |
matcher = get_model(match_conf)
|
469 |
if model["dense"]:
|
470 |
pred = match_dense.match_images(
|
|
|
536 |
{"geom_info": geom_info},
|
537 |
choice_estimate_geom,
|
538 |
)
|
539 |
+
plt.close("all")
|
540 |
del pred
|
541 |
+
logger.info(f"TOTAL time: {time.time()-t1:.3f}s")
|
542 |
return (
|
543 |
output_keypoints,
|
544 |
output_matches_raw,
|
common/viz.py
CHANGED
@@ -252,6 +252,7 @@ def draw_matches(
|
|
252 |
img1: np.ndarray,
|
253 |
conf: np.ndarray,
|
254 |
titles: Optional[List[str]] = None,
|
|
|
255 |
dpi: int = 150,
|
256 |
path: Optional[str] = None,
|
257 |
pad: float = 0.5,
|
@@ -370,7 +371,10 @@ def draw_image_pairs(
|
|
370 |
|
371 |
|
372 |
def display_matches(
|
373 |
-
pred: Dict[str, np.ndarray],
|
|
|
|
|
|
|
374 |
) -> Tuple[np.ndarray, int]:
|
375 |
"""
|
376 |
Displays the matches between two images.
|
@@ -408,6 +412,7 @@ def display_matches(
|
|
408 |
mconf,
|
409 |
dpi=dpi,
|
410 |
titles=titles,
|
|
|
411 |
)
|
412 |
fig = fig_mkpts
|
413 |
if (
|
|
|
252 |
img1: np.ndarray,
|
253 |
conf: np.ndarray,
|
254 |
titles: Optional[List[str]] = None,
|
255 |
+
texts: Optional[List[str]] = None,
|
256 |
dpi: int = 150,
|
257 |
path: Optional[str] = None,
|
258 |
pad: float = 0.5,
|
|
|
371 |
|
372 |
|
373 |
def display_matches(
|
374 |
+
pred: Dict[str, np.ndarray],
|
375 |
+
titles: List[str] = [],
|
376 |
+
texts: List[str] = [],
|
377 |
+
dpi: int = 300,
|
378 |
) -> Tuple[np.ndarray, int]:
|
379 |
"""
|
380 |
Displays the matches between two images.
|
|
|
412 |
mconf,
|
413 |
dpi=dpi,
|
414 |
titles=titles,
|
415 |
+
texts=texts,
|
416 |
)
|
417 |
fig = fig_mkpts
|
418 |
if (
|
hloc/extract_features.py
CHANGED
@@ -201,6 +201,17 @@ confs = {
|
|
201 |
"resize_max": 1600,
|
202 |
},
|
203 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
"alike": {
|
205 |
"output": "feats-alike-n5000-r1600",
|
206 |
"model": {
|
|
|
201 |
"resize_max": 1600,
|
202 |
},
|
203 |
},
|
204 |
+
"xfeat": {
|
205 |
+
"output": "feats-xfeat-n5000-r1600",
|
206 |
+
"model": {
|
207 |
+
"name": "xfeat",
|
208 |
+
"max_keypoints": 5000,
|
209 |
+
},
|
210 |
+
"preprocessing": {
|
211 |
+
"grayscale": False,
|
212 |
+
"resize_max": 1600,
|
213 |
+
},
|
214 |
+
},
|
215 |
"alike": {
|
216 |
"output": "feats-alike-n5000-r1600",
|
217 |
"model": {
|
hloc/extractors/disk.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import kornia
|
2 |
-
|
3 |
from ..utils.base_model import BaseModel
|
4 |
|
5 |
|
@@ -15,6 +15,7 @@ class DISK(BaseModel):
|
|
15 |
|
16 |
def _init(self, conf):
|
17 |
self.model = kornia.feature.DISK.from_pretrained(conf["weights"])
|
|
|
18 |
|
19 |
def _forward(self, data):
|
20 |
image = data["image"]
|
|
|
1 |
import kornia
|
2 |
+
from hloc import logger
|
3 |
from ..utils.base_model import BaseModel
|
4 |
|
5 |
|
|
|
15 |
|
16 |
def _init(self, conf):
|
17 |
self.model = kornia.feature.DISK.from_pretrained(conf["weights"])
|
18 |
+
logger.info(f"Load DISK model done.")
|
19 |
|
20 |
def _forward(self, data):
|
21 |
image = data["image"]
|
hloc/extractors/xfeat.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from pathlib import Path
|
3 |
+
from hloc import logger
|
4 |
+
from ..utils.base_model import BaseModel
|
5 |
+
|
6 |
+
|
7 |
+
class XFeat(BaseModel):
|
8 |
+
default_conf = {
|
9 |
+
"keypoint_threshold": 0.005,
|
10 |
+
"max_keypoints": -1,
|
11 |
+
}
|
12 |
+
required_inputs = ["image"]
|
13 |
+
|
14 |
+
def _init(self, conf):
|
15 |
+
self.net = torch.hub.load(
|
16 |
+
"verlab/accelerated_features",
|
17 |
+
"XFeat",
|
18 |
+
pretrained=True,
|
19 |
+
top_k=self.conf["max_keypoints"],
|
20 |
+
)
|
21 |
+
logger.info(f"Load XFeat model done.")
|
22 |
+
|
23 |
+
def _forward(self, data):
|
24 |
+
pred = self.net.detectAndCompute(
|
25 |
+
data["image"], top_k=self.conf["max_keypoints"]
|
26 |
+
)[0]
|
27 |
+
pred = {
|
28 |
+
"keypoints": pred["keypoints"][None],
|
29 |
+
"scores": pred["scores"][None],
|
30 |
+
"descriptors": pred["descriptors"].T[None],
|
31 |
+
}
|
32 |
+
return pred
|