Johannes commited on
Commit
25a8011
1 Parent(s): 83849bd
Files changed (4) hide show
  1. app.py +56 -30
  2. collect_env.py +187 -131
  3. plot_utils.py +5 -5
  4. requirements.txt +1 -1
app.py CHANGED
@@ -3,12 +3,13 @@ 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):
@@ -17,48 +18,68 @@ def infer(img1, img2, line_style: str):
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 = """In this space you can try out Line Detection and Segment Matching with the Kornia library as seen in [this tutorial](https://kornia-tutorials.readthedocs.io/en/latest/line_detection_and_matching_sold2.html).
64
 
@@ -68,17 +89,22 @@ Just upload two images of a scene with different view points, choose an option f
68
 
69
  Iface = gr.Interface(
70
  fn=infer,
71
- inputs=[gr.components.Image(),
72
- gr.components.Image(),
73
- gr.components.Dropdown(["Line Matches",
74
- "Color Line Matches",
75
- #"Line Segment Homography Warping",
76
- ],
77
- value="Line Matches",
78
- label="Options"),
 
79
  ],
 
 
 
 
80
  outputs=gr.components.Plot(),
81
  examples=[["terrace0.JPG", "terrace1.JPG", "Line Matches"]],
82
  title="Line Segment Matching with Kornia",
83
  description=description,
84
- ).launch()
3
  import kornia.feature as KF
4
  import torch
5
  import matplotlib
6
+
7
+ matplotlib.use("Agg")
8
  import numpy as np
9
  from plot_utils import plot_images, plot_lines, plot_color_line_matches
10
 
11
  sold2 = KF.SOLD2(pretrained=True, config=None)
12
+ ransac = K.geometry.RANSAC(model_type="homography_from_linesegments", inl_th=3.0)
13
 
14
 
15
  def infer(img1, img2, line_style: str):
18
 
19
  torch_img1_gray = K.color.rgb_to_grayscale(torch_img1)
20
  torch_img2_gray = K.color.rgb_to_grayscale(torch_img2)
21
+
22
+ imgs = torch.stack(
23
+ [torch_img1_gray, torch_img2_gray],
24
+ )
25
+
26
  with torch.inference_mode():
27
  outputs = sold2(imgs)
28
+
29
  line_seg1 = outputs["line_segments"][0]
30
  line_seg2 = outputs["line_segments"][1]
31
  desc1 = outputs["dense_desc"][0]
32
  desc2 = outputs["dense_desc"][1]
33
+
34
  with torch.inference_mode():
35
  matches = sold2.match(line_seg1, line_seg2, desc1[None], desc2[None])
36
+
37
  valid_matches = matches != -1
38
  match_indices = matches[valid_matches]
39
 
40
  matched_lines1 = line_seg1[valid_matches]
41
  matched_lines2 = line_seg2[match_indices]
42
+
43
  imgs_to_plot = [K.tensor_to_image(torch_img1), K.tensor_to_image(torch_img2)]
44
 
45
+ fig = plot_images(
46
+ imgs_to_plot, ["Image 1 - detected lines", "Image 2 - detected lines"]
47
+ )
48
  if line_style == "Line Matches":
49
  lines_to_plot = [line_seg1.numpy(), line_seg2.numpy()]
50
  plot_lines(lines_to_plot, fig, ps=3, lw=2, indices={0, 1})
51
  elif line_style == "Color Line Matches":
52
  plot_color_line_matches([matched_lines1, matched_lines2], fig, lw=2)
53
+ elif line_style == "Line Segment Homography Warping":
54
+ _, _, img1_warp_to2 = get_homography_values(
55
+ matched_lines1, matched_lines2, torch_img1
56
+ )
57
+ fig = plot_images(
58
+ [K.tensor_to_image(torch_img2), K.tensor_to_image(img1_warp_to2)],
59
+ ["Image 2", "Image 1 wrapped to 2"],
60
+ )
61
+ elif line_style == "Matched Lines for Homography Warping":
62
+ _, correspondence_mask, _ = get_homography_values(
63
+ matched_lines1, matched_lines2, torch_img1
64
+ )
65
+ plot_color_line_matches(
66
+ [matched_lines1[correspondence_mask], matched_lines2[correspondence_mask]],
67
+ fig,
68
+ lw=2,
69
+ )
70
  return fig
71
 
72
 
73
+ def get_homography_values(matched_lines1, matched_lines2, torch_img1):
74
+ H_ransac, correspondence_mask = ransac(
75
+ matched_lines1.flip(dims=(2,)), matched_lines2.flip(dims=(2,))
76
+ )
77
+ img1_warp_to2 = K.geometry.warp_perspective(
78
+ torch_img1[None], H_ransac[None], (torch_img1.shape[1:])
79
+ )
80
+
81
+ return H_ransac, correspondence_mask, img1_warp_to2
82
+
83
 
84
  description = """In this space you can try out Line Detection and Segment Matching with the Kornia library as seen in [this tutorial](https://kornia-tutorials.readthedocs.io/en/latest/line_detection_and_matching_sold2.html).
85
 
89
 
90
  Iface = gr.Interface(
91
  fn=infer,
92
+ inputs=[
93
+ gr.components.Image(),
94
+ gr.components.Image(),
95
+ gr.components.Dropdown(
96
+ [
97
+ "Line Matches",
98
+ "Color Line Matches",
99
+ "Line Segment Homography Warping",
100
+ "Matched Lines for Homography Warping",
101
  ],
102
+ value="Line Matches",
103
+ label="Options",
104
+ ),
105
+ ],
106
  outputs=gr.components.Plot(),
107
  examples=[["terrace0.JPG", "terrace1.JPG", "Line Matches"]],
108
  title="Line Segment Matching with Kornia",
109
  description=description,
110
+ ).launch()
collect_env.py CHANGED
@@ -14,46 +14,51 @@ from collections import namedtuple
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)
@@ -79,16 +84,17 @@ def run_and_parse_first_match(run_lambda, command, regex):
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
@@ -111,68 +117,77 @@ def get_conda_packages(run_lambda):
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)
@@ -182,18 +197,20 @@ def get_cudnn_version(run_lambda):
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):
@@ -203,63 +220,69 @@ def get_nvidia_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
@@ -267,14 +290,16 @@ def get_os(run_lambda):
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):
@@ -297,23 +322,26 @@ def get_pip_packages(run_lambda):
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)
@@ -323,24 +351,32 @@ def get_env_info():
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,
@@ -363,6 +399,7 @@ def get_env_info():
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}
@@ -393,14 +430,14 @@ Versions of relevant libraries:
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
@@ -408,42 +445,48 @@ def pretty_str(envinfo):
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)
@@ -452,17 +495,19 @@ def pretty_str(envinfo):
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
 
