Vincentqyw
commited on
Commit
•
ab830e5
1
Parent(s):
0cc9e81
update: rord
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitignore +4 -0
- app.py +6 -3
- common/utils.py +10 -1
- hloc/extract_features.py +12 -0
- hloc/extractors/alike.py +0 -1
- hloc/extractors/d2net.py +0 -1
- hloc/extractors/darkfeat.py +1 -4
- hloc/extractors/dedode.py +1 -3
- hloc/extractors/example.py +1 -3
- hloc/extractors/fire_local.py +1 -2
- hloc/extractors/netvlad.py +1 -3
- hloc/extractors/rord.py +75 -0
- hloc/matchers/aspanformer.py +4 -3
- hloc/matchers/dkm.py +1 -3
- hloc/matchers/gluestick.py +1 -3
- hloc/matchers/lightglue.py +1 -2
- hloc/matchers/roma.py +1 -3
- hloc/matchers/sgmnet.py +1 -2
- hloc/matchers/sold2.py +14 -7
- hloc/utils/__init__.py +2 -2
- third_party/RoRD/LICENSE +251 -0
- third_party/RoRD/assets/register_ortho.jpg +3 -0
- third_party/RoRD/assets/register_persp.jpg +3 -0
- third_party/RoRD/assets/register_pointcloud.jpg +3 -0
- third_party/RoRD/assets/rord_evalRT.jpg +3 -0
- third_party/RoRD/assets/rord_extract.jpg +3 -0
- third_party/RoRD/assets/sift_extract.jpg +3 -0
- third_party/RoRD/assets/teaser2.jpg +3 -0
- third_party/RoRD/configs/camera.txt +3 -0
- third_party/RoRD/configs/train_scenes.txt +7 -0
- third_party/RoRD/configs/train_scenes_small.txt +1 -0
- third_party/RoRD/demo/__init__.py +0 -0
- third_party/RoRD/demo/depth/depth1_1.png +3 -0
- third_party/RoRD/demo/depth/depth1_2.png +3 -0
- third_party/RoRD/demo/depth/depth2_1.png +3 -0
- third_party/RoRD/demo/depth/depth2_2.png +3 -0
- third_party/RoRD/demo/depth/depth3_1.png +3 -0
- third_party/RoRD/demo/depth/depth3_2.png +3 -0
- third_party/RoRD/demo/register.py +265 -0
- third_party/RoRD/demo/rgb/rgb1_1.jpg +3 -0
- third_party/RoRD/demo/rgb/rgb1_1.npy +3 -0
- third_party/RoRD/demo/rgb/rgb1_2.jpg +3 -0
- third_party/RoRD/demo/rgb/rgb1_2.npy +3 -0
- third_party/RoRD/demo/rgb/rgb2_1.jpg +3 -0
- third_party/RoRD/demo/rgb/rgb2_1.npy +3 -0
- third_party/RoRD/demo/rgb/rgb2_2.jpg +3 -0
- third_party/RoRD/demo/rgb/rgb2_2.npy +3 -0
- third_party/RoRD/demo/rgb/rgb3_1.jpg +3 -0
- third_party/RoRD/demo/rgb/rgb3_1.npy +3 -0
- third_party/RoRD/demo/rgb/rgb3_2.jpg +3 -0
.gitignore
CHANGED
@@ -17,3 +17,7 @@ third_party/REKD
|
|
17 |
Dockerfile
|
18 |
hloc/matchers/dedode.py
|
19 |
gradio_cached_examples
|
|
|
|
|
|
|
|
|
|
17 |
Dockerfile
|
18 |
hloc/matchers/dedode.py
|
19 |
gradio_cached_examples
|
20 |
+
|
21 |
+
hloc/matchers/quadtree.py
|
22 |
+
third_party/QuadTreeAttention
|
23 |
+
desktop.ini
|
app.py
CHANGED
@@ -14,6 +14,9 @@ This Space demonstrates [Image Matching WebUI](https://github.com/Vincentqyw/ima
|
|
14 |
|
15 |
🔎 For more details about supported local features and matchers, please refer to https://github.com/Vincentqyw/image-matching-webui
|
16 |
|
|
|
|
|
|
|
17 |
"""
|
18 |
|
19 |
|
@@ -102,9 +105,9 @@ def run(config):
|
|
102 |
)
|
103 |
|
104 |
with gr.Row():
|
105 |
-
button_reset = gr.Button(
|
106 |
button_run = gr.Button(
|
107 |
-
|
108 |
)
|
109 |
|
110 |
with gr.Accordion("Advanced Setting", open=False):
|
@@ -242,7 +245,7 @@ def run(config):
|
|
242 |
)
|
243 |
with gr.Accordion("Open for More: Geometry info", open=False):
|
244 |
geometry_result = gr.JSON(label="Reconstructed Geometry")
|
245 |
-
|
246 |
# callbacks
|
247 |
match_image_src.change(
|
248 |
fn=ui_change_imagebox,
|
|
|
14 |
|
15 |
🔎 For more details about supported local features and matchers, please refer to https://github.com/Vincentqyw/image-matching-webui
|
16 |
|
17 |
+
🚀 All algorithms run on CPU for inference on HF, causing slow speeds and high latency. For faster inference, please download the [source code](https://github.com/Vincentqyw/image-matching-webui) for local deployment or check [openxlab space](https://github.com/Vincentqyw/image-matching-webui) and [direct URL](https://g-app-center-083997-7409-n9elr1.openxlab.space)
|
18 |
+
|
19 |
+
🐛 Your feedback is valuable to me. Please do not hesitate to report any bugs [here](https://github.com/Vincentqyw/image-matching-webui/issues).
|
20 |
"""
|
21 |
|
22 |
|
|
|
105 |
)
|
106 |
|
107 |
with gr.Row():
|
108 |
+
button_reset = gr.Button(value="Reset")
|
109 |
button_run = gr.Button(
|
110 |
+
value="Run Match", variant="primary"
|
111 |
)
|
112 |
|
113 |
with gr.Accordion("Advanced Setting", open=False):
|
|
|
245 |
)
|
246 |
with gr.Accordion("Open for More: Geometry info", open=False):
|
247 |
geometry_result = gr.JSON(label="Reconstructed Geometry")
|
248 |
+
|
249 |
# callbacks
|
250 |
match_image_src.change(
|
251 |
fn=ui_change_imagebox,
|
common/utils.py
CHANGED
@@ -48,6 +48,7 @@ def gen_examples():
|
|
48 |
pairs = list(combinations(imgs_list, 2))
|
49 |
selected = random.sample(range(len(pairs)), count)
|
50 |
return [pairs[i] for i in selected]
|
|
|
51 |
# image pair path
|
52 |
path = "datasets/sacre_coeur/mapping"
|
53 |
pairs = gen_images_pairs(path, len(example_matchers))
|
@@ -176,7 +177,10 @@ def compute_geom(
|
|
176 |
if H is not None:
|
177 |
geo_info["Homography"] = H.tolist()
|
178 |
_, H1, H2 = cv2.stereoRectifyUncalibrated(
|
179 |
-
mkpts0.reshape(-1, 2),
|
|
|
|
|
|
|
180 |
)
|
181 |
geo_info["H1"] = H1.tolist()
|
182 |
geo_info["H2"] = H2.tolist()
|
@@ -504,6 +508,11 @@ matcher_zoo = {
|
|
504 |
"config_feature": extract_features.confs["d2net-ss"],
|
505 |
"dense": False,
|
506 |
},
|
|
|
|
|
|
|
|
|
|
|
507 |
# "d2net-ms": {
|
508 |
# "config": match_features.confs["NN-mutual"],
|
509 |
# "config_feature": extract_features.confs["d2net-ms"],
|
|
|
48 |
pairs = list(combinations(imgs_list, 2))
|
49 |
selected = random.sample(range(len(pairs)), count)
|
50 |
return [pairs[i] for i in selected]
|
51 |
+
|
52 |
# image pair path
|
53 |
path = "datasets/sacre_coeur/mapping"
|
54 |
pairs = gen_images_pairs(path, len(example_matchers))
|
|
|
177 |
if H is not None:
|
178 |
geo_info["Homography"] = H.tolist()
|
179 |
_, H1, H2 = cv2.stereoRectifyUncalibrated(
|
180 |
+
mkpts0.reshape(-1, 2),
|
181 |
+
mkpts1.reshape(-1, 2),
|
182 |
+
F,
|
183 |
+
imgSize=(w1, h1),
|
184 |
)
|
185 |
geo_info["H1"] = H1.tolist()
|
186 |
geo_info["H2"] = H2.tolist()
|
|
|
508 |
"config_feature": extract_features.confs["d2net-ss"],
|
509 |
"dense": False,
|
510 |
},
|
511 |
+
"rord": {
|
512 |
+
"config": match_features.confs["NN-mutual"],
|
513 |
+
"config_feature": extract_features.confs["rord"],
|
514 |
+
"dense": False,
|
515 |
+
},
|
516 |
# "d2net-ms": {
|
517 |
# "config": match_features.confs["NN-mutual"],
|
518 |
# "config_feature": extract_features.confs["d2net-ms"],
|
hloc/extract_features.py
CHANGED
@@ -115,6 +115,18 @@ confs = {
|
|
115 |
"resize_max": 1600,
|
116 |
},
|
117 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
"rootsift": {
|
119 |
"output": "feats-rootsift-n5000-r1600",
|
120 |
"model": {
|
|
|
115 |
"resize_max": 1600,
|
116 |
},
|
117 |
},
|
118 |
+
"rord": {
|
119 |
+
"output": "feats-rord-ss-n5000-r1600",
|
120 |
+
"model": {
|
121 |
+
"name": "rord",
|
122 |
+
"multiscale": False,
|
123 |
+
"max_keypoints": 5000,
|
124 |
+
},
|
125 |
+
"preprocessing": {
|
126 |
+
"grayscale": False,
|
127 |
+
"resize_max": 1600,
|
128 |
+
},
|
129 |
+
},
|
130 |
"rootsift": {
|
131 |
"output": "feats-rootsift-n5000-r1600",
|
132 |
"model": {
|
hloc/extractors/alike.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
-
import subprocess
|
4 |
import torch
|
5 |
|
6 |
from ..utils.base_model import BaseModel
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
|
|
3 |
import torch
|
4 |
|
5 |
from ..utils.base_model import BaseModel
|
hloc/extractors/d2net.py
CHANGED
@@ -10,7 +10,6 @@ sys.path.append(str(d2net_path))
|
|
10 |
from lib.model_test import D2Net as _D2Net
|
11 |
from lib.pyramid import process_multiscale
|
12 |
|
13 |
-
|
14 |
class D2Net(BaseModel):
|
15 |
default_conf = {
|
16 |
"model_name": "d2_tf.pth",
|
|
|
10 |
from lib.model_test import D2Net as _D2Net
|
11 |
from lib.pyramid import process_multiscale
|
12 |
|
|
|
13 |
class D2Net(BaseModel):
|
14 |
default_conf = {
|
15 |
"model_name": "d2_tf.pth",
|
hloc/extractors/darkfeat.py
CHANGED
@@ -1,11 +1,8 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
-
import logging
|
5 |
-
|
6 |
from ..utils.base_model import BaseModel
|
7 |
-
|
8 |
-
logger = logging.getLogger(__name__)
|
9 |
|
10 |
darkfeat_path = Path(__file__).parent / "../../third_party/DarkFeat"
|
11 |
sys.path.append(str(darkfeat_path))
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
|
|
|
|
4 |
from ..utils.base_model import BaseModel
|
5 |
+
from .. import logger
|
|
|
6 |
|
7 |
darkfeat_path = Path(__file__).parent / "../../third_party/DarkFeat"
|
8 |
sys.path.append(str(darkfeat_path))
|
hloc/extractors/dedode.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
-
import logging
|
5 |
import torch
|
6 |
from PIL import Image
|
7 |
from ..utils.base_model import BaseModel
|
|
|
8 |
import torchvision.transforms as transforms
|
9 |
|
10 |
dedode_path = Path(__file__).parent / "../../third_party/DeDoDe"
|
@@ -14,8 +14,6 @@ from DeDoDe import dedode_detector_L, dedode_descriptor_B
|
|
14 |
from DeDoDe.utils import to_pixel_coords
|
15 |
|
16 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
17 |
-
logger = logging.getLogger(__name__)
|
18 |
-
|
19 |
|
20 |
class DeDoDe(BaseModel):
|
21 |
default_conf = {
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
|
|
4 |
import torch
|
5 |
from PIL import Image
|
6 |
from ..utils.base_model import BaseModel
|
7 |
+
from .. import logger
|
8 |
import torchvision.transforms as transforms
|
9 |
|
10 |
dedode_path = Path(__file__).parent / "../../third_party/DeDoDe"
|
|
|
14 |
from DeDoDe.utils import to_pixel_coords
|
15 |
|
16 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
|
|
17 |
|
18 |
class DeDoDe(BaseModel):
|
19 |
default_conf = {
|
hloc/extractors/example.py
CHANGED
@@ -2,7 +2,7 @@ import sys
|
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
import torch
|
5 |
-
import
|
6 |
|
7 |
from ..utils.base_model import BaseModel
|
8 |
|
@@ -12,8 +12,6 @@ sys.path.append(str(example_path))
|
|
12 |
# import some modules here
|
13 |
|
14 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
15 |
-
logger = logging.getLogger(__name__)
|
16 |
-
|
17 |
|
18 |
class Example(BaseModel):
|
19 |
# change to your default configs
|
|
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
import torch
|
5 |
+
from .. import logger
|
6 |
|
7 |
from ..utils.base_model import BaseModel
|
8 |
|
|
|
12 |
# import some modules here
|
13 |
|
14 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
|
|
15 |
|
16 |
class Example(BaseModel):
|
17 |
# change to your default configs
|
hloc/extractors/fire_local.py
CHANGED
@@ -1,13 +1,12 @@
|
|
1 |
from pathlib import Path
|
2 |
import subprocess
|
3 |
-
import logging
|
4 |
import sys
|
5 |
import torch
|
6 |
import torchvision.transforms as tvf
|
7 |
|
8 |
from ..utils.base_model import BaseModel
|
|
|
9 |
|
10 |
-
logger = logging.getLogger(__name__)
|
11 |
fire_path = Path(__file__).parent / "../../third_party/fire"
|
12 |
|
13 |
sys.path.append(str(fire_path))
|
|
|
1 |
from pathlib import Path
|
2 |
import subprocess
|
|
|
3 |
import sys
|
4 |
import torch
|
5 |
import torchvision.transforms as tvf
|
6 |
|
7 |
from ..utils.base_model import BaseModel
|
8 |
+
from .. import logger
|
9 |
|
|
|
10 |
fire_path = Path(__file__).parent / "../../third_party/fire"
|
11 |
|
12 |
sys.path.append(str(fire_path))
|
hloc/extractors/netvlad.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
from pathlib import Path
|
2 |
import subprocess
|
3 |
-
import logging
|
4 |
import numpy as np
|
5 |
import torch
|
6 |
import torch.nn as nn
|
@@ -9,8 +8,7 @@ import torchvision.models as models
|
|
9 |
from scipy.io import loadmat
|
10 |
|
11 |
from ..utils.base_model import BaseModel
|
12 |
-
|
13 |
-
logger = logging.getLogger(__name__)
|
14 |
|
15 |
EPS = 1e-6
|
16 |
|
|
|
1 |
from pathlib import Path
|
2 |
import subprocess
|
|
|
3 |
import numpy as np
|
4 |
import torch
|
5 |
import torch.nn as nn
|
|
|
8 |
from scipy.io import loadmat
|
9 |
|
10 |
from ..utils.base_model import BaseModel
|
11 |
+
from .. import logger
|
|
|
12 |
|
13 |
EPS = 1e-6
|
14 |
|
hloc/extractors/rord.py
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
from pathlib import Path
|
3 |
+
import subprocess
|
4 |
+
import torch
|
5 |
+
|
6 |
+
from ..utils.base_model import BaseModel
|
7 |
+
from .. import logger
|
8 |
+
|
9 |
+
rord_path = Path(__file__).parent / "../../third_party/RoRD"
|
10 |
+
sys.path.append(str(rord_path))
|
11 |
+
from lib.model_test import D2Net as _RoRD
|
12 |
+
from lib.pyramid import process_multiscale
|
13 |
+
|
14 |
+
class RoRD(BaseModel):
|
15 |
+
default_conf = {
|
16 |
+
"model_name": "rord.pth",
|
17 |
+
"checkpoint_dir": rord_path / "models",
|
18 |
+
"use_relu": True,
|
19 |
+
"multiscale": False,
|
20 |
+
"max_keypoints": 1024,
|
21 |
+
}
|
22 |
+
required_inputs = ["image"]
|
23 |
+
weight_urls = {
|
24 |
+
"rord.pth": "https://drive.google.com/uc?id=12414ZGKwgPAjNTGtNrlB4VV9l7W76B2o&confirm=t",
|
25 |
+
}
|
26 |
+
proxy = "http://localhost:1080"
|
27 |
+
|
28 |
+
def _init(self, conf):
|
29 |
+
model_path = conf["checkpoint_dir"] / conf["model_name"]
|
30 |
+
link = self.weight_urls[conf["model_name"]]
|
31 |
+
if not model_path.exists():
|
32 |
+
model_path.parent.mkdir(exist_ok=True)
|
33 |
+
cmd_wo_proxy = ["gdown", link, "-O", str(model_path)]
|
34 |
+
cmd = ["gdown", link, "-O", str(model_path), "--proxy", self.proxy]
|
35 |
+
logger.info(
|
36 |
+
f"Downloading the RoRD model with `{cmd_wo_proxy}`."
|
37 |
+
)
|
38 |
+
try:
|
39 |
+
subprocess.run(cmd_wo_proxy, check=True)
|
40 |
+
except subprocess.CalledProcessError as e:
|
41 |
+
logger.info(f"Downloading the RoRD model with `{cmd}`.")
|
42 |
+
try:
|
43 |
+
subprocess.run(cmd, check=True)
|
44 |
+
except subprocess.CalledProcessError as e:
|
45 |
+
logger.error(f"Failed to download the RoRD model.")
|
46 |
+
raise e
|
47 |
+
logger.info("RoRD model loaded.")
|
48 |
+
self.net = _RoRD(
|
49 |
+
model_file=model_path, use_relu=conf["use_relu"], use_cuda=False
|
50 |
+
)
|
51 |
+
|
52 |
+
def _forward(self, data):
|
53 |
+
image = data["image"]
|
54 |
+
image = image.flip(1) # RGB -> BGR
|
55 |
+
norm = image.new_tensor([103.939, 116.779, 123.68])
|
56 |
+
image = image * 255 - norm.view(1, 3, 1, 1) # caffe normalization
|
57 |
+
|
58 |
+
if self.conf["multiscale"]:
|
59 |
+
keypoints, scores, descriptors = process_multiscale(image, self.net)
|
60 |
+
else:
|
61 |
+
keypoints, scores, descriptors = process_multiscale(
|
62 |
+
image, self.net, scales=[1]
|
63 |
+
)
|
64 |
+
keypoints = keypoints[:, [1, 0]] # (x, y) and remove the scale
|
65 |
+
|
66 |
+
idxs = scores.argsort()[-self.conf["max_keypoints"] or None :]
|
67 |
+
keypoints = keypoints[idxs, :2]
|
68 |
+
descriptors = descriptors[idxs]
|
69 |
+
scores = scores[idxs]
|
70 |
+
|
71 |
+
return {
|
72 |
+
"keypoints": torch.from_numpy(keypoints)[None],
|
73 |
+
"scores": torch.from_numpy(scores)[None],
|
74 |
+
"descriptors": torch.from_numpy(descriptors.T)[None],
|
75 |
+
}
|
hloc/matchers/aspanformer.py
CHANGED
@@ -4,9 +4,8 @@ from ..utils.base_model import BaseModel
|
|
4 |
from ..utils import do_system
|
5 |
from pathlib import Path
|
6 |
import subprocess
|
7 |
-
import logging
|
8 |
|
9 |
-
|
10 |
|
11 |
sys.path.append(str(Path(__file__).parent / "../../third_party"))
|
12 |
from ASpanFormer.src.ASpanFormer.aspanformer import ASpanFormer as _ASpanFormer
|
@@ -77,7 +76,9 @@ class ASpanFormer(BaseModel):
|
|
77 |
|
78 |
# update: match threshold
|
79 |
_config["aspan"]["match_coarse"]["thr"] = conf["match_threshold"]
|
80 |
-
_config["aspan"]["match_coarse"]["skh_iters"] = conf[
|
|
|
|
|
81 |
|
82 |
self.net = _ASpanFormer(config=_config["aspan"])
|
83 |
weight_path = model_path
|
|
|
4 |
from ..utils import do_system
|
5 |
from pathlib import Path
|
6 |
import subprocess
|
|
|
7 |
|
8 |
+
from .. import logger
|
9 |
|
10 |
sys.path.append(str(Path(__file__).parent / "../../third_party"))
|
11 |
from ASpanFormer.src.ASpanFormer.aspanformer import ASpanFormer as _ASpanFormer
|
|
|
76 |
|
77 |
# update: match threshold
|
78 |
_config["aspan"]["match_coarse"]["thr"] = conf["match_threshold"]
|
79 |
+
_config["aspan"]["match_coarse"]["skh_iters"] = conf[
|
80 |
+
"sinkhorn_iterations"
|
81 |
+
]
|
82 |
|
83 |
self.net = _ASpanFormer(config=_config["aspan"])
|
84 |
weight_path = model_path
|
hloc/matchers/dkm.py
CHANGED
@@ -3,16 +3,14 @@ from pathlib import Path
|
|
3 |
import torch
|
4 |
from PIL import Image
|
5 |
import subprocess
|
6 |
-
import logging
|
7 |
from ..utils.base_model import BaseModel
|
|
|
8 |
|
9 |
sys.path.append(str(Path(__file__).parent / "../../third_party"))
|
10 |
from DKM.dkm import DKMv3_outdoor
|
11 |
|
12 |
dkm_path = Path(__file__).parent / "../../third_party/DKM"
|
13 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
14 |
-
logger = logging.getLogger(__name__)
|
15 |
-
|
16 |
|
17 |
class DKMv3(BaseModel):
|
18 |
default_conf = {
|
|
|
3 |
import torch
|
4 |
from PIL import Image
|
5 |
import subprocess
|
|
|
6 |
from ..utils.base_model import BaseModel
|
7 |
+
from .. import logger
|
8 |
|
9 |
sys.path.append(str(Path(__file__).parent / "../../third_party"))
|
10 |
from DKM.dkm import DKMv3_outdoor
|
11 |
|
12 |
dkm_path = Path(__file__).parent / "../../third_party/DKM"
|
13 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
|
|
14 |
|
15 |
class DKMv3(BaseModel):
|
16 |
default_conf = {
|
hloc/matchers/gluestick.py
CHANGED
@@ -1,11 +1,9 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
-
import logging
|
5 |
import torch
|
6 |
from ..utils.base_model import BaseModel
|
7 |
-
|
8 |
-
logger = logging.getLogger(__name__)
|
9 |
|
10 |
gluestick_path = Path(__file__).parent / "../../third_party/GlueStick"
|
11 |
sys.path.append(str(gluestick_path))
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
|
|
4 |
import torch
|
5 |
from ..utils.base_model import BaseModel
|
6 |
+
from .. import logger
|
|
|
7 |
|
8 |
gluestick_path = Path(__file__).parent / "../../third_party/GlueStick"
|
9 |
sys.path.append(str(gluestick_path))
|
hloc/matchers/lightglue.py
CHANGED
@@ -1,9 +1,8 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
-
import logging
|
4 |
from ..utils.base_model import BaseModel
|
|
|
5 |
|
6 |
-
logger = logging.getLogger(__name__)
|
7 |
lightglue_path = Path(__file__).parent / "../../third_party/LightGlue"
|
8 |
sys.path.append(str(lightglue_path))
|
9 |
from lightglue import LightGlue as LG
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
|
|
3 |
from ..utils.base_model import BaseModel
|
4 |
+
from .. import logger
|
5 |
|
|
|
6 |
lightglue_path = Path(__file__).parent / "../../third_party/LightGlue"
|
7 |
sys.path.append(str(lightglue_path))
|
8 |
from lightglue import LightGlue as LG
|
hloc/matchers/roma.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
-
import logging
|
5 |
import torch
|
6 |
from PIL import Image
|
7 |
from ..utils.base_model import BaseModel
|
|
|
8 |
|
9 |
roma_path = Path(__file__).parent / "../../third_party/Roma"
|
10 |
sys.path.append(str(roma_path))
|
@@ -12,8 +12,6 @@ sys.path.append(str(roma_path))
|
|
12 |
from roma.models.model_zoo.roma_models import roma_model
|
13 |
|
14 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
15 |
-
logger = logging.getLogger(__name__)
|
16 |
-
|
17 |
|
18 |
class Roma(BaseModel):
|
19 |
default_conf = {
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
|
|
4 |
import torch
|
5 |
from PIL import Image
|
6 |
from ..utils.base_model import BaseModel
|
7 |
+
from .. import logger
|
8 |
|
9 |
roma_path = Path(__file__).parent / "../../third_party/Roma"
|
10 |
sys.path.append(str(roma_path))
|
|
|
12 |
from roma.models.model_zoo.roma_models import roma_model
|
13 |
|
14 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
|
|
15 |
|
16 |
class Roma(BaseModel):
|
17 |
default_conf = {
|
hloc/matchers/sgmnet.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
4 |
-
import logging
|
5 |
import torch
|
6 |
from PIL import Image
|
7 |
from collections import OrderedDict, namedtuple
|
8 |
from ..utils.base_model import BaseModel
|
9 |
from ..utils import do_system
|
|
|
10 |
|
11 |
sgmnet_path = Path(__file__).parent / "../../third_party/SGMNet"
|
12 |
sys.path.append(str(sgmnet_path))
|
@@ -14,7 +14,6 @@ sys.path.append(str(sgmnet_path))
|
|
14 |
from sgmnet import matcher as SGM_Model
|
15 |
|
16 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
17 |
-
logger = logging.getLogger(__name__)
|
18 |
|
19 |
|
20 |
class SGMNet(BaseModel):
|
|
|
1 |
import sys
|
2 |
from pathlib import Path
|
3 |
import subprocess
|
|
|
4 |
import torch
|
5 |
from PIL import Image
|
6 |
from collections import OrderedDict, namedtuple
|
7 |
from ..utils.base_model import BaseModel
|
8 |
from ..utils import do_system
|
9 |
+
from .. import logger
|
10 |
|
11 |
sgmnet_path = Path(__file__).parent / "../../third_party/SGMNet"
|
12 |
sys.path.append(str(sgmnet_path))
|
|
|
14 |
from sgmnet import matcher as SGM_Model
|
15 |
|
16 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
17 |
|
18 |
|
19 |
class SGMNet(BaseModel):
|
hloc/matchers/sold2.py
CHANGED
@@ -4,18 +4,13 @@ from ..utils.base_model import BaseModel
|
|
4 |
import torch
|
5 |
|
6 |
from ..utils.base_model import BaseModel
|
|
|
|
|
7 |
|
8 |
sold2_path = Path(__file__).parent / "../../third_party/SOLD2"
|
9 |
sys.path.append(str(sold2_path))
|
10 |
|
11 |
from sold2.model.line_matcher import LineMatcher
|
12 |
-
from sold2.misc.visualize_util import (
|
13 |
-
plot_images,
|
14 |
-
plot_lines,
|
15 |
-
plot_line_matches,
|
16 |
-
plot_color_line_matches,
|
17 |
-
plot_keypoints,
|
18 |
-
)
|
19 |
|
20 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
21 |
|
@@ -36,9 +31,21 @@ class SOLD2(BaseModel):
|
|
36 |
"image1",
|
37 |
]
|
38 |
|
|
|
|
|
|
|
39 |
# Initialize the line matcher
|
40 |
def _init(self, conf):
|
41 |
checkpoint_path = conf["checkpoint_dir"] / conf["weights"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
mode = "dynamic" # 'dynamic' or 'static'
|
43 |
match_config = {
|
44 |
"model_cfg": {
|
|
|
4 |
import torch
|
5 |
|
6 |
from ..utils.base_model import BaseModel
|
7 |
+
from .. import logger
|
8 |
+
import subprocess
|
9 |
|
10 |
sold2_path = Path(__file__).parent / "../../third_party/SOLD2"
|
11 |
sys.path.append(str(sold2_path))
|
12 |
|
13 |
from sold2.model.line_matcher import LineMatcher
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
16 |
|
|
|
31 |
"image1",
|
32 |
]
|
33 |
|
34 |
+
weight_urls = {
|
35 |
+
"sold2_wireframe.tar": "https://www.polybox.ethz.ch/index.php/s/blOrW89gqSLoHOk/download",
|
36 |
+
}
|
37 |
# Initialize the line matcher
|
38 |
def _init(self, conf):
|
39 |
checkpoint_path = conf["checkpoint_dir"] / conf["weights"]
|
40 |
+
|
41 |
+
# Download the model.
|
42 |
+
if not checkpoint_path.exists():
|
43 |
+
checkpoint_path.parent.mkdir(exist_ok=True)
|
44 |
+
link = self.weight_urls[conf["weights"]]
|
45 |
+
cmd = ["wget", link, "-O", str(checkpoint_path)]
|
46 |
+
logger.info(f"Downloading the SOLD2 model with `{cmd}`.")
|
47 |
+
subprocess.run(cmd, check=True)
|
48 |
+
|
49 |
mode = "dynamic" # 'dynamic' or 'static'
|
50 |
match_config = {
|
51 |
"model_cfg": {
|
hloc/utils/__init__.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import os
|
2 |
import logging
|
3 |
-
|
4 |
-
|
5 |
|
6 |
|
7 |
def do_system(cmd, verbose=False):
|
|
|
1 |
import os
|
2 |
import logging
|
3 |
+
import sys
|
4 |
+
from .. import logger
|
5 |
|
6 |
|
7 |
def do_system(cmd, verbose=False):
|
third_party/RoRD/LICENSE
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License
|
2 |
+
|
3 |
+
By exercising the Licensed Rights (defined below), You accept and agree to be
|
4 |
+
bound by the terms and conditions of this Creative Commons
|
5 |
+
Attribution-NonCommercial-NoDerivatives 4.0 International Public License
|
6 |
+
("Public License"). To the extent this Public License may be interpreted as a
|
7 |
+
contract, You are granted the Licensed Rights in consideration of Your
|
8 |
+
acceptance of these terms and conditions, and the Licensor grants You such
|
9 |
+
rights in consideration of benefits the Licensor receives from making the
|
10 |
+
Licensed Material available under these terms and conditions.
|
11 |
+
|
12 |
+
Section 1 – Definitions.
|
13 |
+
|
14 |
+
a. Adapted Material means material subject to Copyright and Similar Rights
|
15 |
+
that is derived from or based upon the Licensed Material and in which
|
16 |
+
the Licensed Material is translated, altered, arranged, transformed, or
|
17 |
+
otherwise modified in a manner requiring permission under the Copyright
|
18 |
+
and Similar Rights held by the Licensor. For purposes of this Public
|
19 |
+
License, where the Licensed Material is a musical work, performance, or
|
20 |
+
sound recording, Adapted Material is always produced where the Licensed
|
21 |
+
Material is synched in timed relation with a moving image.
|
22 |
+
b. Copyright and Similar Rights means copyright and/or similar rights
|
23 |
+
closely related to copyright including, without limitation,
|
24 |
+
performance, broadcast, sound recording, and Sui Generis Database
|
25 |
+
Rights, without regard to how the rights are labeled or categorized.
|
26 |
+
For purposes of this Public License, the rights specified in Section
|
27 |
+
2(b)(1)-(2) are not Copyright and Similar Rights.
|
28 |
+
c. Effective Technological Measures means those measures that, in the
|
29 |
+
absence of proper authority, may not be circumvented under laws
|
30 |
+
fulfilling obligations under Article 11 of the WIPO Copyright Treaty
|
31 |
+
adopted on December 20, 1996, and/or similar international agreements.
|
32 |
+
d. Exceptions and Limitations means fair use, fair dealing, and/or any
|
33 |
+
other exception or limitation to Copyright and Similar Rights that
|
34 |
+
applies to Your use of the Licensed Material.
|
35 |
+
e. Licensed Material means the artistic or literary work, database, or
|
36 |
+
other material to which the Licensor applied this Public License.
|
37 |
+
f. Licensed Rights means the rights granted to You subject to the terms
|
38 |
+
and conditions of this Public License, which are limited to all
|
39 |
+
Copyright and Similar Rights that apply to Your use of the Licensed
|
40 |
+
Material and that the Licensor has authority to license.
|
41 |
+
g. Licensor means the individual(s) or entity(ies) granting rights under
|
42 |
+
this Public License.
|
43 |
+
h. NonCommercial means not primarily intended for or directed towards
|
44 |
+
commercial advantage or monetary compensation. For purposes of this
|
45 |
+
Public License, the exchange of the Licensed Material for other
|
46 |
+
material subject to Copyright and Similar Rights by digital
|
47 |
+
file-sharing or similar means is NonCommercial provided there is no
|
48 |
+
payment of monetary compensation in connection with the exchange.
|
49 |
+
i. Share means to provide material to the public by any means or process
|
50 |
+
that requires permission under the Licensed Rights, such as
|
51 |
+
reproduction, public display, public performance, distribution,
|
52 |
+
dissemination, communication, or importation, and to make material
|
53 |
+
available to the public including in ways that members of the public
|
54 |
+
may access the material from a place and at a time individually chosen
|
55 |
+
by them.
|
56 |
+
j. Sui Generis Database Rights means rights other than copyright resulting
|
57 |
+
from Directive 96/9/EC of the European Parliament and of the Council of
|
58 |
+
11 March 1996 on the legal protection of databases, as amended and/or
|
59 |
+
succeeded, as well as other essentially equivalent rights anywhere in
|
60 |
+
the world.
|
61 |
+
k. You means the individual or entity exercising the Licensed Rights under
|
62 |
+
this Public License. Your has a corresponding meaning.
|
63 |
+
|
64 |
+
Section 2 – Scope.
|
65 |
+
|
66 |
+
a. License grant.
|
67 |
+
1. Subject to the terms and conditions of this Public License, the
|
68 |
+
Licensor hereby grants You a worldwide, royalty-free,
|
69 |
+
non-sublicensable, non-exclusive, irrevocable license to exercise
|
70 |
+
the Licensed Rights in the Licensed Material to:
|
71 |
+
A. reproduce and Share the Licensed Material, in whole or in part,
|
72 |
+
for NonCommercial purposes only; and
|
73 |
+
B. produce and reproduce, but not Share, Adapted Material for
|
74 |
+
NonCommercial purposes only.
|
75 |
+
2. Exceptions and Limitations. For the avoidance of doubt, where
|
76 |
+
Exceptions and Limitations apply to Your use, this Public License
|
77 |
+
does not apply, and You do not need to comply with its terms and
|
78 |
+
conditions.
|
79 |
+
3. Term. The term of this Public License is specified in Section 6(a).
|
80 |
+
4. Media and formats; technical modifications allowed. The Licensor
|
81 |
+
authorizes You to exercise the Licensed Rights in all media and
|
82 |
+
formats whether now known or hereafter created, and to make
|
83 |
+
technical modifications necessary to do so. The Licensor waives
|
84 |
+
and/or agrees not to assert any right or authority to forbid You
|
85 |
+
from making technical modifications necessary to exercise the
|
86 |
+
Licensed Rights, including technical modifications necessary to
|
87 |
+
circumvent Effective Technological Measures. For purposes of this
|
88 |
+
Public License, simply making modifications authorized by this
|
89 |
+
Section 2(a)(4) never produces Adapted Material.
|
90 |
+
5. Downstream recipients.
|
91 |
+
A. Offer from the Licensor – Licensed Material. Every recipient of
|
92 |
+
the Licensed Material automatically receives an offer from the
|
93 |
+
Licensor to exercise the Licensed Rights under the terms and
|
94 |
+
conditions of this Public License.
|
95 |
+
B. No downstream restrictions. You may not offer or impose any
|
96 |
+
additional or different terms or conditions on, or apply any
|
97 |
+
Effective Technological Measures to, the Licensed Material if
|
98 |
+
doing so restricts exercise of the Licensed Rights by any
|
99 |
+
recipient of the Licensed Material.
|
100 |
+
6. No endorsement. Nothing in this Public License constitutes or may
|
101 |
+
be construed as permission to assert or imply that You are, or that
|
102 |
+
Your use of the Licensed Material is, connected with, or sponsored,
|
103 |
+
endorsed, or granted official status by, the Licensor or others
|
104 |
+
designated to receive attribution as provided in Section
|
105 |
+
3(a)(1)(A)(i).
|
106 |
+
|
107 |
+
b. Other rights.
|
108 |
+
1. Moral rights, such as the right of integrity, are not licensed
|
109 |
+
under this Public License, nor are publicity, privacy, and/or other
|
110 |
+
similar personality rights; however, to the extent possible, the
|
111 |
+
Licensor waives and/or agrees not to assert any such rights held by
|
112 |
+
the Licensor to the limited extent necessary to allow You to
|
113 |
+
exercise the Licensed Rights, but not otherwise.
|
114 |
+
2. Patent and trademark rights are not licensed under this Public
|
115 |
+
License.
|
116 |
+
3. To the extent possible, the Licensor waives any right to collect
|
117 |
+
royalties from You for the exercise of the Licensed Rights, whether
|
118 |
+
directly or through a collecting society under any voluntary or
|
119 |
+
waivable statutory or compulsory licensing scheme. In all other
|
120 |
+
cases the Licensor expressly reserves any right to collect such
|
121 |
+
royalties, including when the Licensed Material is used other than
|
122 |
+
for NonCommercial purposes.
|
123 |
+
|
124 |
+
Section 3 – License Conditions.
|
125 |
+
|
126 |
+
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
|
127 |
+
|
128 |
+
a. Attribution.
|
129 |
+
|
130 |
+
1. If You Share the Licensed Material, You must:
|
131 |
+
A. retain the following if it is supplied by the Licensor with the
|
132 |
+
Licensed Material:
|
133 |
+
i. identification of the creator(s) of the Licensed Material
|
134 |
+
and any others designated to receive attribution, in any
|
135 |
+
reasonable manner requested by the Licensor (including by
|
136 |
+
pseudonym if designated);
|
137 |
+
ii. a copyright notice;
|
138 |
+
iii. a notice that refers to this Public License;
|
139 |
+
iv. a notice that refers to the disclaimer of warranties;
|
140 |
+
v. a URI or hyperlink to the Licensed Material to the extent
|
141 |
+
reasonably practicable;
|
142 |
+
B. indicate if You modified the Licensed Material and retain an
|
143 |
+
indication of any previous modifications; and
|
144 |
+
C. indicate the Licensed Material is licensed under this Public
|
145 |
+
License, and include the text of, or the URI or hyperlink to,
|
146 |
+
this Public License.
|
147 |
+
|
148 |
+
For the avoidance of doubt, You do not have permission under this
|
149 |
+
Public License to Share Adapted Material.
|
150 |
+
|
151 |
+
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable
|
152 |
+
manner based on the medium, means, and context in which You Share
|
153 |
+
the Licensed Material. For example, it may be reasonable to satisfy
|
154 |
+
the conditions by providing a URI or hyperlink to a resource that
|
155 |
+
includes the required information.
|
156 |
+
3. If requested by the Licensor, You must remove any of the
|
157 |
+
information required by Section 3(a)(1)(A) to the extent reasonably
|
158 |
+
practicable.
|
159 |
+
|
160 |
+
Section 4 – Sui Generis Database Rights.
|
161 |
+
|
162 |
+
Where the Licensed Rights include Sui Generis Database Rights that apply to
|
163 |
+
Your use of the Licensed Material:
|
164 |
+
|
165 |
+
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to
|
166 |
+
extract, reuse, reproduce, and Share all or a substantial portion of
|
167 |
+
the contents of the database for NonCommercial purposes only and
|
168 |
+
provided You do not Share Adapted Material;
|
169 |
+
b. if You include all or a substantial portion of the database contents in
|
170 |
+
a database in which You have Sui Generis Database Rights, then the
|
171 |
+
database in which You have Sui Generis Database Rights (but not its
|
172 |
+
individual contents) is Adapted Material; and
|
173 |
+
c. You must comply with the conditions in Section 3(a) if You Share all or
|
174 |
+
a substantial portion of the contents of the database.
|
175 |
+
|
176 |
+
For the avoidance of doubt, this Section 4 supplements and does not replace
|
177 |
+
Your obligations under this Public License where the Licensed Rights include
|
178 |
+
other Copyright and Similar Rights.
|
179 |
+
|
180 |
+
Section 5 – Disclaimer of Warranties and Limitation of Liability.
|
181 |
+
|
182 |
+
a. Unless otherwise separately undertaken by the Licensor, to the extent
|
183 |
+
possible, the Licensor offers the Licensed Material as-is and
|
184 |
+
as-available, and makes no representations or warranties of any kind
|
185 |
+
concerning the Licensed Material, whether express, implied, statutory,
|
186 |
+
or other. This includes, without limitation, warranties of title,
|
187 |
+
merchantability, fitness for a particular purpose, non-infringement,
|
188 |
+
absence of latent or other defects, accuracy, or the presence or
|
189 |
+
absence of errors, whether or not known or discoverable. Where
|
190 |
+
disclaimers of warranties are not allowed in full or in part, this
|
191 |
+
disclaimer may not apply to You.
|
192 |
+
b. To the extent possible, in no event will the Licensor be liable to You
|
193 |
+
on any legal theory (including, without limitation, negligence) or
|
194 |
+
otherwise for any direct, special, indirect, incidental, consequential,
|
195 |
+
punitive, exemplary, or other losses, costs, expenses, or damages
|
196 |
+
arising out of this Public License or use of the Licensed Material,
|
197 |
+
even if the Licensor has been advised of the possibility of such
|
198 |
+
losses, costs, expenses, or damages. Where a limitation of liability is
|
199 |
+
not allowed in full or in part, this limitation may not apply to You.
|
200 |
+
c. The disclaimer of warranties and limitation of liability provided above
|
201 |
+
shall be interpreted in a manner that, to the extent possible, most
|
202 |
+
closely approximates an absolute disclaimer and waiver of all
|
203 |
+
liability.
|
204 |
+
|
205 |
+
Section 6 – Term and Termination.
|
206 |
+
|
207 |
+
a. This Public License applies for the term of the Copyright and Similar
|
208 |
+
Rights licensed here. However, if You fail to comply with this Public
|
209 |
+
License, then Your rights under this Public License terminate
|
210 |
+
automatically.
|
211 |
+
b. Where Your right to use the Licensed Material has terminated under
|
212 |
+
Section 6(a), it reinstates:
|
213 |
+
1. automatically as of the date the violation is cured, provided it is
|
214 |
+
cured within 30 days of Your discovery of the violation; or
|
215 |
+
2. upon express reinstatement by the Licensor.
|
216 |
+
|
217 |
+
For the avoidance of doubt, this Section 6(b) does not affect any right
|
218 |
+
the Licensor may have to seek remedies for Your violations of this
|
219 |
+
Public License.
|
220 |
+
|
221 |
+
c. For the avoidance of doubt, the Licensor may also offer the Licensed
|
222 |
+
Material under separate terms or conditions or stop distributing the
|
223 |
+
Licensed Material at any time; however, doing so will not terminate
|
224 |
+
this Public License.
|
225 |
+
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
|
226 |
+
|
227 |
+
Section 7 – Other Terms and Conditions.
|
228 |
+
|
229 |
+
a. The Licensor shall not be bound by any additional or different terms or
|
230 |
+
conditions communicated by You unless expressly agreed.
|
231 |
+
b. Any arrangements, understandings, or agreements regarding the Licensed
|
232 |
+
Material not stated herein are separate from and independent of the
|
233 |
+
terms and conditions of this Public License.
|
234 |
+
|
235 |
+
Section 8 – Interpretation.
|
236 |
+
|
237 |
+
a. For the avoidance of doubt, this Public License does not, and shall not
|
238 |
+
be interpreted to, reduce, limit, restrict, or impose conditions on any
|
239 |
+
use of the Licensed Material that could lawfully be made without
|
240 |
+
permission under this Public License.
|
241 |
+
b. To the extent possible, if any provision of this Public License is
|
242 |
+
deemed unenforceable, it shall be automatically reformed to the minimum
|
243 |
+
extent necessary to make it enforceable. If the provision cannot be
|
244 |
+
reformed, it shall be severed from this Public License without
|
245 |
+
affecting the enforceability of the remaining terms and conditions.
|
246 |
+
c. No term or condition of this Public License will be waived and no
|
247 |
+
failure to comply consented to unless expressly agreed to by the Licensor.
|
248 |
+
d. Nothing in this Public License constitutes or may be interpreted as a
|
249 |
+
limitation upon, or waiver of, any privileges and immunities that apply
|
250 |
+
to the Licensor or You, including from the legal processes of any
|
251 |
+
jurisdiction or authority.
|
third_party/RoRD/assets/register_ortho.jpg
ADDED
Git LFS Details
|
third_party/RoRD/assets/register_persp.jpg
ADDED
Git LFS Details
|
third_party/RoRD/assets/register_pointcloud.jpg
ADDED
Git LFS Details
|
third_party/RoRD/assets/rord_evalRT.jpg
ADDED
Git LFS Details
|
third_party/RoRD/assets/rord_extract.jpg
ADDED
Git LFS Details
|
third_party/RoRD/assets/sift_extract.jpg
ADDED
Git LFS Details
|
third_party/RoRD/assets/teaser2.jpg
ADDED
Git LFS Details
|
third_party/RoRD/configs/camera.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
382.1996765136719 381.8395690917969 312.7102355957031 247.72047424316406 1000.0
|
2 |
+
|
3 |
+
|
third_party/RoRD/configs/train_scenes.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
temple_nara_japan
|
2 |
+
brandenburg_gate
|
3 |
+
taj_mahal
|
4 |
+
buckingham_palace
|
5 |
+
grand_place_brussels
|
6 |
+
hagia_sophia_interior
|
7 |
+
westminster_abbey
|
third_party/RoRD/configs/train_scenes_small.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
brandenburg_gate
|
third_party/RoRD/demo/__init__.py
ADDED
File without changes
|
third_party/RoRD/demo/depth/depth1_1.png
ADDED
Git LFS Details
|
third_party/RoRD/demo/depth/depth1_2.png
ADDED
Git LFS Details
|
third_party/RoRD/demo/depth/depth2_1.png
ADDED
Git LFS Details
|
third_party/RoRD/demo/depth/depth2_2.png
ADDED
Git LFS Details
|
third_party/RoRD/demo/depth/depth3_1.png
ADDED
Git LFS Details
|
third_party/RoRD/demo/depth/depth3_2.png
ADDED
Git LFS Details
|
third_party/RoRD/demo/register.py
ADDED
@@ -0,0 +1,265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import copy
|
3 |
+
import argparse
|
4 |
+
import os, sys
|
5 |
+
import open3d as o3d
|
6 |
+
from sys import argv
|
7 |
+
from PIL import Image
|
8 |
+
import math
|
9 |
+
import cv2
|
10 |
+
import torch
|
11 |
+
|
12 |
+
sys.path.append("../")
|
13 |
+
from lib.extractMatchTop import getPerspKeypoints, getPerspKeypointsEnsemble, siftMatching
|
14 |
+
from lib.model_test import D2Net
|
15 |
+
|
16 |
+
#### Cuda ####
|
17 |
+
use_cuda = torch.cuda.is_available()
|
18 |
+
device = torch.device('cuda:0' if use_cuda else 'cpu')
|
19 |
+
|
20 |
+
#### Argument Parsing ####
|
21 |
+
parser = argparse.ArgumentParser(description='RoRD ICP evaluation')
|
22 |
+
|
23 |
+
parser.add_argument(
|
24 |
+
'--rgb1', type=str, default = 'rgb/rgb2_1.jpg',
|
25 |
+
help='path to the rgb image1'
|
26 |
+
)
|
27 |
+
parser.add_argument(
|
28 |
+
'--rgb2', type=str, default = 'rgb/rgb2_2.jpg',
|
29 |
+
help='path to the rgb image2'
|
30 |
+
)
|
31 |
+
|
32 |
+
parser.add_argument(
|
33 |
+
'--depth1', type=str, default = 'depth/depth2_1.png',
|
34 |
+
help='path to the depth image1'
|
35 |
+
)
|
36 |
+
|
37 |
+
parser.add_argument(
|
38 |
+
'--depth2', type=str, default = 'depth/depth2_2.png',
|
39 |
+
help='path to the depth image2'
|
40 |
+
)
|
41 |
+
|
42 |
+
parser.add_argument(
|
43 |
+
'--model_rord', type=str, default = '../models/rord.pth',
|
44 |
+
help='path to the RoRD model for evaluation'
|
45 |
+
)
|
46 |
+
|
47 |
+
parser.add_argument(
|
48 |
+
'--model_d2', type=str,
|
49 |
+
help='path to the vanilla D2-Net model for evaluation'
|
50 |
+
)
|
51 |
+
|
52 |
+
parser.add_argument(
|
53 |
+
'--model_ens', action='store_true',
|
54 |
+
help='ensemble model of RoRD + D2-Net'
|
55 |
+
)
|
56 |
+
|
57 |
+
parser.add_argument(
|
58 |
+
'--sift', action='store_true',
|
59 |
+
help='Sift'
|
60 |
+
)
|
61 |
+
|
62 |
+
parser.add_argument(
|
63 |
+
'--camera_file', type=str, default='../configs/camera.txt',
|
64 |
+
help='path to the camera intrinsics file. In order: focal_x, focal_y, center_x, center_y, scaling_factor.'
|
65 |
+
)
|
66 |
+
|
67 |
+
parser.add_argument(
|
68 |
+
'--viz3d', action='store_true',
|
69 |
+
help='visualize the pointcloud registrations'
|
70 |
+
)
|
71 |
+
|
72 |
+
args = parser.parse_args()
|
73 |
+
|
74 |
+
if args.model_ens: # Change default paths accordingly for ensemble
|
75 |
+
model1_ens = '../../models/rord.pth'
|
76 |
+
model2_ens = '../../models/d2net.pth'
|
77 |
+
|
78 |
+
def draw_registration_result(source, target, transformation):
|
79 |
+
source_temp = copy.deepcopy(source)
|
80 |
+
target_temp = copy.deepcopy(target)
|
81 |
+
source_temp.transform(transformation)
|
82 |
+
|
83 |
+
target_temp += source_temp
|
84 |
+
# print("Saved registered PointCloud.")
|
85 |
+
# o3d.io.write_point_cloud("registered.pcd", target_temp)
|
86 |
+
|
87 |
+
trgSph.append(source_temp); trgSph.append(target_temp)
|
88 |
+
axis1 = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5, origin=[0, 0, 0])
|
89 |
+
axis2 = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5, origin=[0, 0, 0])
|
90 |
+
axis2.transform(transformation)
|
91 |
+
trgSph.append(axis1); trgSph.append(axis2)
|
92 |
+
print("Showing registered PointCloud.")
|
93 |
+
o3d.visualization.draw_geometries(trgSph)
|
94 |
+
|
95 |
+
|
96 |
+
def readDepth(depthFile):
|
97 |
+
depth = Image.open(depthFile)
|
98 |
+
if depth.mode != "I":
|
99 |
+
raise Exception("Depth image is not in intensity format")
|
100 |
+
|
101 |
+
return np.asarray(depth)
|
102 |
+
|
103 |
+
def readCamera(camera):
|
104 |
+
with open (camera, "rt") as file:
|
105 |
+
contents = file.read().split()
|
106 |
+
|
107 |
+
focalX = float(contents[0])
|
108 |
+
focalY = float(contents[1])
|
109 |
+
centerX = float(contents[2])
|
110 |
+
centerY = float(contents[3])
|
111 |
+
scalingFactor = float(contents[4])
|
112 |
+
|
113 |
+
return focalX, focalY, centerX, centerY, scalingFactor
|
114 |
+
|
115 |
+
def getPointCloud(rgbFile, depthFile, pts):
|
116 |
+
thresh = 15.0
|
117 |
+
|
118 |
+
depth = readDepth(depthFile)
|
119 |
+
rgb = Image.open(rgbFile)
|
120 |
+
|
121 |
+
points = []
|
122 |
+
colors = []
|
123 |
+
|
124 |
+
corIdx = [-1]*len(pts)
|
125 |
+
corPts = [None]*len(pts)
|
126 |
+
ptIdx = 0
|
127 |
+
|
128 |
+
for v in range(depth.shape[0]):
|
129 |
+
for u in range(depth.shape[1]):
|
130 |
+
Z = depth[v, u] / scalingFactor
|
131 |
+
if Z==0: continue
|
132 |
+
if (Z > thresh): continue
|
133 |
+
|
134 |
+
X = (u - centerX) * Z / focalX
|
135 |
+
Y = (v - centerY) * Z / focalY
|
136 |
+
|
137 |
+
points.append((X, Y, Z))
|
138 |
+
colors.append(rgb.getpixel((u, v)))
|
139 |
+
|
140 |
+
if((u, v) in pts):
|
141 |
+
# print("Point found.")
|
142 |
+
index = pts.index((u, v))
|
143 |
+
corIdx[index] = ptIdx
|
144 |
+
corPts[index] = (X, Y, Z)
|
145 |
+
|
146 |
+
ptIdx = ptIdx+1
|
147 |
+
|
148 |
+
points = np.asarray(points)
|
149 |
+
colors = np.asarray(colors)
|
150 |
+
|
151 |
+
pcd = o3d.geometry.PointCloud()
|
152 |
+
pcd.points = o3d.utility.Vector3dVector(points)
|
153 |
+
pcd.colors = o3d.utility.Vector3dVector(colors/255)
|
154 |
+
|
155 |
+
return pcd, corIdx, corPts
|
156 |
+
|
157 |
+
|
158 |
+
def convertPts(A):
|
159 |
+
X = A[0]; Y = A[1]
|
160 |
+
|
161 |
+
x = []; y = []
|
162 |
+
|
163 |
+
for i in range(len(X)):
|
164 |
+
x.append(int(float(X[i])))
|
165 |
+
|
166 |
+
for i in range(len(Y)):
|
167 |
+
y.append(int(float(Y[i])))
|
168 |
+
|
169 |
+
pts = []
|
170 |
+
for i in range(len(x)):
|
171 |
+
pts.append((x[i], y[i]))
|
172 |
+
|
173 |
+
return pts
|
174 |
+
|
175 |
+
|
176 |
+
def getSphere(pts):
|
177 |
+
sphs = []
|
178 |
+
|
179 |
+
for ele in pts:
|
180 |
+
if(ele is not None):
|
181 |
+
sphere = o3d.geometry.TriangleMesh.create_sphere(radius=0.03)
|
182 |
+
sphere.paint_uniform_color([0.9, 0.2, 0])
|
183 |
+
|
184 |
+
trans = np.identity(4)
|
185 |
+
trans[0, 3] = ele[0]
|
186 |
+
trans[1, 3] = ele[1]
|
187 |
+
trans[2, 3] = ele[2]
|
188 |
+
|
189 |
+
sphere.transform(trans)
|
190 |
+
sphs.append(sphere)
|
191 |
+
|
192 |
+
return sphs
|
193 |
+
|
194 |
+
|
195 |
+
def get3dCor(src, trg):
|
196 |
+
corr = []
|
197 |
+
|
198 |
+
for sId, tId in zip(src, trg):
|
199 |
+
if(sId != -1 and tId != -1):
|
200 |
+
corr.append((sId, tId))
|
201 |
+
|
202 |
+
corr = np.asarray(corr)
|
203 |
+
|
204 |
+
return corr
|
205 |
+
|
206 |
+
if __name__ == "__main__":
|
207 |
+
|
208 |
+
focalX, focalY, centerX, centerY, scalingFactor = readCamera(args.camera_file)
|
209 |
+
|
210 |
+
rgb_name_src = os.path.basename(args.rgb1)
|
211 |
+
H_name_src = os.path.splitext(rgb_name_src)[0] + '.npy'
|
212 |
+
srcH = os.path.join(os.path.dirname(args.rgb1), H_name_src)
|
213 |
+
rgb_name_trg = os.path.basename(args.rgb2)
|
214 |
+
H_name_trg = os.path.splitext(rgb_name_trg)[0] + '.npy'
|
215 |
+
trgH = os.path.join(os.path.dirname(args.rgb2), H_name_trg)
|
216 |
+
|
217 |
+
use_cuda = torch.cuda.is_available()
|
218 |
+
device = torch.device('cuda:0' if use_cuda else 'cpu')
|
219 |
+
model1 = D2Net(model_file=args.model_d2)
|
220 |
+
model1 = model1.to(device)
|
221 |
+
model2 = D2Net(model_file=args.model_rord)
|
222 |
+
model2 = model2.to(device)
|
223 |
+
|
224 |
+
if args.model_rord:
|
225 |
+
srcPts, trgPts, matchImg, matchImgOrtho = getPerspKeypoints(args.rgb1, args.rgb2, srcH, trgH, model2, device)
|
226 |
+
elif args.model_d2:
|
227 |
+
srcPts, trgPts, matchImg, matchImgOrtho = getPerspKeypoints(args.rgb1, args.rgb2, srcH, trgH, model1, device)
|
228 |
+
elif args.model_ens:
|
229 |
+
model1 = D2Net(model_file=model1_ens)
|
230 |
+
model1 = model1.to(device)
|
231 |
+
model2 = D2Net(model_file=model2_ens)
|
232 |
+
model2 = model2.to(device)
|
233 |
+
srcPts, trgPts, matchImg, matchImgOrtho = getPerspKeypointsEnsemble(model1, model2, args.rgb1, args.rgb2, srcH, trgH, device)
|
234 |
+
elif args.sift:
|
235 |
+
srcPts, trgPts, matchImg, matchImgOrtho = siftMatching(args.rgb1, args.rgb2, srcH, trgH, device)
|
236 |
+
|
237 |
+
#### Visualization ####
|
238 |
+
print("\nShowing matches in perspective and orthographic view. Press q\n")
|
239 |
+
cv2.imshow('Orthographic view', matchImgOrtho)
|
240 |
+
cv2.imshow('Perspective view', matchImg)
|
241 |
+
cv2.waitKey()
|
242 |
+
|
243 |
+
srcPts = convertPts(srcPts)
|
244 |
+
trgPts = convertPts(trgPts)
|
245 |
+
|
246 |
+
srcCld, srcIdx, srcCor = getPointCloud(args.rgb1, args.depth1, srcPts)
|
247 |
+
trgCld, trgIdx, trgCor = getPointCloud(args.rgb2, args.depth2, trgPts)
|
248 |
+
|
249 |
+
srcSph = getSphere(srcCor)
|
250 |
+
trgSph = getSphere(trgCor)
|
251 |
+
axis = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5, origin=[0, 0, 0])
|
252 |
+
srcSph.append(srcCld); srcSph.append(axis)
|
253 |
+
trgSph.append(trgCld); trgSph.append(axis)
|
254 |
+
|
255 |
+
corr = get3dCor(srcIdx, trgIdx)
|
256 |
+
|
257 |
+
p2p = o3d.registration.TransformationEstimationPointToPoint()
|
258 |
+
trans_init = p2p.compute_transformation(srcCld, trgCld, o3d.utility.Vector2iVector(corr))
|
259 |
+
print("Transformation matrix: \n", trans_init)
|
260 |
+
|
261 |
+
if args.viz3d:
|
262 |
+
# o3d.visualization.draw_geometries(srcSph)
|
263 |
+
# o3d.visualization.draw_geometries(trgSph)
|
264 |
+
|
265 |
+
draw_registration_result(srcCld, trgCld, trans_init)
|
third_party/RoRD/demo/rgb/rgb1_1.jpg
ADDED
Git LFS Details
|
third_party/RoRD/demo/rgb/rgb1_1.npy
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:99396bb9e7c265b8bad5237806d37d8fd9d92a772e118f6de22668f1db011948
|
3 |
+
size 200
|
third_party/RoRD/demo/rgb/rgb1_2.jpg
ADDED
Git LFS Details
|
third_party/RoRD/demo/rgb/rgb1_2.npy
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f29bb750adcb50b497192ecbd554cf3cd74c3f1c9809d41994c5acd1654179f2
|
3 |
+
size 200
|
third_party/RoRD/demo/rgb/rgb2_1.jpg
ADDED
Git LFS Details
|
third_party/RoRD/demo/rgb/rgb2_1.npy
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0b911f2c3962789f99f31fc78313262ec3fa257b9dd8887d318f69fa7a303c04
|
3 |
+
size 200
|
third_party/RoRD/demo/rgb/rgb2_2.jpg
ADDED
Git LFS Details
|
third_party/RoRD/demo/rgb/rgb2_2.npy
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:63b82950927db25768fe129af2138f535faf3da2789c87e7c98957c90d8423f2
|
3 |
+
size 200
|
third_party/RoRD/demo/rgb/rgb3_1.jpg
ADDED
Git LFS Details
|
third_party/RoRD/demo/rgb/rgb3_1.npy
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d3262c4ce815dad042112aed3f3a082806fc3dab62ee6bd02492ec94abbf6987
|
3 |
+
size 200
|
third_party/RoRD/demo/rgb/rgb3_2.jpg
ADDED
Git LFS Details
|