megadetector 5.0.28__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 +231 -224
  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 +340 -337
  65. megadetector/detection/pytorch_detector.py +304 -262
  66. megadetector/detection/run_detector.py +177 -164
  67. megadetector/detection/run_detector_batch.py +364 -363
  68. megadetector/detection/run_inference_with_yolov5_val.py +328 -325
  69. megadetector/detection/run_tiled_inference.py +256 -249
  70. megadetector/detection/tf_detector.py +24 -24
  71. megadetector/detection/video_utils.py +290 -282
  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 +415 -415
  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 +219 -146
  79. megadetector/postprocessing/detector_calibration.py +173 -168
  80. megadetector/postprocessing/generate_csv_report.py +508 -499
  81. megadetector/postprocessing/load_api_results.py +23 -20
  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 +313 -298
  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 -66
  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 +10 -10
  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 +1018 -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 +1457 -398
  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 +61 -61
  115. megadetector/utils/string_utils.py +147 -26
  116. megadetector/utils/url_utils.py +463 -173
  117. megadetector/utils/wi_utils.py +2629 -2526
  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 +401 -397
  122. megadetector/visualization/visualize_db.py +197 -190
  123. megadetector/visualization/visualize_detector_output.py +79 -73
  124. {megadetector-5.0.28.dist-info → megadetector-5.0.29.dist-info}/METADATA +135 -132
  125. megadetector-5.0.29.dist-info/RECORD +163 -0
  126. {megadetector-5.0.28.dist-info → megadetector-5.0.29.dist-info}/WHEEL +1 -1
  127. {megadetector-5.0.28.dist-info → megadetector-5.0.29.dist-info}/licenses/LICENSE +0 -0
  128. {megadetector-5.0.28.dist-info → megadetector-5.0.29.dist-info}/top_level.txt +0 -0
  129. megadetector/data_management/importers/add_nacti_sizes.py +0 -52
  130. megadetector/data_management/importers/add_timestamps_to_icct.py +0 -79
  131. megadetector/data_management/importers/animl_results_to_md_results.py +0 -158
  132. megadetector/data_management/importers/auckland_doc_test_to_json.py +0 -373
  133. megadetector/data_management/importers/auckland_doc_to_json.py +0 -201
  134. megadetector/data_management/importers/awc_to_json.py +0 -191
  135. megadetector/data_management/importers/bellevue_to_json.py +0 -272
  136. megadetector/data_management/importers/cacophony-thermal-importer.py +0 -793
  137. megadetector/data_management/importers/carrizo_shrubfree_2018.py +0 -269
  138. megadetector/data_management/importers/carrizo_trail_cam_2017.py +0 -289
  139. megadetector/data_management/importers/cct_field_adjustments.py +0 -58
  140. megadetector/data_management/importers/channel_islands_to_cct.py +0 -913
  141. megadetector/data_management/importers/eMammal/copy_and_unzip_emammal.py +0 -180
  142. megadetector/data_management/importers/eMammal/eMammal_helpers.py +0 -249
  143. megadetector/data_management/importers/eMammal/make_eMammal_json.py +0 -223
  144. megadetector/data_management/importers/ena24_to_json.py +0 -276
  145. megadetector/data_management/importers/filenames_to_json.py +0 -386
  146. megadetector/data_management/importers/helena_to_cct.py +0 -283
  147. megadetector/data_management/importers/idaho-camera-traps.py +0 -1407
  148. megadetector/data_management/importers/idfg_iwildcam_lila_prep.py +0 -294
  149. megadetector/data_management/importers/import_desert_lion_conservation_camera_traps.py +0 -387
  150. megadetector/data_management/importers/jb_csv_to_json.py +0 -150
  151. megadetector/data_management/importers/mcgill_to_json.py +0 -250
  152. megadetector/data_management/importers/missouri_to_json.py +0 -490
  153. megadetector/data_management/importers/nacti_fieldname_adjustments.py +0 -79
  154. megadetector/data_management/importers/noaa_seals_2019.py +0 -181
  155. megadetector/data_management/importers/osu-small-animals-to-json.py +0 -364
  156. megadetector/data_management/importers/pc_to_json.py +0 -365
  157. megadetector/data_management/importers/plot_wni_giraffes.py +0 -123
  158. megadetector/data_management/importers/prepare_zsl_imerit.py +0 -131
  159. megadetector/data_management/importers/raic_csv_to_md_results.py +0 -416
  160. megadetector/data_management/importers/rspb_to_json.py +0 -356
  161. megadetector/data_management/importers/save_the_elephants_survey_A.py +0 -320
  162. megadetector/data_management/importers/save_the_elephants_survey_B.py +0 -329
  163. megadetector/data_management/importers/snapshot_safari_importer.py +0 -758
  164. megadetector/data_management/importers/snapshot_serengeti_lila.py +0 -1067
  165. megadetector/data_management/importers/snapshotserengeti/make_full_SS_json.py +0 -150
  166. megadetector/data_management/importers/snapshotserengeti/make_per_season_SS_json.py +0 -153
  167. megadetector/data_management/importers/sulross_get_exif.py +0 -65
  168. megadetector/data_management/importers/timelapse_csv_set_to_json.py +0 -490
  169. megadetector/data_management/importers/ubc_to_json.py +0 -399
  170. megadetector/data_management/importers/umn_to_json.py +0 -507
  171. megadetector/data_management/importers/wellington_to_json.py +0 -263
  172. megadetector/data_management/importers/wi_to_json.py +0 -442
  173. megadetector/data_management/importers/zamba_results_to_md_results.py +0 -180
  174. megadetector/data_management/lila/add_locations_to_island_camera_traps.py +0 -101
  175. megadetector/data_management/lila/add_locations_to_nacti.py +0 -151
  176. megadetector-5.0.28.dist-info/RECORD +0 -209
@@ -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