@@ -475,18 +520,29 @@ def main():
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()
14
 
15
  try:
16
  import torch
17
+
18
  TORCH_AVAILABLE = True
19
  except (ImportError, NameError, AttributeError, OSError):
20
  TORCH_AVAILABLE = False
21
 
22
  # System Environment Information
23
+ SystemEnv = namedtuple(
24
+ "SystemEnv",
25
+ [
26
+ "torch_version",
27
+ "is_debug_build",
28
+ "cuda_compiled_version",
29
+ "gcc_version",
30
+ "clang_version",
31
+ "cmake_version",
32
+ "os",
33
+ "libc_version",
34
+ "python_version",
35
+ "python_platform",
36
+ "is_cuda_available",
37
+ "cuda_runtime_version",
38
+ "nvidia_driver_version",
39
+ "nvidia_gpu_models",
40
+ "cudnn_version",
41
+ "pip_version", # 'pip' or 'pip3'
42
+ "pip_packages",
43
+ "conda_packages",
44
+ "hip_compiled_version",
45
+ "hip_runtime_version",
46
+ "miopen_runtime_version",
47
+ "caching_allocator_config",
48
+ "is_xnnpack_available",
49
+ ],
50
+ )
51
 
52
 
53
  def run(command):
54
  """Returns (return-code, stdout, stderr)"""
55
+ p = subprocess.Popen(
56
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
57
+ )
58
  raw_output, raw_err = p.communicate()
