megadetector 5.0.5__py3-none-any.whl → 5.0.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of megadetector might be problematic. Click here for more details.

Files changed (132) hide show
  1. api/batch_processing/data_preparation/manage_local_batch.py +302 -263
  2. api/batch_processing/data_preparation/manage_video_batch.py +81 -2
  3. api/batch_processing/postprocessing/add_max_conf.py +1 -0
  4. api/batch_processing/postprocessing/categorize_detections_by_size.py +50 -19
  5. api/batch_processing/postprocessing/compare_batch_results.py +110 -60
  6. api/batch_processing/postprocessing/load_api_results.py +56 -70
  7. api/batch_processing/postprocessing/md_to_coco.py +1 -1
  8. api/batch_processing/postprocessing/md_to_labelme.py +2 -1
  9. api/batch_processing/postprocessing/postprocess_batch_results.py +240 -81
  10. api/batch_processing/postprocessing/render_detection_confusion_matrix.py +625 -0
  11. api/batch_processing/postprocessing/repeat_detection_elimination/find_repeat_detections.py +71 -23
  12. api/batch_processing/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +1 -1
  13. api/batch_processing/postprocessing/repeat_detection_elimination/repeat_detections_core.py +227 -75
  14. api/batch_processing/postprocessing/subset_json_detector_output.py +132 -5
  15. api/batch_processing/postprocessing/top_folders_to_bottom.py +1 -1
  16. api/synchronous/api_core/animal_detection_api/detection/run_detector_batch.py +2 -2
  17. classification/prepare_classification_script.py +191 -191
  18. data_management/coco_to_yolo.py +68 -45
  19. data_management/databases/integrity_check_json_db.py +7 -5
  20. data_management/generate_crops_from_cct.py +3 -3
  21. data_management/get_image_sizes.py +8 -6
  22. data_management/importers/add_timestamps_to_icct.py +79 -0
  23. data_management/importers/animl_results_to_md_results.py +160 -0
  24. data_management/importers/auckland_doc_test_to_json.py +4 -4
  25. data_management/importers/auckland_doc_to_json.py +1 -1
  26. data_management/importers/awc_to_json.py +5 -5
  27. data_management/importers/bellevue_to_json.py +5 -5
  28. data_management/importers/carrizo_shrubfree_2018.py +5 -5
  29. data_management/importers/carrizo_trail_cam_2017.py +5 -5
  30. data_management/importers/cct_field_adjustments.py +2 -3
  31. data_management/importers/channel_islands_to_cct.py +4 -4
  32. data_management/importers/ena24_to_json.py +5 -5
  33. data_management/importers/helena_to_cct.py +10 -10
  34. data_management/importers/idaho-camera-traps.py +12 -12
  35. data_management/importers/idfg_iwildcam_lila_prep.py +8 -8
  36. data_management/importers/jb_csv_to_json.py +4 -4
  37. data_management/importers/missouri_to_json.py +1 -1
  38. data_management/importers/noaa_seals_2019.py +1 -1
  39. data_management/importers/pc_to_json.py +5 -5
  40. data_management/importers/prepare-noaa-fish-data-for-lila.py +4 -4
  41. data_management/importers/prepare_zsl_imerit.py +5 -5
  42. data_management/importers/rspb_to_json.py +4 -4
  43. data_management/importers/save_the_elephants_survey_A.py +5 -5
  44. data_management/importers/save_the_elephants_survey_B.py +6 -6
  45. data_management/importers/snapshot_safari_importer.py +9 -9
  46. data_management/importers/snapshot_serengeti_lila.py +9 -9
  47. data_management/importers/timelapse_csv_set_to_json.py +5 -7
  48. data_management/importers/ubc_to_json.py +4 -4
  49. data_management/importers/umn_to_json.py +4 -4
  50. data_management/importers/wellington_to_json.py +1 -1
  51. data_management/importers/wi_to_json.py +2 -2
  52. data_management/importers/zamba_results_to_md_results.py +181 -0
  53. data_management/labelme_to_coco.py +35 -7
  54. data_management/labelme_to_yolo.py +229 -0
  55. data_management/lila/add_locations_to_island_camera_traps.py +1 -1
  56. data_management/lila/add_locations_to_nacti.py +147 -0
  57. data_management/lila/create_lila_blank_set.py +474 -0
  58. data_management/lila/create_lila_test_set.py +2 -1
  59. data_management/lila/create_links_to_md_results_files.py +106 -0
  60. data_management/lila/download_lila_subset.py +46 -21
  61. data_management/lila/generate_lila_per_image_labels.py +23 -14
  62. data_management/lila/get_lila_annotation_counts.py +17 -11
  63. data_management/lila/lila_common.py +14 -11
  64. data_management/lila/test_lila_metadata_urls.py +116 -0
  65. data_management/ocr_tools.py +829 -0
  66. data_management/resize_coco_dataset.py +13 -11
  67. data_management/yolo_output_to_md_output.py +84 -12
  68. data_management/yolo_to_coco.py +38 -20
  69. detection/process_video.py +36 -14
  70. detection/pytorch_detector.py +23 -8
  71. detection/run_detector.py +76 -19
  72. detection/run_detector_batch.py +178 -63
  73. detection/run_inference_with_yolov5_val.py +326 -57
  74. detection/run_tiled_inference.py +153 -43
  75. detection/video_utils.py +34 -8
  76. md_utils/ct_utils.py +172 -1
  77. md_utils/md_tests.py +372 -51
  78. md_utils/path_utils.py +167 -39
  79. md_utils/process_utils.py +26 -7
  80. md_utils/split_locations_into_train_val.py +215 -0
  81. md_utils/string_utils.py +10 -0
  82. md_utils/url_utils.py +0 -2
  83. md_utils/write_html_image_list.py +9 -26
  84. md_visualization/plot_utils.py +12 -8
  85. md_visualization/visualization_utils.py +106 -7
  86. md_visualization/visualize_db.py +16 -8
  87. md_visualization/visualize_detector_output.py +208 -97
  88. {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/METADATA +3 -6
  89. {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/RECORD +98 -121
  90. {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/WHEEL +1 -1
  91. taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +1 -1
  92. taxonomy_mapping/map_new_lila_datasets.py +43 -39
  93. taxonomy_mapping/prepare_lila_taxonomy_release.py +5 -2
  94. taxonomy_mapping/preview_lila_taxonomy.py +27 -27
  95. taxonomy_mapping/species_lookup.py +33 -13
  96. taxonomy_mapping/taxonomy_csv_checker.py +7 -5
  97. api/synchronous/api_core/yolov5/detect.py +0 -252
  98. api/synchronous/api_core/yolov5/export.py +0 -607
  99. api/synchronous/api_core/yolov5/hubconf.py +0 -146
  100. api/synchronous/api_core/yolov5/models/__init__.py +0 -0
  101. api/synchronous/api_core/yolov5/models/common.py +0 -738
  102. api/synchronous/api_core/yolov5/models/experimental.py +0 -104
  103. api/synchronous/api_core/yolov5/models/tf.py +0 -574
  104. api/synchronous/api_core/yolov5/models/yolo.py +0 -338
  105. api/synchronous/api_core/yolov5/train.py +0 -670
  106. api/synchronous/api_core/yolov5/utils/__init__.py +0 -36
  107. api/synchronous/api_core/yolov5/utils/activations.py +0 -103
  108. api/synchronous/api_core/yolov5/utils/augmentations.py +0 -284
  109. api/synchronous/api_core/yolov5/utils/autoanchor.py +0 -170
  110. api/synchronous/api_core/yolov5/utils/autobatch.py +0 -66
  111. api/synchronous/api_core/yolov5/utils/aws/__init__.py +0 -0
  112. api/synchronous/api_core/yolov5/utils/aws/resume.py +0 -40
  113. api/synchronous/api_core/yolov5/utils/benchmarks.py +0 -148
  114. api/synchronous/api_core/yolov5/utils/callbacks.py +0 -71
  115. api/synchronous/api_core/yolov5/utils/dataloaders.py +0 -1087
  116. api/synchronous/api_core/yolov5/utils/downloads.py +0 -178
  117. api/synchronous/api_core/yolov5/utils/flask_rest_api/example_request.py +0 -19
  118. api/synchronous/api_core/yolov5/utils/flask_rest_api/restapi.py +0 -46
  119. api/synchronous/api_core/yolov5/utils/general.py +0 -1018
  120. api/synchronous/api_core/yolov5/utils/loggers/__init__.py +0 -187
  121. api/synchronous/api_core/yolov5/utils/loggers/wandb/__init__.py +0 -0
  122. api/synchronous/api_core/yolov5/utils/loggers/wandb/log_dataset.py +0 -27
  123. api/synchronous/api_core/yolov5/utils/loggers/wandb/sweep.py +0 -41
  124. api/synchronous/api_core/yolov5/utils/loggers/wandb/wandb_utils.py +0 -577
  125. api/synchronous/api_core/yolov5/utils/loss.py +0 -234
  126. api/synchronous/api_core/yolov5/utils/metrics.py +0 -355
  127. api/synchronous/api_core/yolov5/utils/plots.py +0 -489
  128. api/synchronous/api_core/yolov5/utils/torch_utils.py +0 -314
  129. api/synchronous/api_core/yolov5/val.py +0 -394
  130. md_utils/matlab_porting_tools.py +0 -97
  131. {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/LICENSE +0 -0
  132. {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/top_level.txt +0 -0
@@ -8,16 +8,13 @@
8
8
  # Each "filename" can also be a dict with elements 'filename','title',
9
9
  # 'imageStyle','textStyle', 'linkTarget'
10
10
  #
11
- # Strips directory information away if options.makeRelative == 1.
12
- #
13
- # Tries to convert absolute to relative paths if options.makeRelative == 2.
14
- #
15
11
  ########
16
12
 
17
13
  #%% Constants and imports
18
14
 
19
15
  import os
20
16
  import math
17
+ import urllib
21
18
 
22
19
  from md_utils import path_utils
23
20
 
@@ -39,12 +36,12 @@ def write_html_image_list(filename=None,images=None,options=None):
39
36
  options: a dict with one or more of the following fields:
40
37
 
41
38
  fHtml
42
- makeRelative
43
39
  headerHtml
44
40
  trailerHtml
45
41
  defaultTextStyle
46
42
  defaultImageStyle
47
43
  maxFiguresPerHtmlFile
44
+ urlEncodeFilenames (default True, e.g. '#' will be replaced by '%23')
48
45
 
49
46
  """
50
47
 
@@ -55,9 +52,6 @@ def write_html_image_list(filename=None,images=None,options=None):
55
52
  if 'fHtml' not in options:
56
53
  options['fHtml'] = -1
57
54
 
58
- if 'makeRelative' not in options:
59
- options['makeRelative'] = 0
60
-
61
55
  if 'headerHtml' not in options or options['headerHtml'] is None:
62
56
  options['headerHtml'] = ''
63
57
 
@@ -71,6 +65,9 @@ def write_html_image_list(filename=None,images=None,options=None):
71
65
  if 'defaultImageStyle' not in options or options['defaultImageStyle'] is None:
72
66
  options['defaultImageStyle'] = \
73
67
  "margin:0px;margin-top:5px;margin-bottom:5px;"
68
+
69
+ if 'urlEncodeFilenames' not in options or options['urlEncodeFilenames'] is None:
70
+ options['urlEncodeFilenames'] = True
74
71
 
75
72
  # Possibly split the html output for figures into multiple files; Chrome gets sad with
76
73
  # thousands of images in a single tab.
@@ -98,24 +95,6 @@ def write_html_image_list(filename=None,images=None,options=None):
98
95
  imageInfo['textStyle'] = options['defaultTextStyle']
99
96
  images[iImage] = imageInfo
100
97
 
101
- # Remove leading directory information from filenames if requested
102
- if options['makeRelative'] == 1:
103
-
104
- for iImage in range(0,len(images)):
105
- _,n,e = path_utils.fileparts(images[iImage]['filename'])
106
- images[iImage]['filename'] = n + e
107
-
108
- elif options['makeRelative'] == 2:
109
-
110
- baseDir,_,_ = path_utils.fileparts(filename)
111
- if len(baseDir) > 1 and baseDir[-1] != '\\':
112
- baseDir = baseDir + '\\'
113
-
114
- for iImage in range(0,len(images)):
115
- fn = images[iImage]['filename']
116
- fn = fn.replace(baseDir,'')
117
- images[iImage]['filename'] = fn
118
-
119
98
  nImages = len(images)
120
99
 
121
100
  # If we need to break this up into multiple files...
@@ -197,6 +176,10 @@ def write_html_image_list(filename=None,images=None,options=None):
197
176
  title = title.encode('ascii','ignore').decode('ascii')
198
177
  filename = filename.encode('ascii','ignore').decode('ascii')
199
178
 
179
+ if options['urlEncodeFilenames']:
180
+ filename = filename.replace('\\','/')
181
+ filename = urllib.parse.quote(filename)
182
+
200
183
  if len(title) > 0:
201
184
  fHtml.write(
202
185
  '<p style="{}">{}</p>\n'\
@@ -28,8 +28,9 @@ def plot_confusion_matrix(
28
28
  cmap: Union[str, matplotlib.colors.Colormap] = matplotlib.cm.Blues,
29
29
  vmax: Optional[float] = None,
30
30
  use_colorbar: bool = True,
31
- y_label: bool = True,
32
- fmt: str = '{:.0f}'
31
+ y_label: bool = True,
32
+ fmt: str = '{:.0f}',
33
+ fig=None
33
34
  ) -> matplotlib.figure.Figure:
34
35
  """
35
36
  Plot a confusion matrix. By default, assumes values in the given matrix
@@ -56,18 +57,20 @@ def plot_confusion_matrix(
56
57
  assert matrix.shape[1] == num_classes
57
58
  assert len(classes) == num_classes
58
59
 
60
+ normalized_matrix = matrix.astype(np.float64) / (
61
+ matrix.sum(axis=1, keepdims=True) + 1e-7)
59
62
  if normalize:
60
- matrix = matrix.astype(np.float64) / (
61
- matrix.sum(axis=1, keepdims=True) + 1e-7)
63
+ matrix = normalized_matrix
62
64
 
63
65
  fig_h = 3 + 0.3 * num_classes
64
66
  fig_w = fig_h
65
67
  if use_colorbar:
66
68
  fig_w += 0.5
67
69
 
68
- fig = matplotlib.figure.Figure(figsize=(fig_w, fig_h), tight_layout=True)
70
+ if fig is None:
71
+ fig = matplotlib.figure.Figure(figsize=(fig_w, fig_h), tight_layout=True)
69
72
  ax = fig.subplots(1, 1)
70
- im = ax.imshow(matrix, interpolation='nearest', cmap=cmap, vmax=vmax)
73
+ im = ax.imshow(normalized_matrix, interpolation='nearest', cmap=cmap, vmax=vmax)
71
74
  ax.set_title(title)
72
75
 
73
76
  if use_colorbar:
@@ -86,10 +89,11 @@ def plot_confusion_matrix(
86
89
  ax.set_ylabel('Ground-truth class')
87
90
 
88
91
  for i, j in np.ndindex(matrix.shape):
89
- ax.text(j, i, fmt.format(matrix[i, j] * 100),
92
+ v = matrix[i, j]
93
+ ax.text(j, i, fmt.format(v),
90
94
  horizontalalignment='center',
91
95
  verticalalignment='center',
92
- color='white' if matrix[i, j] > 0.5 else 'black')
96
+ color='white' if normalized_matrix[i, j] > 0.5 else 'black')
93
97
 
94
98
  return fig
95
99
 
@@ -166,13 +166,26 @@ def load_image(input_file: Union[str, BytesIO]) -> Image:
166
166
  return image
167
167
 
168
168
 
169
- def resize_image(image, target_width, target_height=-1):
169
+ def resize_image(image, target_width, target_height=-1, output_file=None):
170
170
  """
171
171
  Resizes a PIL image object to the specified width and height; does not resize
172
172
  in place. If either width or height are -1, resizes with aspect ratio preservation.
173
173
  If both are -1, returns the original image (does not copy in this case).
174
+
175
+ None is equivalent to -1 for target_width and target_height.
176
+
177
+ [image] can be a PIL image or a filename.
174
178
  """
175
179
 
180
+ if isinstance(image,str):
181
+ image = load_image(image)
182
+
183
+ if target_width is None:
184
+ target_width = -1
185
+
186
+ if target_height is None:
187
+ target_height = -1
188
+
176
189
  # Null operation
177
190
  if target_width == -1 and target_height == -1:
178
191
  return image
@@ -197,6 +210,9 @@ def resize_image(image, target_width, target_height=-1):
197
210
  except:
198
211
  resized_image = image.resize((target_width, target_height), Image.Resampling.LANCZOS)
199
212
 
213
+ if output_file is not None:
214
+ exif_preserving_save(resized_image,output_file)
215
+
200
216
  return resized_image
201
217
 
202
218
 
@@ -363,7 +379,8 @@ def render_detection_bounding_boxes(detections, image,
363
379
  The type of the numerical label (default string) needs to be consistent with the keys in
364
380
  label_map; no casting is carried out. If this is None, no classification labels are shown.
365
381
 
366
- confidence_threshold: optional, threshold above which the bounding box is rendered.
382
+ confidence_threshold: optional, threshold above which boxes are rendered. Can also be a dictionary
383
+ mapping category IDs to thresholds.
367
384
 
368
385
  thickness: line thickness in pixels. Default value is 4.
369
386
 
@@ -397,9 +414,15 @@ def render_detection_bounding_boxes(detections, image,
397
414
 
398
415
  score = detection['conf']
399
416
 
417
+ if isinstance(confidence_threshold,dict):
418
+ rendering_threshold = confidence_threshold[detection['category']]
419
+ else:
420
+ rendering_threshold = confidence_threshold
421
+
422
+
400
423
  # Always render objects with a confidence of "None", this is typically used
401
424
  # for ground truth data.
402
- if score is None or score >= confidence_threshold:
425
+ if score is None or score >= rendering_threshold:
403
426
 
404
427
  x1, y1, w_box, h_box = detection['bbox']
405
428
  display_boxes.append([y1, x1, y1 + h_box, x1 + w_box])
@@ -784,7 +807,8 @@ def draw_bounding_boxes_on_file(input_file, output_file, detections, confidence_
784
807
  detector_label_map=DEFAULT_DETECTOR_LABEL_MAP,
785
808
  thickness=DEFAULT_BOX_THICKNESS, expansion=0,
786
809
  colormap=DEFAULT_COLORS,
787
- custom_strings=None):
810
+ label_font_size=DEFAULT_LABEL_FONT_SIZE,
811
+ custom_strings=None,target_size=None):
788
812
  """
789
813
  Render detection bounding boxes on an image loaded from file, writing the results to a
790
814
  new image file.
@@ -804,15 +828,21 @@ def draw_bounding_boxes_on_file(input_file, output_file, detections, confidence_
804
828
  custom_strings: optional set of strings to append to detection labels, should have the
805
829
  same length as [detections]. Appended before classification labels, if classification
806
830
  data is provided.
831
+
832
+ target_size: tuple of (target_width,target_height). Either or both can be -1,
833
+ see resize_image for documentation. If None or (-1,-1), uses the original image size.
807
834
  """
808
835
 
809
836
  image = open_image(input_file)
810
-
837
+
838
+ if target_size is not None:
839
+ image = resize_image(image,target_size[0],target_size[1])
840
+
811
841
  render_detection_bounding_boxes(
812
842
  detections, image, label_map=detector_label_map,
813
843
  confidence_threshold=confidence_threshold,
814
844
  thickness=thickness,expansion=expansion,colormap=colormap,
815
- custom_strings=custom_strings)
845
+ custom_strings=custom_strings,label_font_size=label_font_size)
816
846
 
817
847
  image.save(output_file)
818
848
 
@@ -838,4 +868,73 @@ def draw_db_boxes_on_file(input_file, output_file, boxes, classes=None,
838
868
 
839
869
  image.save(output_file)
840
870
 
841
-
871
+
872
+ def gray_scale_fraction(image,crop_size=(0.1,0.1)):
873
+ """
874
+ Returns the fraction of the pixels in [image] that appear to be grayscale (R==G==B),
875
+ useful for approximating whether this is a night-time image when flash information is not
876
+ available in EXIF data (or for video frames, where this information is often not available
877
+ in structured metadata at all).
878
+
879
+ [image] can be a PIL image or a file name.
880
+
881
+ crop_size should be a 2-element list/tuple, representing the fraction of the image
882
+ to crop at the top and bottom, respectively, before analyzing (to minimize the possibility
883
+ of including color elements in the image chrome).
884
+ """
885
+
886
+ if isinstance(image,str):
887
+ image = Image.open(image)
888
+
889
+ if image.mode == 'L':
890
+ return 1.0
891
+
892
+ if len(image.getbands()) == 1:
893
+ return 1.0
894
+
895
+ # Crop if necessary
896
+ if crop_size[0] > 0 or crop_size[1] > 0:
897
+
898
+ assert (crop_size[0] + crop_size[1]) < 1.0, \
899
+ print('Illegal crop size: {}'.format(str(crop_size)))
900
+
901
+ top_crop_pixels = int(image.height * crop_size[0])
902
+ bottom_crop_pixels = int(image.height * crop_size[1])
903
+
904
+ left = 0
905
+ right = image.width
906
+
907
+ # Remove pixels from the top
908
+ first_crop_top = top_crop_pixels
909
+ first_crop_bottom = image.height
910
+ first_crop = image.crop((left, first_crop_top, right, first_crop_bottom))
911
+
912
+ # Remove pixels from the bottom
913
+ second_crop_top = 0
914
+ second_crop_bottom = first_crop.height - bottom_crop_pixels
915
+ second_crop = first_crop.crop((left, second_crop_top, right, second_crop_bottom))
916
+
917
+ image = second_crop
918
+
919
+ # It doesn't matter if these are actually R/G/B, they're just names
920
+ r = np.array(image.getchannel(0))
921
+ g = np.array(image.getchannel(1))
922
+ b = np.array(image.getchannel(2))
923
+
924
+ gray_pixels = np.logical_and(r == g, r == b)
925
+ n_pixels = gray_pixels.size
926
+ n_gray_pixels = gray_pixels.sum()
927
+
928
+ return n_gray_pixels / n_pixels
929
+
930
+ # Non-numpy way to do the same thing, briefly keeping this here for posterity
931
+ if False:
932
+
933
+ w, h = image.size
934
+ n_pixels = w*h
935
+ n_gray_pixels = 0
936
+ for i in range(w):
937
+ for j in range(h):
938
+ r, g, b = image.getpixel((i,j))
939
+ if r == g and r == b and g == b:
940
+ n_gray_pixels += 1
@@ -3,7 +3,7 @@
3
3
  # visualize_db.py
4
4
  #
5
5
  # Outputs an HTML page visualizing annotations (class labels and/or bounding boxes)
6
- # on a sample of images in a database in the COCO Camera Traps format
6
+ # on a sample of images in a database in the COCO Camera Traps format.
7
7
  #
8
8
  ########
9
9
 
@@ -41,7 +41,15 @@ class DbVizOptions:
41
41
  #
42
42
  # If viz_size is None or (-1,-1), the original image size is used.
43
43
  viz_size = (675, -1)
44
+
45
+ # The most relevant option one might want to set here is:
46
+ #
47
+ # htmlOptions['maxFiguresPerHtmlFile']
48
+ #
49
+ # ...which can be used to paginate previews to a number of images that will load well
50
+ # in a browser (5000 is a reasonable limit).
44
51
  htmlOptions = write_html_image_list()
52
+
45
53
  sort_by_filename = True
46
54
  trim_to_images_with_bboxes = False
47
55
 
@@ -96,7 +104,7 @@ def image_filename_to_path(image_file_name, image_base_dir, pathsep_replacement=
96
104
 
97
105
  #%% Core functions
98
106
 
99
- def process_images(db_path, output_dir, image_base_dir, options=None):
107
+ def visualize_db(db_path, output_dir, image_base_dir, options=None):
100
108
  """
101
109
  Writes images and html to output_dir to visualize the annotations in the json file
102
110
  db_path.
@@ -418,7 +426,7 @@ def process_images(db_path, output_dir, image_base_dir, options=None):
418
426
 
419
427
  return htmlOutputFile,image_db
420
428
 
421
- # def process_images(...)
429
+ # def visualize_db(...)
422
430
 
423
431
 
424
432
  #%% Command-line driver
@@ -452,7 +460,8 @@ def main():
452
460
  parser.add_argument('--random_seed', action='store', type=int, default=None,
453
461
  help='Random seed for image selection')
454
462
  parser.add_argument('--pathsep_replacement', action='store', type=str, default='',
455
- help='Replace path separators in relative filenames with another character (frequently ~)')
463
+ help='Replace path separators in relative filenames with another ' + \
464
+ 'character (frequently ~)')
456
465
 
457
466
  if len(sys.argv[1:]) == 0:
458
467
  parser.print_help()
@@ -466,7 +475,7 @@ def main():
466
475
  if options.random_sort:
467
476
  options.sort_by_filename = False
468
477
 
469
- process_images(options.db_path,options.output_dir,options.image_base_dir,options)
478
+ visualize_db(options.db_path,options.output_dir,options.image_base_dir,options)
470
479
 
471
480
 
472
481
  if __name__ == '__main__':
@@ -474,7 +483,7 @@ if __name__ == '__main__':
474
483
  main()
475
484
 
476
485
 
477
- #%% Interactive driver(s)
486
+ #%% Interactive driver
478
487
 
479
488
  if False:
480
489
 
@@ -487,6 +496,5 @@ if False:
487
496
  options = DbVizOptions()
488
497
  options.num_to_visualize = 100
489
498
 
490
- htmlOutputFile,db = process_images(db_path,output_dir,image_base_dir,options)
499
+ htmlOutputFile,db = visualize_db(db_path,output_dir,image_base_dir,options)
491
500
  # os.startfile(htmlOutputFile)
492
-