megadetector 5.0.27__py3-none-any.whl → 5.0.29__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 (176) hide show
  1. megadetector/api/batch_processing/api_core/batch_service/score.py +4 -5
  2. megadetector/api/batch_processing/api_core_support/aggregate_results_manually.py +1 -1
  3. megadetector/api/batch_processing/api_support/summarize_daily_activity.py +1 -1
  4. megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +2 -2
  5. megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +1 -1
  6. megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +1 -1
  7. megadetector/api/synchronous/api_core/tests/load_test.py +2 -3
  8. megadetector/classification/aggregate_classifier_probs.py +3 -3
  9. megadetector/classification/analyze_failed_images.py +5 -5
  10. megadetector/classification/cache_batchapi_outputs.py +5 -5
  11. megadetector/classification/create_classification_dataset.py +11 -12
  12. megadetector/classification/crop_detections.py +10 -10
  13. megadetector/classification/csv_to_json.py +8 -8
  14. megadetector/classification/detect_and_crop.py +13 -15
  15. megadetector/classification/evaluate_model.py +7 -7
  16. megadetector/classification/identify_mislabeled_candidates.py +6 -6
  17. megadetector/classification/json_to_azcopy_list.py +1 -1
  18. megadetector/classification/json_validator.py +29 -32
  19. megadetector/classification/map_classification_categories.py +9 -9
  20. megadetector/classification/merge_classification_detection_output.py +12 -9
  21. megadetector/classification/prepare_classification_script.py +19 -19
  22. megadetector/classification/prepare_classification_script_mc.py +23 -23
  23. megadetector/classification/run_classifier.py +4 -4
  24. megadetector/classification/save_mislabeled.py +6 -6
  25. megadetector/classification/train_classifier.py +1 -1
  26. megadetector/classification/train_classifier_tf.py +9 -9
  27. megadetector/classification/train_utils.py +10 -10
  28. megadetector/data_management/annotations/annotation_constants.py +1 -1
  29. megadetector/data_management/camtrap_dp_to_coco.py +45 -45
  30. megadetector/data_management/cct_json_utils.py +101 -101
  31. megadetector/data_management/cct_to_md.py +49 -49
  32. megadetector/data_management/cct_to_wi.py +33 -33
  33. megadetector/data_management/coco_to_labelme.py +75 -75
  34. megadetector/data_management/coco_to_yolo.py +189 -189
  35. megadetector/data_management/databases/add_width_and_height_to_db.py +3 -2
  36. megadetector/data_management/databases/combine_coco_camera_traps_files.py +38 -38
  37. megadetector/data_management/databases/integrity_check_json_db.py +202 -188
  38. megadetector/data_management/databases/subset_json_db.py +33 -33
  39. megadetector/data_management/generate_crops_from_cct.py +38 -38
  40. megadetector/data_management/get_image_sizes.py +54 -49
  41. megadetector/data_management/labelme_to_coco.py +130 -124
  42. megadetector/data_management/labelme_to_yolo.py +78 -72
  43. megadetector/data_management/lila/create_lila_blank_set.py +81 -83
  44. megadetector/data_management/lila/create_lila_test_set.py +32 -31
  45. megadetector/data_management/lila/create_links_to_md_results_files.py +18 -18
  46. megadetector/data_management/lila/download_lila_subset.py +21 -24
  47. megadetector/data_management/lila/generate_lila_per_image_labels.py +91 -91
  48. megadetector/data_management/lila/get_lila_annotation_counts.py +30 -30
  49. megadetector/data_management/lila/get_lila_image_counts.py +22 -22
  50. megadetector/data_management/lila/lila_common.py +70 -70
  51. megadetector/data_management/lila/test_lila_metadata_urls.py +13 -14
  52. megadetector/data_management/mewc_to_md.py +339 -340
  53. megadetector/data_management/ocr_tools.py +258 -252
  54. megadetector/data_management/read_exif.py +232 -223
  55. megadetector/data_management/remap_coco_categories.py +26 -26
  56. megadetector/data_management/remove_exif.py +31 -20
  57. megadetector/data_management/rename_images.py +187 -187
  58. megadetector/data_management/resize_coco_dataset.py +41 -41
  59. megadetector/data_management/speciesnet_to_md.py +41 -41
  60. megadetector/data_management/wi_download_csv_to_coco.py +55 -55
  61. megadetector/data_management/yolo_output_to_md_output.py +117 -120
  62. megadetector/data_management/yolo_to_coco.py +195 -188
  63. megadetector/detection/change_detection.py +831 -0
  64. megadetector/detection/process_video.py +341 -338
  65. megadetector/detection/pytorch_detector.py +308 -266
  66. megadetector/detection/run_detector.py +186 -166
  67. megadetector/detection/run_detector_batch.py +366 -364
  68. megadetector/detection/run_inference_with_yolov5_val.py +328 -325
  69. megadetector/detection/run_tiled_inference.py +312 -253
  70. megadetector/detection/tf_detector.py +24 -24
  71. megadetector/detection/video_utils.py +291 -283
  72. megadetector/postprocessing/add_max_conf.py +15 -11
  73. megadetector/postprocessing/categorize_detections_by_size.py +44 -44
  74. megadetector/postprocessing/classification_postprocessing.py +808 -311
  75. megadetector/postprocessing/combine_batch_outputs.py +20 -21
  76. megadetector/postprocessing/compare_batch_results.py +528 -517
  77. megadetector/postprocessing/convert_output_format.py +97 -97
  78. megadetector/postprocessing/create_crop_folder.py +220 -147
  79. megadetector/postprocessing/detector_calibration.py +173 -168
  80. megadetector/postprocessing/generate_csv_report.py +508 -0
  81. megadetector/postprocessing/load_api_results.py +25 -22
  82. megadetector/postprocessing/md_to_coco.py +129 -98
  83. megadetector/postprocessing/md_to_labelme.py +89 -83
  84. megadetector/postprocessing/md_to_wi.py +40 -40
  85. megadetector/postprocessing/merge_detections.py +87 -114
  86. megadetector/postprocessing/postprocess_batch_results.py +319 -302
  87. megadetector/postprocessing/remap_detection_categories.py +36 -36
  88. megadetector/postprocessing/render_detection_confusion_matrix.py +205 -199
  89. megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +57 -57
  90. megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +27 -28
  91. megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +702 -677
  92. megadetector/postprocessing/separate_detections_into_folders.py +226 -211
  93. megadetector/postprocessing/subset_json_detector_output.py +265 -262
  94. megadetector/postprocessing/top_folders_to_bottom.py +45 -45
  95. megadetector/postprocessing/validate_batch_results.py +70 -70
  96. megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +52 -52
  97. megadetector/taxonomy_mapping/map_new_lila_datasets.py +15 -15
  98. megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +14 -14
  99. megadetector/taxonomy_mapping/preview_lila_taxonomy.py +66 -69
  100. megadetector/taxonomy_mapping/retrieve_sample_image.py +16 -16
  101. megadetector/taxonomy_mapping/simple_image_download.py +8 -8
  102. megadetector/taxonomy_mapping/species_lookup.py +33 -33
  103. megadetector/taxonomy_mapping/taxonomy_csv_checker.py +14 -14
  104. megadetector/taxonomy_mapping/taxonomy_graph.py +11 -11
  105. megadetector/taxonomy_mapping/validate_lila_category_mappings.py +13 -13
  106. megadetector/utils/azure_utils.py +22 -22
  107. megadetector/utils/ct_utils.py +1019 -200
  108. megadetector/utils/directory_listing.py +21 -77
  109. megadetector/utils/gpu_test.py +22 -22
  110. megadetector/utils/md_tests.py +541 -518
  111. megadetector/utils/path_utils.py +1511 -406
  112. megadetector/utils/process_utils.py +41 -41
  113. megadetector/utils/sas_blob_utils.py +53 -49
  114. megadetector/utils/split_locations_into_train_val.py +73 -60
  115. megadetector/utils/string_utils.py +147 -26
  116. megadetector/utils/url_utils.py +463 -173
  117. megadetector/utils/wi_utils.py +2629 -2868
  118. megadetector/utils/write_html_image_list.py +137 -137
  119. megadetector/visualization/plot_utils.py +21 -21
  120. megadetector/visualization/render_images_with_thumbnails.py +37 -73
  121. megadetector/visualization/visualization_utils.py +424 -404
  122. megadetector/visualization/visualize_db.py +197 -190
  123. megadetector/visualization/visualize_detector_output.py +126 -98
  124. {megadetector-5.0.27.dist-info → megadetector-5.0.29.dist-info}/METADATA +6 -3
  125. megadetector-5.0.29.dist-info/RECORD +163 -0
  126. {megadetector-5.0.27.dist-info → megadetector-5.0.29.dist-info}/WHEEL +1 -1
  127. megadetector/data_management/importers/add_nacti_sizes.py +0 -52
  128. megadetector/data_management/importers/add_timestamps_to_icct.py +0 -79
  129. megadetector/data_management/importers/animl_results_to_md_results.py +0 -158
  130. megadetector/data_management/importers/auckland_doc_test_to_json.py +0 -373
  131. megadetector/data_management/importers/auckland_doc_to_json.py +0 -201
  132. megadetector/data_management/importers/awc_to_json.py +0 -191
  133. megadetector/data_management/importers/bellevue_to_json.py +0 -272
  134. megadetector/data_management/importers/cacophony-thermal-importer.py +0 -793
  135. megadetector/data_management/importers/carrizo_shrubfree_2018.py +0 -269
  136. megadetector/data_management/importers/carrizo_trail_cam_2017.py +0 -289
  137. megadetector/data_management/importers/cct_field_adjustments.py +0 -58
  138. megadetector/data_management/importers/channel_islands_to_cct.py +0 -913
  139. megadetector/data_management/importers/eMammal/copy_and_unzip_emammal.py +0 -180
  140. megadetector/data_management/importers/eMammal/eMammal_helpers.py +0 -249
  141. megadetector/data_management/importers/eMammal/make_eMammal_json.py +0 -223
  142. megadetector/data_management/importers/ena24_to_json.py +0 -276
  143. megadetector/data_management/importers/filenames_to_json.py +0 -386
  144. megadetector/data_management/importers/helena_to_cct.py +0 -283
  145. megadetector/data_management/importers/idaho-camera-traps.py +0 -1407
  146. megadetector/data_management/importers/idfg_iwildcam_lila_prep.py +0 -294
  147. megadetector/data_management/importers/import_desert_lion_conservation_camera_traps.py +0 -387
  148. megadetector/data_management/importers/jb_csv_to_json.py +0 -150
  149. megadetector/data_management/importers/mcgill_to_json.py +0 -250
  150. megadetector/data_management/importers/missouri_to_json.py +0 -490
  151. megadetector/data_management/importers/nacti_fieldname_adjustments.py +0 -79
  152. megadetector/data_management/importers/noaa_seals_2019.py +0 -181
  153. megadetector/data_management/importers/osu-small-animals-to-json.py +0 -364
  154. megadetector/data_management/importers/pc_to_json.py +0 -365
  155. megadetector/data_management/importers/plot_wni_giraffes.py +0 -123
  156. megadetector/data_management/importers/prepare_zsl_imerit.py +0 -131
  157. megadetector/data_management/importers/raic_csv_to_md_results.py +0 -416
  158. megadetector/data_management/importers/rspb_to_json.py +0 -356
  159. megadetector/data_management/importers/save_the_elephants_survey_A.py +0 -320
  160. megadetector/data_management/importers/save_the_elephants_survey_B.py +0 -329
  161. megadetector/data_management/importers/snapshot_safari_importer.py +0 -758
  162. megadetector/data_management/importers/snapshot_serengeti_lila.py +0 -1067
  163. megadetector/data_management/importers/snapshotserengeti/make_full_SS_json.py +0 -150
  164. megadetector/data_management/importers/snapshotserengeti/make_per_season_SS_json.py +0 -153
  165. megadetector/data_management/importers/sulross_get_exif.py +0 -65
  166. megadetector/data_management/importers/timelapse_csv_set_to_json.py +0 -490
  167. megadetector/data_management/importers/ubc_to_json.py +0 -399
  168. megadetector/data_management/importers/umn_to_json.py +0 -507
  169. megadetector/data_management/importers/wellington_to_json.py +0 -263
  170. megadetector/data_management/importers/wi_to_json.py +0 -442
  171. megadetector/data_management/importers/zamba_results_to_md_results.py +0 -180
  172. megadetector/data_management/lila/add_locations_to_island_camera_traps.py +0 -101
  173. megadetector/data_management/lila/add_locations_to_nacti.py +0 -151
  174. megadetector-5.0.27.dist-info/RECORD +0 -208
  175. {megadetector-5.0.27.dist-info → megadetector-5.0.29.dist-info}/licenses/LICENSE +0 -0
  176. {megadetector-5.0.27.dist-info → megadetector-5.0.29.dist-info}/top_level.txt +0 -0