59
  rc = p.returncode
60
+ if get_platform() == "win32":
61
+ enc = "oem"
62
  else:
63
  enc = locale.getpreferredencoding()
64
  output = raw_output.decode(enc)
84
  return None
85
  return match.group(1)
86
 
87
+
88
  def run_and_return_first_line(run_lambda, command):
89
  """Runs command using run_lambda and returns first line if output is not empty"""
90
  rc, out, _ = run_lambda(command)
91
  if rc != 0:
92
  return None
93
+ return out.split("\n")[0]
94
 
95
 
96
  def get_conda_packages(run_lambda):
97
+ conda = os.environ.get("CONDA_EXE", "conda")
98
  out = run_and_read_all(run_lambda, "{} list".format(conda))
99
  if out is None:
100
  return out
117
  )
118
  )
119
 
120
+
121
  def get_gcc_version(run_lambda):
122
+ return run_and_parse_first_match(run_lambda, "gcc --version", r"gcc (.*)")
123
+
124
 
125
  def get_clang_version(run_lambda):
126
+ return run_and_parse_first_match(
127
+ run_lambda, "clang --version", r"clang version (.*)"
128
+ )
129
 
130
 
131
  def get_cmake_version(run_lambda):
132
+ return run_and_parse_first_match(run_lambda, "cmake --version", r"cmake (.*)")
133
 
134
 
135
  def get_nvidia_driver_version(run_lambda):
136
+ if get_platform() == "darwin":
137
+ cmd = "kextstat | grep -i cuda"
138
+ return run_and_parse_first_match(
139
+ run_lambda, cmd, r"com[.]nvidia[.]CUDA [(](.*?)[)]"
140
+ )
141
  smi = get_nvidia_smi()
142
+ return run_and_parse_first_match(run_lambda, smi, r"Driver Version: (.*?) ")
143
 
144
 
145
  def get_gpu_info(run_lambda):
146
+ if get_platform() == "darwin" or (
147
+ TORCH_AVAILABLE
148
+ and hasattr(torch.version, "hip")
149
+ and torch.version.hip is not None
150
+ ):
151
  if TORCH_AVAILABLE and torch.cuda.is_available():
152
  return torch.cuda.get_device_name(None)
153
  return None
154
  smi = get_nvidia_smi()
155
+ uuid_regex = re.compile(r" \(UUID: .+?\)")
156
+ rc, out, _ = run_lambda(smi + " -L")
157
  if rc != 0:
158
  return None
159
  # Anonymize GPUs by removing their UUID
160
+ return re.sub(uuid_regex, "", out)
161
 
162
 
163
  def get_running_cuda_version(run_lambda):
164
+ return run_and_parse_first_match(run_lambda, "nvcc --version", r"release .+ V(.*)")
165
 
166
 
167
  def get_cudnn_version(run_lambda):
168
  """This will return a list of libcudnn.so; it's hard to tell which one is being used"""
169
+ if get_platform() == "win32":
170
+ system_root = os.environ.get("SYSTEMROOT", "C:\\Windows")
171
+ cuda_path = os.environ.get("CUDA_PATH", "%CUDA_PATH%")
172
+ where_cmd = os.path.join(system_root, "System32", "where")
173
  cudnn_cmd = '{} /R "{}\\bin" cudnn*.dll'.format(where_cmd, cuda_path)
174
+ elif get_platform() == "darwin":
175
  # CUDA libraries and drivers can be found in /usr/local/cuda/. See
176
  # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#install
177
  # https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installmac
178
  # Use CUDNN_LIBRARY when cudnn library is installed elsewhere.
179
+ cudnn_cmd = "ls /usr/local/cuda/lib/libcudnn*"
180
  else:
181
  cudnn_cmd = 'ldconfig -p | grep libcudnn | rev | cut -d" " -f1 | rev'
182
  rc, out, _ = run_lambda(cudnn_cmd)
183
  # find will return 1 if there are permission errors or if not found
184
  if len(out) == 0 or (rc != 1 and rc != 0):
185
+ l = os.environ.get("CUDNN_LIBRARY")
186
  if l is not None and os.path.isfile(l):
