Johannes commited on
Commit
29421eb
β€’
1 Parent(s): 5c0df9c
Files changed (7) hide show
  1. README.md +1 -1
  2. app.py +86 -0
  3. collect_env.py +492 -0
  4. plot_utils.py +107 -0
  5. requirements.txt +3 -0
  6. terrace0.JPG +0 -0
  7. terrace1.JPG +0 -0
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: Line Segment Matching
3
- emoji: 🌍
4
  colorFrom: indigo
5
  colorTo: pink
6
  sdk: gradio
1
  ---
2
  title: Line Segment Matching
3
+ emoji: πŸ“ˆ
4
  colorFrom: indigo
5
  colorTo: pink
6
  sdk: gradio
app.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import kornia as K
3
+ import kornia.feature as KF
4
+ import torch
5
+ import matplotlib
6
+ matplotlib.use('Agg')
7
+ import numpy as np
8
+ from plot_utils import plot_images, plot_lines, plot_color_line_matches
9
+
10
+ sold2 = KF.SOLD2(pretrained=True, config=None)
11
+ ransac = K.geometry.RANSAC(model_type="homography", inl_th=3.0)
12
+
13
+
14
+ def infer(img1, img2, line_style: str):
15
+ torch_img1 = K.image_to_tensor(img1).float() / 255.0
16
+ torch_img2 = K.image_to_tensor(img2).float() / 255.0
17
+
18
+ torch_img1_gray = K.color.rgb_to_grayscale(torch_img1)
19
+ torch_img2_gray = K.color.rgb_to_grayscale(torch_img2)
20
+
21
+ imgs = torch.stack([torch_img1_gray, torch_img2_gray],)
22
+
23
+ with torch.inference_mode():
24
+ outputs = sold2(imgs)
25
+
26
+ line_seg1 = outputs["line_segments"][0]
27
+ line_seg2 = outputs["line_segments"][1]
28
+ desc1 = outputs["dense_desc"][0]
29
+ desc2 = outputs["dense_desc"][1]
30
+
31
+ with torch.inference_mode():
32
+ matches = sold2.match(line_seg1, line_seg2, desc1[None], desc2[None])
33
+
34
+ valid_matches = matches != -1
35
+ match_indices = matches[valid_matches]
36
+
37
+ matched_lines1 = line_seg1[valid_matches]
38
+ matched_lines2 = line_seg2[match_indices]
39
+
40
+ imgs_to_plot = [K.tensor_to_image(torch_img1), K.tensor_to_image(torch_img2)]
41
+
42
+ fig = plot_images(imgs_to_plot, ["Image 1 - detected lines", "Image 2 - detected lines"])
43
+ if line_style == "Line Matches":
44
+ lines_to_plot = [line_seg1.numpy(), line_seg2.numpy()]
45
+ plot_lines(lines_to_plot, fig, ps=3, lw=2, indices={0, 1})
46
+ elif line_style == "Color Line Matches":
47
+ plot_color_line_matches([matched_lines1, matched_lines2], fig, lw=2)
48
+ # elif line_style == "Line Segment Homography Warping":
49
+ # H_ransac, correspondence_mask = ransac(
50
+ # matched_lines1.flip(dims=(2,)), matched_lines2.flip(dims=(2,))
51
+ # )
52
+ # img1_warp_to2 = K.geometry.warp_perspective(
53
+ # torch_img1[None], H_ransac[None], (torch_img1.shape[1:])
54
+ # )
55
+ # fig = plot_images(
56
+ # [K.tensor_to_image(torch_img2), K.tensor_to_image(img1_warp_to2)],
57
+ # ["Image 2", "Image 1 wrapped to 2"],
58
+ # )
59
+ return fig
60
+
61
+
62
+
63
+ description = """Line Segment Matching with Kornia
64
+
65
+ In this space you can try out Line Segment Matching with the Kornia library as seen in [this tutorial](https://kornia-tutorials.readthedocs.io/en/latest/line_detection_and_matching_sold2.html).
66
+
67
+ Just upload two images of a scene with different view points, choose an option for output and run the demo.
68
+ """
69
+
70
+
71
+ Iface = gr.Interface(
72
+ fn=infer,
73
+ inputs=[gr.components.Image(),
74
+ gr.components.Image(),
75
+ gr.components.Dropdown(["Line Matches",
76
+ "Color Line Matches",
77
+ #"Line Segment Homography Warping",
78
+ ],
79
+ value="Line Matches",
80
+ label="Options"),
81
+ ],
82
+ outputs=gr.components.Plot(),
83
+ examples=[["terrace0.JPG", "terrace1.JPG"]],
84
+ title="Line Segment Matching with Kornia",
85
+ description=description,
86
+ ).launch()
collect_env.py ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import print_function
2
+
3
+ # Unlike the rest of the PyTorch this file must be python2 compliant.
4
+ # This script outputs relevant system environment info
5
+ # Run it with `python collect_env.py`.
6
+ import datetime
7
+ import locale
8
+ import re
9
+ import subprocess
10
+ import sys
11
+ import os
12
+ from collections import namedtuple
13
+
14
+
15
+ try:
16
+ import torch
17
+ TORCH_AVAILABLE = True
18
+ except (ImportError, NameError, AttributeError, OSError):
19
+ TORCH_AVAILABLE = False
20
+
21
+ # System Environment Information
22
+ SystemEnv = namedtuple('SystemEnv', [
23
+ 'torch_version',
24
+ 'is_debug_build',
25
+ 'cuda_compiled_version',
26
+ 'gcc_version',
27
+ 'clang_version',
28
+ 'cmake_version',
29
+ 'os',
30
+ 'libc_version',
31
+ 'python_version',
32
+ 'python_platform',
33
+ 'is_cuda_available',
34
+ 'cuda_runtime_version',
35
+ 'nvidia_driver_version',
36
+ 'nvidia_gpu_models',
37
+ 'cudnn_version',
38
+ 'pip_version', # 'pip' or 'pip3'
39
+ 'pip_packages',
40
+ 'conda_packages',
41
+ 'hip_compiled_version',
42
+ 'hip_runtime_version',
43
+ 'miopen_runtime_version',
44
+ 'caching_allocator_config',
45
+ 'is_xnnpack_available',
46
+ ])
47
+
48
+
49
+ def run(command):
50
+ """Returns (return-code, stdout, stderr)"""
51
+ p = subprocess.Popen(command, stdout=subprocess.PIPE,
52
+ stderr=subprocess.PIPE, shell=True)
53
+ raw_output, raw_err = p.communicate()
54
+ rc = p.returncode
55
+ if get_platform() == 'win32':
56
+ enc = 'oem'
57
+ else:
58
+ enc = locale.getpreferredencoding()
59
+ output = raw_output.decode(enc)
60
+ err = raw_err.decode(enc)
61
+ return rc, output.strip(), err.strip()
62
+
63
+
64
+ def run_and_read_all(run_lambda, command):
65
+ """Runs command using run_lambda; reads and returns entire output if rc is 0"""
66
+ rc, out, _ = run_lambda(command)
67
+ if rc != 0:
68
+ return None
69
+ return out
70
+
71
+
72
+ def run_and_parse_first_match(run_lambda, command, regex):
73
+ """Runs command using run_lambda, returns the first regex match if it exists"""
74
+ rc, out, _ = run_lambda(command)
75
+ if rc != 0:
76
+ return None
77
+ match = re.search(regex, out)
78
+ if match is None:
79
+ return None
80
+ return match.group(1)
81
+
82
+ def run_and_return_first_line(run_lambda, command):
83
+ """Runs command using run_lambda and returns first line if output is not empty"""
84
+ rc, out, _ = run_lambda(command)
85
+ if rc != 0:
86
+ return None
87
+ return out.split('\n')[0]
88
+
89
+
90
+ def get_conda_packages(run_lambda):
91
+ conda = os.environ.get('CONDA_EXE', 'conda')
92
+ out = run_and_read_all(run_lambda, "{} list".format(conda))
93
+ if out is None:
94
+ return out
95
+
96
+ return "\n".join(
97
+ line
98
+ for line in out.splitlines()
99
+ if not line.startswith("#")
100
+ and any(
101
+ name in line
102
+ for name in {
103
+ "torch",
104
+ "numpy",
105
+ "cudatoolkit",
106
+ "soumith",
107
+ "mkl",
108
+ "magma",
109
+ "mkl",
110
+ }
111
+ )
112
+ )
113
+
114
+ def get_gcc_version(run_lambda):
115
+ return run_and_parse_first_match(run_lambda, 'gcc --version', r'gcc (.*)')
116
+
117
+ def get_clang_version(run_lambda):
118
+ return run_and_parse_first_match(run_lambda, 'clang --version', r'clang version (.*)')
119
+
120
+
121
+ def get_cmake_version(run_lambda):
122
+ return run_and_parse_first_match(run_lambda, 'cmake --version', r'cmake (.*)')
123
+
124
+
125
+ def get_nvidia_driver_version(run_lambda):
126
+ if get_platform() == 'darwin':
127
+ cmd = 'kextstat | grep -i cuda'
128
+ return run_and_parse_first_match(run_lambda, cmd,
129
+ r'com[.]nvidia[.]CUDA [(](.*?)[)]')
130
+ smi = get_nvidia_smi()
131
+ return run_and_parse_first_match(run_lambda, smi, r'Driver Version: (.*?) ')
132
+
133
+
134
+ def get_gpu_info(run_lambda):
135
+ if get_platform() == 'darwin' or (TORCH_AVAILABLE and hasattr(torch.version, 'hip') and torch.version.hip is not None):
136
+ if TORCH_AVAILABLE and torch.cuda.is_available():
137
+ return torch.cuda.get_device_name(None)
138
+ return None
139
+ smi = get_nvidia_smi()
140
+ uuid_regex = re.compile(r' \(UUID: .+?\)')
141
+ rc, out, _ = run_lambda(smi + ' -L')
142
+ if rc != 0:
143
+ return None
144
+ # Anonymize GPUs by removing their UUID
145
+ return re.sub(uuid_regex, '', out)
146
+
147
+
148
+ def get_running_cuda_version(run_lambda):
149
+ return run_and_parse_first_match(run_lambda, 'nvcc --version', r'release .+ V(.*)')
150
+
151
+
152
+ def get_cudnn_version(run_lambda):
153
+ """This will return a list of libcudnn.so; it's hard to tell which one is being used"""
154
+ if get_platform() == 'win32':
155
+ system_root = os.environ.get('SYSTEMROOT', 'C:\\Windows')
156
+ cuda_path = os.environ.get('CUDA_PATH', "%CUDA_PATH%")
157
+ where_cmd = os.path.join(system_root, 'System32', 'where')
158
+ cudnn_cmd = '{} /R "{}\\bin" cudnn*.dll'.format(where_cmd, cuda_path)
159
+ elif get_platform() == 'darwin':
160
+ # CUDA libraries and drivers can be found in /usr/local/cuda/. See
161
+ # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#install
162
+ # https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installmac
163
+ # Use CUDNN_LIBRARY when cudnn library is installed elsewhere.
164
+ cudnn_cmd = 'ls /usr/local/cuda/lib/libcudnn*'
165
+ else:
166
+ cudnn_cmd = 'ldconfig -p | grep libcudnn | rev | cut -d" " -f1 | rev'
167
+ rc, out, _ = run_lambda(cudnn_cmd)
168
+ # find will return 1 if there are permission errors or if not found
169
+ if len(out) == 0 or (rc != 1 and rc != 0):
170
+ l = os.environ.get('CUDNN_LIBRARY')
171
+ if l is not None and os.path.isfile(l):
172
+ return os.path.realpath(l)
173
+ return None
174
+ files_set = set()
175
+ for fn in out.split('\n'):
176
+ fn = os.path.realpath(fn) # eliminate symbolic links
177
+ if os.path.isfile(fn):
178
+ files_set.add(fn)
179
+ if not files_set:
180
+ return None
181
+ # Alphabetize the result because the order is non-deterministic otherwise
182
+ files = list(sorted(files_set))
183
+ if len(files) == 1:
184
+ return files[0]
185
+ result = '\n'.join(files)
186
+ return 'Probably one of the following:\n{}'.format(result)
187
+
188
+
189
+ def get_nvidia_smi():
190
+ # Note: nvidia-smi is currently available only on Windows and Linux
191
+ smi = 'nvidia-smi'
192
+ if get_platform() == 'win32':
193
+ system_root = os.environ.get('SYSTEMROOT', 'C:\\Windows')
194
+ program_files_root = os.environ.get('PROGRAMFILES', 'C:\\Program Files')
195
+ legacy_path = os.path.join(program_files_root, 'NVIDIA Corporation', 'NVSMI', smi)
196
+ new_path = os.path.join(system_root, 'System32', smi)
197
+ smis = [new_path, legacy_path]
198
+ for candidate_smi in smis:
199
+ if os.path.exists(candidate_smi):
200
+ smi = '"{}"'.format(candidate_smi)
201
+ break
202
+ return smi
203
+
204
+
205
+ def get_platform():
206
+ if sys.platform.startswith('linux'):
207
+ return 'linux'
208
+ elif sys.platform.startswith('win32'):
209
+ return 'win32'
210
+ elif sys.platform.startswith('cygwin'):
211
+ return 'cygwin'
212
+ elif sys.platform.startswith('darwin'):
213
+ return 'darwin'
214
+ else:
215
+ return sys.platform
216
+
217
+
218
+ def get_mac_version(run_lambda):
219
+ return run_and_parse_first_match(run_lambda, 'sw_vers -productVersion', r'(.*)')
220
+
221
+
222
+ def get_windows_version(run_lambda):
223
+ system_root = os.environ.get('SYSTEMROOT', 'C:\\Windows')
224
+ wmic_cmd = os.path.join(system_root, 'System32', 'Wbem', 'wmic')
225
+ findstr_cmd = os.path.join(system_root, 'System32', 'findstr')
226
+ return run_and_read_all(run_lambda, '{} os get Caption | {} /v Caption'.format(wmic_cmd, findstr_cmd))
227
+
228
+
229
+ def get_lsb_version(run_lambda):
230
+ return run_and_parse_first_match(run_lambda, 'lsb_release -a', r'Description:\t(.*)')
231
+
232
+
233
+ def check_release_file(run_lambda):
234
+ return run_and_parse_first_match(run_lambda, 'cat /etc/*-release',
235
+ r'PRETTY_NAME="(.*)"')
236
+
237
+
238
+ def get_os(run_lambda):
239
+ from platform import machine
240
+ platform = get_platform()
241
+
242
+ if platform == 'win32' or platform == 'cygwin':
243
+ return get_windows_version(run_lambda)
244
+
245
+ if platform == 'darwin':
246
+ version = get_mac_version(run_lambda)
247
+ if version is None:
248
+ return None
249
+ return 'macOS {} ({})'.format(version, machine())
250
+
251
+ if platform == 'linux':
252
+ # Ubuntu/Debian based
253
+ desc = get_lsb_version(run_lambda)
254
+ if desc is not None:
255
+ return '{} ({})'.format(desc, machine())
256
+
257
+ # Try reading /etc/*-release
258
+ desc = check_release_file(run_lambda)
259
+ if desc is not None:
260
+ return '{} ({})'.format(desc, machine())
261
+
262
+ return '{} ({})'.format(platform, machine())
263
+
264
+ # Unknown platform
265
+ return platform
266
+
267
+
268
+ def get_python_platform():
269
+ import platform
270
+ return platform.platform()
271
+
272
+
273
+ def get_libc_version():
274
+ import platform
275
+ if get_platform() != 'linux':
276
+ return 'N/A'
277
+ return '-'.join(platform.libc_ver())
278
+
279
+
280
+ def get_pip_packages(run_lambda):
281
+ """Returns `pip list` output. Note: will also find conda-installed pytorch
282
+ and numpy packages."""
283
+ # People generally have `pip` as `pip` or `pip3`
284
+ # But here it is incoved as `python -mpip`
285
+ def run_with_pip(pip):
286
+ out = run_and_read_all(run_lambda, "{} list --format=freeze".format(pip))
287
+ return "\n".join(
288
+ line
289
+ for line in out.splitlines()
290
+ if any(
291
+ name in line
292
+ for name in {
293
+ "torch",
294
+ "numpy",
295
+ "mypy",
296
+ }
297
+ )
298
+ )
299
+
300
+ pip_version = 'pip3' if sys.version[0] == '3' else 'pip'
301
+ out = run_with_pip(sys.executable + ' -mpip')
302
+
303
+ return pip_version, out
304
+
305
+
306
+ def get_cachingallocator_config():
307
+ ca_config = os.environ.get('PYTORCH_CUDA_ALLOC_CONF', '')
308
+ return ca_config
309
+
310
+ def is_xnnpack_available():
311
+ if TORCH_AVAILABLE:
312
+ import torch.backends.xnnpack
313
+ return str(torch.backends.xnnpack.enabled) # type: ignore[attr-defined]
314
+ else:
315
+ return "N/A"
316
+
317
+ def get_env_info():
318
+ run_lambda = run
319
+ pip_version, pip_list_output = get_pip_packages(run_lambda)
320
+
321
+ if TORCH_AVAILABLE:
322
+ version_str = torch.__version__
323
+ debug_mode_str = str(torch.version.debug)
324
+ cuda_available_str = str(torch.cuda.is_available())
325
+ cuda_version_str = torch.version.cuda
326
+ if not hasattr(torch.version, 'hip') or torch.version.hip is None: # cuda version
327
+ hip_compiled_version = hip_runtime_version = miopen_runtime_version = 'N/A'
328
+ else: # HIP version
329
+ cfg = torch._C._show_config().split('\n')
330
+ hip_runtime_version = [s.rsplit(None, 1)[-1] for s in cfg if 'HIP Runtime' in s][0]
331
+ miopen_runtime_version = [s.rsplit(None, 1)[-1] for s in cfg if 'MIOpen' in s][0]
332
+ cuda_version_str = 'N/A'
333
+ hip_compiled_version = torch.version.hip
334
+ else:
335
+ version_str = debug_mode_str = cuda_available_str = cuda_version_str = 'N/A'
336
+ hip_compiled_version = hip_runtime_version = miopen_runtime_version = 'N/A'
337
+
338
+ sys_version = sys.version.replace("\n", " ")
339
+
340
+ return SystemEnv(
341
+ torch_version=version_str,
342
+ is_debug_build=debug_mode_str,
343
+ python_version='{} ({}-bit runtime)'.format(sys_version, sys.maxsize.bit_length() + 1),
344
+ python_platform=get_python_platform(),
345
+ is_cuda_available=cuda_available_str,
346
+ cuda_compiled_version=cuda_version_str,
347
+ cuda_runtime_version=get_running_cuda_version(run_lambda),
348
+ nvidia_gpu_models=get_gpu_info(run_lambda),
349
+ nvidia_driver_version=get_nvidia_driver_version(run_lambda),
350
+ cudnn_version=get_cudnn_version(run_lambda),
351
+ hip_compiled_version=hip_compiled_version,
352
+ hip_runtime_version=hip_runtime_version,
353
+ miopen_runtime_version=miopen_runtime_version,
354
+ pip_version=pip_version,
355
+ pip_packages=pip_list_output,
356
+ conda_packages=get_conda_packages(run_lambda),
357
+ os=get_os(run_lambda),
358
+ libc_version=get_libc_version(),
359
+ gcc_version=get_gcc_version(run_lambda),
360
+ clang_version=get_clang_version(run_lambda),
361
+ cmake_version=get_cmake_version(run_lambda),
362
+ caching_allocator_config=get_cachingallocator_config(),
363
+ is_xnnpack_available=is_xnnpack_available(),
364
+ )
365
+
366
+ env_info_fmt = """
367
+ PyTorch version: {torch_version}
368
+ Is debug build: {is_debug_build}
369
+ CUDA used to build PyTorch: {cuda_compiled_version}
370
+ ROCM used to build PyTorch: {hip_compiled_version}
371
+
372
+ OS: {os}
373
+ GCC version: {gcc_version}
374
+ Clang version: {clang_version}
375
+ CMake version: {cmake_version}
376
+ Libc version: {libc_version}
377
+
378
+ Python version: {python_version}
379
+ Python platform: {python_platform}
380
+ Is CUDA available: {is_cuda_available}
381
+ CUDA runtime version: {cuda_runtime_version}
382
+ GPU models and configuration: {nvidia_gpu_models}
383
+ Nvidia driver version: {nvidia_driver_version}
384
+ cuDNN version: {cudnn_version}
385
+ HIP runtime version: {hip_runtime_version}
386
+ MIOpen runtime version: {miopen_runtime_version}
387
+ Is XNNPACK available: {is_xnnpack_available}
388
+
389
+ Versions of relevant libraries:
390
+ {pip_packages}
391
+ {conda_packages}
392
+ """.strip()
393
+
394
+
395
+ def pretty_str(envinfo):
396
+ def replace_nones(dct, replacement='Could not collect'):
397
+ for key in dct.keys():
398
+ if dct[key] is not None:
399
+ continue
400
+ dct[key] = replacement
401
+ return dct
402
+
403
+ def replace_bools(dct, true='Yes', false='No'):
404
+ for key in dct.keys():
405
+ if dct[key] is True:
406
+ dct[key] = true
407
+ elif dct[key] is False:
408
+ dct[key] = false
409
+ return dct
410
+
411
+ def prepend(text, tag='[prepend]'):
412
+ lines = text.split('\n')
413
+ updated_lines = [tag + line for line in lines]
414
+ return '\n'.join(updated_lines)
415
+
416
+ def replace_if_empty(text, replacement='No relevant packages'):
417
+ if text is not None and len(text) == 0:
418
+ return replacement
419
+ return text
420
+
421
+ def maybe_start_on_next_line(string):
422
+ # If `string` is multiline, prepend a \n to it.
423
+ if string is not None and len(string.split('\n')) > 1:
424
+ return '\n{}\n'.format(string)
425
+ return string
426
+
427
+ mutable_dict = envinfo._asdict()
428
+
429
+ # If nvidia_gpu_models is multiline, start on the next line
430
+ mutable_dict['nvidia_gpu_models'] = \
431
+ maybe_start_on_next_line(envinfo.nvidia_gpu_models)
432
+
433
+ # If the machine doesn't have CUDA, report some fields as 'No CUDA'
434
+ dynamic_cuda_fields = [
435
+ 'cuda_runtime_version',
436
+ 'nvidia_gpu_models',
437
+ 'nvidia_driver_version',
438
+ ]
439
+ all_cuda_fields = dynamic_cuda_fields + ['cudnn_version']
440
+ all_dynamic_cuda_fields_missing = all(
441
+ mutable_dict[field] is None for field in dynamic_cuda_fields)
442
+ if TORCH_AVAILABLE and not torch.cuda.is_available() and all_dynamic_cuda_fields_missing:
443
+ for field in all_cuda_fields:
444
+ mutable_dict[field] = 'No CUDA'
445
+ if envinfo.cuda_compiled_version is None:
446
+ mutable_dict['cuda_compiled_version'] = 'None'
447
+
448
+ # Replace True with Yes, False with No
449
+ mutable_dict = replace_bools(mutable_dict)
450
+
451
+ # Replace all None objects with 'Could not collect'
452
+ mutable_dict = replace_nones(mutable_dict)
453
+
454
+ # If either of these are '', replace with 'No relevant packages'
455
+ mutable_dict['pip_packages'] = replace_if_empty(mutable_dict['pip_packages'])
456
+ mutable_dict['conda_packages'] = replace_if_empty(mutable_dict['conda_packages'])
457
+
458
+ # Tag conda and pip packages with a prefix
459
+ # If they were previously None, they'll show up as ie '[conda] Could not collect'
460
+ if mutable_dict['pip_packages']:
461
+ mutable_dict['pip_packages'] = prepend(mutable_dict['pip_packages'],
462
+ '[{}] '.format(envinfo.pip_version))
463
+ if mutable_dict['conda_packages']:
464
+ mutable_dict['conda_packages'] = prepend(mutable_dict['conda_packages'],
465
+ '[conda] ')
466
+ return env_info_fmt.format(**mutable_dict)
467
+
468
+
469
+ def get_pretty_env_info():
470
+ return pretty_str(get_env_info())
471
+
472
+
473
+ def main():
474
+ print("Collecting environment information...")
475
+ output = get_pretty_env_info()
476
+ print(output)
477
+
478
+ if TORCH_AVAILABLE and hasattr(torch, 'utils') and hasattr(torch.utils, '_crash_handler'):
479
+ minidump_dir = torch.utils._crash_handler.DEFAULT_MINIDUMP_DIR
480
+ if sys.platform == "linux" and os.path.exists(minidump_dir):
481
+ dumps = [os.path.join(minidump_dir, dump) for dump in os.listdir(minidump_dir)]
482
+ latest = max(dumps, key=os.path.getctime)
483
+ ctime = os.path.getctime(latest)
484
+ creation_time = datetime.datetime.fromtimestamp(ctime).strftime('%Y-%m-%d %H:%M:%S')
485
+ msg = "\n*** Detected a minidump at {} created on {}, ".format(latest, creation_time) + \
486
+ "if this is related to your bug please include it when you file a report ***"
487
+ print(msg, file=sys.stderr)
488
+
489
+
490
+
491
+ if __name__ == '__main__':
492
+ main()
plot_utils.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+
3
+ import matplotlib
4
+ import matplotlib.colors as mcolors
5
+ import matplotlib.pyplot as plt
6
+ import numpy as np
7
+
8
+
9
+ def plot_images(imgs, titles=None, cmaps="gray", dpi=100, size=6, pad=0.5):
10
+ """Plot a set of images horizontally.
11
+ Args:
12
+ imgs: a list of NumPy or PyTorch images, RGB (H, W, 3) or mono (H, W).
13
+ titles: a list of strings, as titles for each image.
14
+ cmaps: colormaps for monochrome images.
15
+ """
16
+ n = len(imgs)
17
+ if not isinstance(cmaps, (list, tuple)):
18
+ cmaps = [cmaps] * n
19
+ figsize = (size * n, size * 3 / 4) if size is not None else None
20
+ fig, ax = plt.subplots(1, n, figsize=figsize, dpi=dpi)
21
+ if n == 1:
22
+ ax = [ax]
23
+ for i in range(n):
24
+ ax[i].imshow(imgs[i], cmap=plt.get_cmap(cmaps[i]))
25
+ ax[i].get_yaxis().set_ticks([])
26
+ ax[i].get_xaxis().set_ticks([])
27
+ ax[i].set_axis_off()
28
+ for spine in ax[i].spines.values(): # remove frame
29
+ spine.set_visible(False)
30
+ if titles:
31
+ ax[i].set_title(titles[i])
32
+ fig.tight_layout(pad=pad)
33
+
34
+ return fig
35
+
36
+
37
+ def plot_lines(
38
+ lines, fig, line_colors="orange", point_colors="cyan", ps=4, lw=2, indices=(0, 1)
39
+ ):
40
+ """Plot lines and endpoints for existing images.
41
+ Args:
42
+ lines: list of ndarrays of size (N, 2, 2).
43
+ colors: string, or list of list of tuples (one for each keypoints).
44
+ ps: size of the keypoints as float pixels.
45
+ lw: line width as float pixels.
46
+ indices: indices of the images to draw the matches on.
47
+ """
48
+ if not isinstance(line_colors, list):
49
+ line_colors = [line_colors] * len(lines)
50
+ if not isinstance(point_colors, list):
51
+ point_colors = [point_colors] * len(lines)
52
+
53
+ #fig = plt.gcf()
54
+ ax = fig.axes
55
+ assert len(ax) > max(indices)
56
+ axes = [ax[i] for i in indices]
57
+ fig.canvas.draw()
58
+
59
+ # Plot the lines and junctions
60
+ for a, l, lc, pc in zip(axes, lines, line_colors, point_colors):
61
+ for i in range(len(l)):
62
+ line = matplotlib.lines.Line2D(
63
+ (l[i, 1, 1], l[i, 0, 1]),
64
+ (l[i, 1, 0], l[i, 0, 0]),
65
+ zorder=1,
66
+ c=lc,
67
+ linewidth=lw,
68
+ )
69
+ a.add_line(line)
70
+ pts = l.reshape(-1, 2)
71
+ a.scatter(pts[:, 1], pts[:, 0], c=pc, s=ps, linewidths=0, zorder=2)
72
+
73
+ return fig
74
+
75
+
76
+ def plot_color_line_matches(lines, fig, lw=2, indices=(0, 1)):
77
+ """Plot line matches for existing images with multiple colors.
78
+ Args:
79
+ lines: list of ndarrays of size (N, 2, 2).
80
+ lw: line width as float pixels.
81
+ indices: indices of the images to draw the matches on.
82
+ """
83
+ n_lines = len(lines[0])
84
+
85
+ cmap = plt.get_cmap("nipy_spectral", lut=n_lines)
86
+ colors = np.array([mcolors.rgb2hex(cmap(i)) for i in range(cmap.N)])
87
+
88
+ np.random.shuffle(colors)
89
+
90
+ ax = fig.axes
91
+ assert len(ax) > max(indices)
92
+ axes = [ax[i] for i in indices]
93
+ fig.canvas.draw()
94
+
95
+ # Plot the lines
96
+ for a, l in zip(axes, lines):
97
+ for i in range(len(l)):
98
+ line = matplotlib.lines.Line2D(
99
+ (l[i, 1, 1], l[i, 0, 1]),
100
+ (l[i, 1, 0], l[i, 0, 0]),
101
+ zorder=1,
102
+ c=colors[i],
103
+ linewidth=lw,
104
+ )
105
+ a.add_line(line)
106
+
107
+ return fig
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ opencv-python
2
+ matplotlib
3
+ kornia
terrace0.JPG ADDED
terrace1.JPG ADDED