@@ -30,9 +30,9 @@ def resize_coco_dataset(input_folder,input_filename,
30
30
  """
31
31
  Given a COCO-formatted dataset (images in input_folder, data in input_filename), resizes
32
32
  all the images to a target size (in output_folder) and scales bounding boxes accordingly.
33
-
33
+
34
34
  Args:
35
- input_folder (str): the folder where images live; filenames in [input_filename] should
35
+ input_folder (str): the folder where images live; filenames in [input_filename] should
36
36
  be relative to [input_folder]
37
37
  input_filename (str): the (input) COCO-formatted .json file containing annotations
38
38
  output_folder (str): the folder to which we should write resized images; can be the
@@ -40,51 +40,51 @@ def resize_coco_dataset(input_folder,input_filename,
40
40
  output_filename (str): the COCO-formatted .json file we should generate that refers to
41
41
  the resized images
42
42
  target_size (list or tuple of ints): this should be tuple/list of ints, with length 2 (w,h).
43
- If either dimension is -1, aspect ratio will be preserved. If both dimensions are -1, this means
44
- "keep the original size". If both dimensions are -1 and correct_size_image_handling is copy, this
45
- function is basically a no-op.
46
- correct_size_image_handling (str): can be 'copy' (in which case the original image is just copied
43
+ If either dimension is -1, aspect ratio will be preserved. If both dimensions are -1, this means
44
+ "keep the original size". If both dimensions are -1 and correct_size_image_handling is copy, this
45
+ function is basically a no-op.
46
+ correct_size_image_handling (str): can be 'copy' (in which case the original image is just copied
47
47
  to the output folder) or 'rewrite' (in which case the image is opened via PIL and re-written,
48
- attempting to preserve the same quality). The only reason to do use 'rewrite' 'is the case where
49
- you're superstitious about biases coming from images in a training set being written by different
48
+ attempting to preserve the same quality). The only reason to do use 'rewrite' 'is the case where
49
+ you're superstitious about biases coming from images in a training set being written by different
50
50
  image encoders.
51
-
51
+
52
52
  Returns:
53
53
  dict: the COCO database with resized images, identical to the content of [output_filename]
54
54
  """
55
-
55
+
56
56
  # Read input data
57
57
  with open(input_filename,'r') as f:
58
58
  d = json.load(f)
59
-
59
+
60
60
  # Map image IDs to annotations
61
61
  image_id_to_annotations = defaultdict(list)
62
62
  for ann in d['annotations']:
63
63
  image_id_to_annotations[ann['image_id']].append(ann)
64
-
64
+
65
65
  # For each image
66
-
66
+
67
67
  # TODO: this is trivially parallelizable
68
68
  #
69
69
  # im = d['images'][0]
70
70
  for im in tqdm(d['images']):
71
-
71
+
72
72
  input_fn_relative = im['file_name']
73
73
  input_fn_abs = os.path.join(input_folder,input_fn_relative)
74
74
  assert os.path.isfile(input_fn_abs), "Can't find image file {}".format(input_fn_abs)
75
-
75
+
76
76
  output_fn_abs = os.path.join(output_folder,input_fn_relative)
77
77
  os.makedirs(os.path.dirname(output_fn_abs),exist_ok=True)
78
-
78
+
79
79
  pil_im = open_image(input_fn_abs)
80
80
  input_w = pil_im.width
81
81
  input_h = pil_im.height
82
-
82
+
83
83
  image_is_already_target_size = \
84
84
  (input_w == target_size[0]) and (input_h == target_size[1])
85
85
  preserve_original_size = \
86
86
  (target_size[0] == -1) and (target_size[1] == -1)
87
-
87
+
88
88
  # If the image is already the right size...
89
89
  if (image_is_already_target_size or preserve_original_size):
90
90
  output_w = input_w
@@ -104,18 +104,18 @@ def resize_coco_dataset(input_folder,input_filename,
104
104
 
105
105
  im['width'] = output_w
106
106
  im['height'] = output_h
107
-
107
+
108
108
  # For each box
109
109
  annotations_this_image = image_id_to_annotations[im['id']]
110
-
110
+
111
111
  # ann = annotations_this_image[0]
112
112
  for ann in annotations_this_image:
113
-
113
+
114
114
  if 'bbox' in ann:
115
-
115
+
116
116
  # boxes are [x,y,w,h]
117
117
  bbox = ann['bbox']
118
-
118
+
119
119
  # Do we need to scale this box?
120
120
  if (output_w != input_w) or (output_h != input_h):
121
121
  width_scale = output_w/input_w
@@ -125,49 +125,49 @@ def resize_coco_dataset(input_folder,input_filename,
125
125
  bbox[1] * height_scale,
126
126
  bbox[2] * width_scale,
127
127
  bbox[3] * height_scale]
128
-
128
+
129
129
  ann['bbox'] = bbox
130
-
130
+
131
131
  # ...if this annotation has a box
132
-
132
+
133
133
  # ...for each annotation
134
-
134
+
135
135
  # ...for each image
136
-
136
+
137
137
  # Write output file
138
138
  with open(output_filename,'w') as f:
139
139
  json.dump(d,f,indent=1)
140
-
140
+
141
141
  return d
142
142
 
143
143
  # ...def resize_coco_dataset(...)
144
-
144
+
145
145
 
146
146
  #%% Interactive driver
147
147
 
148
148
  if False:
149
-
149
+
150
150
  pass
151
151
 
152
152
  #%% Test resizing
153
-
153
+
154
154
  input_folder = os.path.expanduser('~/data/usgs-tegus/usgs-kissel-training')
155
155
  input_filename = os.path.expanduser('~/data/usgs-tegus/usgs-kissel-training.json')
156
156
  target_size = (1600,-1)
157
-
157
+
158
158
  output_filename = insert_before_extension(input_filename,'resized-test')
159
159
  output_folder = input_folder + '-resized-test'
160
-
160
+
161
161
  correct_size_image_handling = 'rewrite'
162
-
162
+
163
163
  resize_coco_dataset(input_folder,input_filename,
164
164
  output_folder,output_filename,
165
165
  target_size=target_size,
166
166
  correct_size_image_handling=correct_size_image_handling)
167
-
168
-
167
+
168
+
169
169
  #%% Preview
170
-
170
+
171
171
  from megadetector.visualization import visualize_db
172
172
  options = visualize_db.DbVizOptions()
173
173
  options.parallelize_rendering = True
@@ -177,12 +177,12 @@ if False:
177
177
  html_file,_ = visualize_db.visualize_db(output_filename,
178
178
  os.path.expanduser('~/tmp/resize_coco_preview'),
179
179
  output_folder,options)
180
-
180
+
181
181
 
182
182
  from megadetector.utils import path_utils # noqa
183
183
  path_utils.open_file(html_file)
184
-
185
-
184
+
185
+
186
186
  #%% Command-line driver
187
187
 
188
188
  # TODO
@@ -1,41 +1,41 @@
1
- """
2
-
3
- wi_to_md.py
4
-
5
- Converts the WI (SpeciesNet) predictions.json format to MD .json format. This is just a
6
- command-line wrapper around utils.wi_utils.generate_md_results_from_predictions_json.
7
-
8
- """
9
-
10
- #%% Imports and constants
11
-
12
- import sys
13
- import argparse
14
- from megadetector.utils.wi_utils import generate_md_results_from_predictions_json
15
-
16
-
17
- #%% Command-line driver
18
-
19
- def main():
20
-
21
- parser = argparse.ArgumentParser()
22
- parser.add_argument('predictions_json_file', action='store', type=str,
23
- help='.json file to convert from SpeciesNet predictions.json format to MD format')
24
- parser.add_argument('md_results_file', action='store', type=str,
25
- help='output file to write in MD format')
26
- parser.add_argument('--base_folder', action='store', type=str, default=None,
27
- help='leading string to remove from each path in the predictions.json ' + \
28
- 'file (to convert from absolute to relative paths)')
29
-
30
- if len(sys.argv[1:]) == 0:
31
- parser.print_help()
32
- parser.exit()
33
-
34
- args = parser.parse_args()
35
-
36
- generate_md_results_from_predictions_json(args.predictions_json_file,
37
- args.md_results_file,
38
- args.base_folder)
39
-
40
- if __name__ == '__main__':
41
- main()
1
+ """
2
+
3
+ speciesnet_to_md.py
4
+
5
+ Converts the WI (SpeciesNet) predictions.json format to MD .json format. This is just a
6
+ command-line wrapper around utils.wi_utils.generate_md_results_from_predictions_json.
7
+
8
+ """
9
+
10
+ #%% Imports and constants
11
+
12
+ import sys
13
+ import argparse
14
+ from megadetector.utils.wi_utils import generate_md_results_from_predictions_json
15
+
16
+
17
+ #%% Command-line driver
18
+
19
+ def main(): # noqa
20
+
21
+ parser = argparse.ArgumentParser()
22
+ parser.add_argument('predictions_json_file', action='store', type=str,
23
+ help='.json file to convert from SpeciesNet predictions.json format to MD format')
24
+ parser.add_argument('md_results_file', action='store', type=str,
25
+ help='output file to write in MD format')
26
+ parser.add_argument('--base_folder', action='store', type=str, default=None,
27
+ help='leading string to remove from each path in the predictions.json ' + \
28
+ 'file (to convert from absolute to relative paths)')
29
+
30
+ if len(sys.argv[1:]) == 0:
31
+ parser.print_help()
32
+ parser.exit()
33
+
34
+ args = parser.parse_args()
35
+
36
+ generate_md_results_from_predictions_json(args.predictions_json_file,
37
+ args.md_results_file,
38
+ args.base_folder)
39
+
40
+ if __name__ == '__main__':
41
+ main()
@@ -27,7 +27,7 @@ wi_extra_annotation_columns = \
27
27
 
28
28
  wi_extra_image_columns = ('project_id','deployment_id')
29
29
 
30
- def _make_location_id(project_id,deployment_id):
30
+ def _make_location_id(project_id,deployment_id):
31
31
  return 'project_' + str(project_id) + '_deployment_' + deployment_id
32
32
 
33
33
  default_category_remappings = {
@@ -47,86 +47,86 @@ def wi_download_csv_to_coco(csv_file_in,
47
47
  verbose=True,
48
48
  category_remappings=default_category_remappings):
49
49
  """
50
- Converts a .csv file from a Wildlife Insights project export to a COCO
50
+ Converts a .csv file from a Wildlife Insights project export to a COCO
51
51
  Camera Traps .json file.
52
-
52
+
53
53
  Args:
54
54
  csv_file_in (str): the downloaded .csv file we should convert to COCO
55
- coco_file_out (str, optional): the .json file we should write; if [coco_file_out] is None,
55
+ coco_file_out (str, optional): the .json file we should write; if [coco_file_out] is None,
56
56
  uses [csv_file_in].json
57
- image_folder (str, optional): the folder where images live, only relevant if
57
+ image_folder (str, optional): the folder where images live, only relevant if
58
58
  [validate_images] is True
59
59
  validate_images (bool, optional): whether to check images for corruption and load
60
60
  image sizes; if this is True, [image_folder] must be a valid folder
61
- gs_prefix (str, optional): a string to remove from GS URLs to convert to path names...
61
+ gs_prefix (str, optional): a string to remove from GS URLs to convert to path names...
62
62
  for example, if your gs:// URLs look like:
63
-
63
+
64
64
  `gs://11234134_xyz/deployment/55554/dfadfasdfs.jpg`
65
-
65
+
66
66
  ...and you specify gs_prefix='11234134_xyz/deployment/', the filenames in
67
67
  the .json file will look like:
68
-
68
+
69
69
  `55554/dfadfasdfs.jpg`
70
70
  verbose (bool, optional): enable additional debug console output
71
71
  category_remappings (dict, optional): str --> str dict that maps any number of
72
72
  WI category names to output category names; for example defaults to mapping
73
- "Homo Species" to "Human", but leaves 99.99% of categories unchanged.
74
-
75
- Returns:
73
+ "Homo Species" to "Human", but leaves 99.99% of categories unchanged.
74
+
75
+ Returns:
76
76
  dict: COCO-formatted data, identical to what's written to [coco_file_out]
77
77
  """
78
-
78
+
79
79
  ##%% Create COCO dictionaries
80
-
80
+
81
81
  category_name_to_id = {}
82
82
  category_name_to_id['empty'] = 0
83
-
83
+
84
84
  df = pd.read_csv(csv_file_in)
85
-
85
+
86
86
  print('Read {} rows from {}'.format(len(df),csv_file_in))
87
-
87
+
88
88
  image_id_to_image = {}
89
89
  image_id_to_annotations = defaultdict(list)
90
-
90
+
91
91
  # i_row = 0; row = df.iloc[i_row]
92
92
  for i_row,row in df.iterrows():
93
-
93
+
94
94
  image_id = row['image_id']
95
-
95
+
96
96
  if image_id not in image_id_to_image:
97
-
97
+
98
98
  im = {}
99
99
  image_id_to_image[image_id] = im
100
-
100
+
101
101
  im['id'] = image_id
102
-
102
+
103
103
  gs_url = row['location']
104
104
  assert gs_url.startswith('gs://')
105
-
105
+
106
106
  file_name = gs_url.replace('gs://','')
107
107
  if gs_prefix is not None:
108
108
  file_name = file_name.replace(gs_prefix,'')
109
-
109
+
110
110
  location_id = _make_location_id(row['project_id'],row['deployment_id'])
111
111
  im['file_name'] = file_name
112
112
  im['location'] = location_id
113
113
  im['datetime'] = row['timestamp']
114
-
114
+
115
115
  im['wi_image_info'] = {}
116
116
  for s in wi_extra_image_columns:
117
117
  im['wi_image_info'][s] = str(row[s])
118
-
118
+
119
119
  else:
120
-
120
+
121
121
  im = image_id_to_image[image_id]
122
122
  assert im['datetime'] == row['timestamp']
123
123
  location_id = _make_location_id(row['project_id'],row['deployment_id'])
124
124
  assert im['location'] == location_id
125
-
125
+
126
126
  category_name = row['common_name']
127
127
  if category_remappings is not None and category_name in category_remappings:
128
128
  category_name = category_remappings[category_name]
129
-
129
+
130
130
  if category_name == 'Blank':
131
131
  category_name = 'empty'
132
132
  assert row['is_blank'] == 1
@@ -138,24 +138,24 @@ def wi_download_csv_to_coco(csv_file_in,
138
138
  else:
139
139
  category_id = len(category_name_to_id)
140
140
  category_name_to_id[category_name] = category_id
141
-
141
+
142
142
  ann = {}
143
143
  ann['image_id'] = image_id
144
144
  annotations_this_image = image_id_to_annotations[image_id]
145
145
  annotation_number = len(annotations_this_image)
146
- ann['id'] = image_id + '_' + str(annotation_number).zfill(2)
146
+ ann['id'] = image_id + '_' + str(annotation_number).zfill(2)
147
147
  ann['category_id'] = category_id
148
148
  annotations_this_image.append(ann)
149
-
149
+
150
150
  extra_info = {}
151
- for s in wi_extra_annotation_columns:
151
+ for s in wi_extra_annotation_columns:
152
152
  v = row[s]
153
153
  if not isnan(v):
154
154
  extra_info[s] = v
155
155
  ann['wi_extra_info'] = extra_info
156
-
156
+
157
157
  # ...for each row
158
-
158
+
159
159
  images = list(image_id_to_image.values())
160
160
  categories = []
161
161
  for category_name in category_name_to_id:
@@ -173,25 +173,25 @@ def wi_download_csv_to_coco(csv_file_in,
173
173
  coco_data['images'] = images
174
174
  coco_data['annotations'] = annotations
175
175
  coco_data['categories'] = categories
176
-
177
-
178
- ##%% Validate images, add sizes
179
-
176
+
177
+
178
+ ##%% Validate images, add sizes
179
+
180
180
  if validate_images:
181
-
181
+
182
182
  print('Validating images')
183
-
183
+
184
184
  assert os.path.isdir(image_folder), \
185
185
  'Must specify a valid image folder if you specify validate_images=True'
186
-
186
+
187
187
  # TODO: trivially parallelizable
188
- #
188
+ #
189
189
  # im = images[0]
190
190
  for im in tqdm(images):
191
191
  file_name_relative = im['file_name']
192
192
  file_name_abs = os.path.join(image_folder,file_name_relative)
193
193
  assert os.path.isfile(file_name_abs)
194
-
194
+
195
195
  im['corrupt'] = False
196
196
  try:
197
197
  pil_im = vis_utils.load_image(file_name_abs)
@@ -200,19 +200,19 @@ def wi_download_csv_to_coco(csv_file_in,
200
200
  if not im['corrupt']:
201
201
  im['width'] = pil_im.width
202
202
  im['height'] = pil_im.height
203
-
204
-
203
+
204
+
205
205
  ##%% Write output json
206
-
207
- if coco_file_out is None:
206
+
207
+ if coco_file_out is None:
208
208
  coco_file_out = csv_file_in + '.json'
209
-
209
+
210
210
  with open(coco_file_out,'w') as f:
211
211
  json.dump(coco_data,f,indent=1)
212
212
 
213
213
 
214
214
  ##%% Validate output
215
-
215
+
216
216
  from megadetector.data_management.databases.integrity_check_json_db import \
217
217
  IntegrityCheckOptions,integrity_check_json_db
218
218
  options = IntegrityCheckOptions()
@@ -220,18 +220,18 @@ def wi_download_csv_to_coco(csv_file_in,
220
220
  options.bCheckImageExistence = True
221
221
  options.verbose = verbose
222
222
  _ = integrity_check_json_db(coco_file_out,options)
223
-
223
+
224
224
  return coco_data
225
225
 
226
- # ...def wi_download_csv_to_coco(...)
226
+ # ...def wi_download_csv_to_coco(...)
227
227
 
228
228
 
229
229
  #%% Interactive driver
230
230
 
231
231
  if False:
232
-
232
+
233
233
  #%%
234
-
234
+
235
235
  base_folder = r'a/b/c'
236
236
  csv_file_in = os.path.join(base_folder,'images.csv')
237
237
  coco_file_out = None