187
  return os.path.realpath(l)
188
  return None
189
  files_set = set()
190
+ for fn in out.split("\n"):
191
  fn = os.path.realpath(fn) # eliminate symbolic links
192
  if os.path.isfile(fn):
193
  files_set.add(fn)
197
  files = list(sorted(files_set))
198
  if len(files) == 1:
199
  return files[0]
200
+ result = "\n".join(files)
201
+ return "Probably one of the following:\n{}".format(result)
202
 
203
 
204
  def get_nvidia_smi():
205
  # Note: nvidia-smi is currently available only on Windows and Linux
206
+ smi = "nvidia-smi"
207
+ if get_platform() == "win32":
208
+ system_root = os.environ.get("SYSTEMROOT", "C:\\Windows")
209
+ program_files_root = os.environ.get("PROGRAMFILES", "C:\\Program Files")
210
+ legacy_path = os.path.join(
211
+ program_files_root, "NVIDIA Corporation", "NVSMI", smi
212
+ )
213
+ new_path = os.path.join(system_root, "System32", smi)
214
  smis = [new_path, legacy_path]
215
  for candidate_smi in smis:
216
  if os.path.exists(candidate_smi):
220
 
221
 
222
  def get_platform():
223
+ if sys.platform.startswith("linux"):
224
+ return "linux"
225
+ elif sys.platform.startswith("win32"):
226
+ return "win32"
227
+ elif sys.platform.startswith("cygwin"):
228
+ return "cygwin"
229
+ elif sys.platform.startswith("darwin"):
230
+ return "darwin"
231
  else:
232
  return sys.platform
233
 
234
 
235
  def get_mac_version(run_lambda):
236
+ return run_and_parse_first_match(run_lambda, "sw_vers -productVersion", r"(.*)")
237
 
238
 
239
  def get_windows_version(run_lambda):
240
+ system_root = os.environ.get("SYSTEMROOT", "C:\\Windows")
241
+ wmic_cmd = os.path.join(system_root, "System32", "Wbem", "wmic")
242
+ findstr_cmd = os.path.join(system_root, "System32", "findstr")
243
+ return run_and_read_all(
244
+ run_lambda, "{} os get Caption | {} /v Caption".format(wmic_cmd, findstr_cmd)
245
+ )
246
 
247
 
248
  def get_lsb_version(run_lambda):
249
+ return run_and_parse_first_match(
250
+ run_lambda, "lsb_release -a", r"Description:\t(.*)"
251
+ )
252
 
253
 
254
  def check_release_file(run_lambda):
255
+ return run_and_parse_first_match(
256
+ run_lambda, "cat /etc/*-release", r'PRETTY_NAME="(.*)"'
257
+ )
258
 
259
 
260
  def get_os(run_lambda):
261
  from platform import machine
262
+
263
  platform = get_platform()
264
 
265
+ if platform == "win32" or platform == "cygwin":
266
  return get_windows_version(run_lambda)
267
 
268
+ if platform == "darwin":
269
  version = get_mac_version(run_lambda)
270
  if version is None:
271
  return None
272
+ return "macOS {} ({})".format(version, machine())
273
 
274
+ if platform == "linux":
275
  # Ubuntu/Debian based
276
  desc = get_lsb_version(run_lambda)
277
  if desc is not None:
278
+ return "{} ({})".format(desc, machine())
279
 
280
  # Try reading /etc/*-release
281
  desc = check_release_file(run_lambda)
282
  if desc is not None:
283
+ return "{} ({})".format(desc, machine())
284
 
285
+ return "{} ({})".format(platform, machine())
286
 
287
  # Unknown platform
288
  return platform
290
 
291
  def get_python_platform():
292
  import platform
293
+
294
  return platform.platform()
295
 
296
 
297
  def get_libc_version():
298
  import platform
299
+
300
+ if get_platform() != "linux":
301
+ return "N/A"
302
+ return "-".join(platform.libc_ver())
303
 
304
 
305
  def get_pip_packages(run_lambda):
322
  )
323
  )
324
 
325
+ pip_version = "pip3" if sys.version[0] == "3" else "pip"
326
+ out = run_with_pip(sys.executable + " -mpip")
327
 
328
  return pip_version, out
329
 
330
 
331
  def get_cachingallocator_config():
332
+ ca_config = os.environ.get("PYTORCH_CUDA_ALLOC_CONF", "")
333
  return ca_config
334
 
335
+
336
  def is_xnnpack_available():
337
  if TORCH_AVAILABLE:
338
  import torch.backends.xnnpack
339
+
340
  return str(torch.backends.xnnpack.enabled) # type: ignore[attr-defined]
341
  else:
342
  return "N/A"
343
 
344
+
345
  def get_env_info():
346
  run_lambda = run
347
  pip_version, pip_list_output = get_pip_packages(run_lambda)
351
  debug_mode_str = str(torch.version.debug)
352
  cuda_available_str = str(torch.cuda.is_available())
353
  cuda_version_str = torch.version.cuda
354
+ if (
355
+ not hasattr(torch.version, "hip") or torch.version.hip is None
356
+ ): # cuda version
357
+ hip_compiled_version = hip_runtime_version = miopen_runtime_version = "N/A"
358
  else: # HIP version
359
+ cfg = torch._C._show_config().split("\n")
360
+ hip_runtime_version = [
361
+ s.rsplit(None, 1)[-1] for s in cfg if "HIP Runtime" in s
362
+ ][0]
363
+ miopen_runtime_version = [
364
+ s.rsplit(None, 1)[-1] for s in cfg if "MIOpen" in s
365
+ ][0]
366
+ cuda_version_str = "N/A"
367
  hip_compiled_version = torch.version.hip
368
  else:
369
+ version_str = debug_mode_str = cuda_available_str = cuda_version_str = "N/A"
370
+ hip_compiled_version = hip_runtime_version = miopen_runtime_version = "N/A"
371
 
372
  sys_version = sys.version.replace("\n", " ")
373
 
374
  return SystemEnv(
375
  torch_version=version_str,
376
  is_debug_build=debug_mode_str,
377
+ python_version="{} ({}-bit runtime)".format(
378
+ sys_version, sys.maxsize.bit_length() + 1
379
+ ),
380
  python_platform=get_python_platform(),
381
  is_cuda_available=cuda_available_str,
382
  cuda_compiled_version=cuda_version_str,
399
  is_xnnpack_available=is_xnnpack_available(),
400
  )
401
 
402
+
403
  env_info_fmt = """
404
  PyTorch version: {torch_version}
405
  Is debug build: {is_debug_build}
430
 
431
 
432
  def pretty_str(envinfo):
433
+ def replace_nones(dct, replacement="Could not collect"):
434
  for key in dct.keys():
435
  if dct[key] is not None:
436
  continue
437
  dct[key] = replacement
438
  return dct
439
 
440
+ def replace_bools(dct, true="Yes", false="No"):
441
  for key in dct.keys():
442
  if dct[key] is True:
443
  dct[key] = true
445
  dct[key] = false
446
  return dct
447
 
448
+ def prepend(text, tag="[prepend]"):
449
+ lines = text.split("\n")
450
  updated_lines = [tag + line for line in lines]
451
+ return "\n".join(updated_lines)
452
 
453
+ def replace_if_empty(text, replacement="No relevant packages"):
454
  if text is not None and len(text) == 0:
455
  return replacement
456
  return text
457
 
458
  def maybe_start_on_next_line(string):
459
  # If `string` is multiline, prepend a \n to it.
460
+ if string is not None and len(string.split("\n")) > 1:
461
+ return "\n{}\n".format(string)
462
  return string
463
 
464
  mutable_dict = envinfo._asdict()
465
 
466
  # If nvidia_gpu_models is multiline, start on the next line
467
+ mutable_dict["nvidia_gpu_models"] = maybe_start_on_next_line(
468
+ envinfo.nvidia_gpu_models
469
+ )
470
 
471
  # If the machine doesn't have CUDA, report some fields as 'No CUDA'
472
  dynamic_cuda_fields = [
473
+ "cuda_runtime_version",
474
+ "nvidia_gpu_models",
475
+ "nvidia_driver_version",
476
  ]
477
+ all_cuda_fields = dynamic_cuda_fields + ["cudnn_version"]
478
  all_dynamic_cuda_fields_missing = all(
479
+ mutable_dict[field] is None for field in dynamic_cuda_fields
480
+ )
481
+ if (
482
+ TORCH_AVAILABLE
483
+ and not torch.cuda.is_available()
484
+ and all_dynamic_cuda_fields_missing
485
+ ):
486
  for field in all_cuda_fields:
487
+ mutable_dict[field] = "No CUDA"
488
  if envinfo.cuda_compiled_version is None:
489
+ mutable_dict["cuda_compiled_version"] = "None"
490
 
491
  # Replace True with Yes, False with No
492
  mutable_dict = replace_bools(mutable_dict)
495
  mutable_dict = replace_nones(mutable_dict)
496
 
497
  # If either of these are '', replace with 'No relevant packages'
498
+ mutable_dict["pip_packages"] = replace_if_empty(mutable_dict["pip_packages"])
499
+ mutable_dict["conda_packages"] = replace_if_empty(mutable_dict["conda_packages"])
500
 
501
  # Tag conda and pip packages with a prefix
502
  # If they were previously None, they'll show up as ie '[conda] Could not collect'
503
+ if mutable_dict["pip_packages"]:
504
+ mutable_dict["pip_packages"] = prepend(
505
+ mutable_dict["pip_packages"], "[{}] ".format(envinfo.pip_version)
506
+ )
507
+ if mutable_dict["conda_packages"]:
508
+ mutable_dict["conda_packages"] = prepend(
509
+ mutable_dict["conda_packages"], "[conda] "
510
+ )
511
  return env_info_fmt.format(**mutable_dict)
512
 
513
 
520
  output = get_pretty_env_info()
521
  print(output)
522
 
523
+ if (
524
+ TORCH_AVAILABLE
525
+ and hasattr(torch, "utils")
526
+ and hasattr(torch.utils, "_crash_handler")
527
+ ):
528
  minidump_dir = torch.utils._crash_handler.DEFAULT_MINIDUMP_DIR
529
  if sys.platform == "linux" and os.path.exists(minidump_dir):
530
+ dumps = [
531
+ os.path.join(minidump_dir, dump) for dump in os.listdir(minidump_dir)
532
+ ]
533
  latest = max(dumps, key=os.path.getctime)
534
  ctime = os.path.getctime(latest)
535
+ creation_time = datetime.datetime.fromtimestamp(ctime).strftime(
536
+ "%Y-%m-%d %H:%M:%S"
537
+ )
538
+ msg = (
539
+ "\n*** Detected a minidump at {} created on {}, ".format(
540
+ latest, creation_time
541
+ )
542
+ + "if this is related to your bug please include it when you file a report ***"
543
+ )
544
  print(msg, file=sys.stderr)
545
 
546
 
547
+ if __name__ == "__main__":
 
548
  main()
plot_utils.py CHANGED
@@ -30,7 +30,7 @@ def plot_images(imgs, titles=None, cmaps="gray", dpi=100, size=6, pad=0.5):
30
  if titles:
31
  ax[i].set_title(titles[i])
32
  fig.tight_layout(pad=pad)
33
-
34
  return fig
35
 
36
 
@@ -50,7 +50,7 @@ def plot_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]
@@ -69,7 +69,7 @@ def plot_lines(
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
 
@@ -103,5 +103,5 @@ def plot_color_line_matches(lines, fig, lw=2, indices=(0, 1)):
103
  linewidth=lw,
104
  )
105
  a.add_line(line)
106
-
107
- return fig
30
  if titles:
31
  ax[i].set_title(titles[i])
32
  fig.tight_layout(pad=pad)
33
+
34
  return fig
35
 
36
 
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]
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
 
103
  linewidth=lw,
104
  )
105
  a.add_line(line)
106
+
107
+ return fig
requirements.txt CHANGED
@@ -1,3 +1,3 @@
1
  opencv-python
2
  matplotlib
3
- kornia
1
  opencv-python
2
  matplotlib
3
+ git+https://github.com/kornia/kornia