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
@@ -4,7 +4,7 @@ convert_output_format.py
4
4
 
5
5
  Converts between file formats output by our batch processing API. Currently
6
6
  supports json <--> csv conversion, but this should be the landing place for any
7
- conversion - including between hypothetical alternative .json versions - that we support
7
+ conversion - including between hypothetical alternative .json versions - that we support
8
8
  in the future.
9
9
 
10
10
  The .csv format is largely obsolete, don't use it unless you're super-duper sure you need it.
@@ -38,18 +38,18 @@ def convert_json_to_csv(input_path,
38
38
  overwrite=True):
39
39
  """
40
40
  Converts a MD results .json file to a totally non-standard .csv format.
41
-
41
+
42
42
  If [output_path] is None, will convert x.json to x.csv.
43
-
43
+
44
44
  TODO: this function should obviously be using Pandas or some other sensible structured
45
45
  representation of tabular data. Even a list of dicts. This implementation is quite
46
46
  brittle and depends on adding fields to every row in exactly the right order.
47
-
47
+
48
48
  Args:
49
49
  input_path (str): the input .json file to convert
50
- output_path (str, optional): the output .csv file to generate; if this is None, uses
50
+ output_path (str, optional): the output .csv file to generate; if this is None, uses
51
51
  [input_path].csv
52
- min_confidence (float, optional): the minimum-confidence detection we should include
52
+ min_confidence (float, optional): the minimum-confidence detection we should include
53
53
  in the "detections" column; has no impact on the other columns
54
54
  omit_bounding_boxes (bool): whether to leave out the json-formatted bounding boxes
55
55
  that make up the "detections" column, which are not generally useful for someone who
@@ -57,24 +57,24 @@ def convert_json_to_csv(input_path,
57
57
  output_encoding (str, optional): encoding to use for the .csv file
58
58
  overwrite (bool): whether to overwrite an existing .csv file; if this is False and the
59
59
  output file exists, no-ops and returns
60
-
60
+
61
61
  """
62
-
62
+
63
63
  if output_path is None:
64
64
  output_path = os.path.splitext(input_path)[0]+'.csv'
65
-
65
+
66
66
  if os.path.isfile(output_path) and (not overwrite):
67
67
  print('File {} exists, skipping json --> csv conversion'.format(output_path))
68
68
  return
69
-
69
+
70
70
  print('Loading json results from {}...'.format(input_path))
71
71
  json_output = json.load(open(input_path))
72
72
 
73
73
  rows = []
74
-
74
+
75
75
  fixed_columns = ['image_path', 'max_confidence', 'detections']
76
-
77
- # We add an output column for each class other than 'empty',
76
+
77
+ # We add an output column for each class other than 'empty',
78
78
  # containing the maximum probability of that class for each image
79
79
  # n_non_empty_detection_categories = len(annotation_constants.annotation_bbox_categories) - 1
80
80
  n_non_empty_detection_categories = annotation_constants.NUM_DETECTOR_CATEGORIES
@@ -83,9 +83,9 @@ def convert_json_to_csv(input_path,
83
83
  for cat_id in range(1,n_non_empty_detection_categories+1):
84
84
  cat_name = annotation_constants.detector_bbox_category_id_to_name[cat_id]
85
85
  detection_category_column_names.append('max_conf_' + cat_name)
86
-
86
+
87
87
  n_classification_categories = 0
88
-
88
+
89
89
  if 'classification_categories' in json_output.keys():
90
90
  classification_category_id_to_name = json_output['classification_categories']
91
91
  classification_category_ids = list(classification_category_id_to_name.keys())
@@ -98,35 +98,35 @@ def convert_json_to_csv(input_path,
98
98
  classification_category_id_to_column_number[category_id] = i_category
99
99
 
100
100
  n_classification_categories = len(classification_category_ids)
101
-
101
+
102
102
  # There are several .json fields for which we add .csv columns; other random bespoke fields
103
103
  # will be ignored.
104
104
  optional_fields = ['width','height','datetime','exif_metadata']
105
105
  optional_fields_present = set()
106
-
106
+
107
107
  # Iterate once over the data to check for optional fields
108
108
  print('Looking for optional fields...')
109
-
109
+
110
110
  for im in tqdm(json_output['images']):
111
111
  # Which optional fields are present for this image?
112
112
  for k in im.keys():
113
113
  if k in optional_fields:
114
114
  optional_fields_present.add(k)
115
-
115
+
116
116
  optional_fields_present = sorted(list(optional_fields_present))
117
117
  if len(optional_fields_present) > 0:
118
118
  print('Found {} optional fields'.format(len(optional_fields_present)))
119
-
119
+
120
120
  expected_row_length = len(fixed_columns) + len(detection_category_column_names) + \
121
121
  n_classification_categories + len(optional_fields_present)
122
-
122
+
123
123
  print('Formatting results...')
124
-
124
+
125
125
  # i_image = 0; im = json_output['images'][i_image]
126
126
  for im in tqdm(json_output['images']):
127
-
127
+
128
128
  image_id = im['file']
129
-
129
+
130
130
  if 'failure' in im and im['failure'] is not None:
131
131
  row = [image_id, 'failure', im['failure']]
132
132
  rows.append(row)
@@ -137,16 +137,16 @@ def convert_json_to_csv(input_path,
137
137
  detections = []
138
138
  max_detection_category_probabilities = [None] * n_non_empty_detection_categories
139
139
  max_classification_category_probabilities = [0] * n_classification_categories
140
-
140
+
141
141
  # d = im['detections'][0]
142
142
  for d in im['detections']:
143
-
143
+
144
144
  # Skip sub-threshold detections
145
145
  if (min_confidence is not None) and (d['conf'] < min_confidence):
146
146
  continue
147
-
147
+
148
148
  input_bbox = d['bbox']
149
-
149
+
150
150
  # Our .json format is xmin/ymin/w/h
151
151
  #
152
152
  # Our .csv format was ymin/xmin/ymax/xmax
@@ -155,9 +155,9 @@ def convert_json_to_csv(input_path,
155
155
  xmax = input_bbox[0] + input_bbox[2]
156
156
  ymax = input_bbox[1] + input_bbox[3]
157
157
  output_detection = [ymin, xmin, ymax, xmax]
158
-
158
+
159
159
  output_detection.append(d['conf'])
160
-
160
+
161
161
  # Category 0 is empty, for which we don't have a column, so the max
162
162
  # confidence for category N goes in column N-1
163
163
  detection_category_id = int(d['category'])
@@ -167,10 +167,10 @@ def convert_json_to_csv(input_path,
167
167
  detection_category_max = max_detection_category_probabilities[detection_category_column]
168
168
  if detection_category_max is None or d['conf'] > detection_category_max:
169
169
  max_detection_category_probabilities[detection_category_column] = d['conf']
170
-
170
+
171
171
  output_detection.append(detection_category_id)
172
172
  detections.append(output_detection)
173
-
173
+
174
174
  if 'classifications' in d:
175
175
  assert n_classification_categories > 0,\
176
176
  'Oops, I have classification results, but no classification metadata'
@@ -180,34 +180,34 @@ def convert_json_to_csv(input_path,
180
180
  category_index = classification_category_id_to_column_number[category_id]
181
181
  if (max_classification_category_probabilities[category_index] < p):
182
182
  max_classification_category_probabilities[category_index] = p
183
-
183
+
184
184
  # ...for each classification
185
-
185
+
186
186
  # ...if we have classification results for this detection
187
-
187
+
188
188
  # ...for each detection
189
-
189
+
190
190
  detection_string = ''
191
191
  if not omit_bounding_boxes:
192
192
  detection_string = json.dumps(detections)
193
-
193
+
194
194
  row = [image_id, max_conf, detection_string]
195
195
  row.extend(max_detection_category_probabilities)
196
196
  row.extend(max_classification_category_probabilities)
197
-
197
+
198
198
  for field_name in optional_fields_present:
199
199
  if field_name not in im:
200
200
  row.append('')
201
201
  else:
202
202
  row.append(str(im[field_name]))
203
-
203
+
204
204
  assert len(row) == expected_row_length
205
205
  rows.append(row)
206
-
206
+
207
207
  # ...for each image
208
208
 
209
209
  print('Writing to csv...')
210
-
210
+
211
211
  with open(output_path, 'w', newline='', encoding=output_encoding) as f:
212
212
  writer = csv.writer(f, delimiter=',')
213
213
  header = fixed_columns
@@ -221,31 +221,31 @@ def convert_json_to_csv(input_path,
221
221
 
222
222
  # ...def convert_json_to_csv(...)
223
223
 
224
-
224
+
225
225
  def convert_csv_to_json(input_path,output_path=None,overwrite=True):
226
226
  """
227
227
  Convert .csv to .json. If output_path is None, will convert x.csv to x.json.
228
-
228
+
229
229
  Args:
230
230
  input_path (str): .csv filename to convert to .json
231
- output_path (str, optional): the output .json file to generate; if this is None, uses
231
+ output_path (str, optional): the output .json file to generate; if this is None, uses
232
232
  [input_path].json
233
233
  overwrite (bool): whether to overwrite an existing .json file; if this is False and the
234
- output file exists, no-ops and returns
235
-
234
+ output file exists, no-ops and returns
235
+
236
236
  """
237
-
237
+
238
238
  if output_path is None:
239
239
  output_path = os.path.splitext(input_path)[0]+'.json'
240
-
240
+
241
241
  if os.path.isfile(output_path) and (not overwrite):
242
242
  print('File {} exists, skipping csv --> json conversion'.format(output_path))
243
243
  return
244
-
244
+
245
245
  # Format spec:
246
246
  #
247
247
  # https://github.com/agentmorris/MegaDetector/tree/main/megadetector/api/batch_processing
248
-
248
+
249
249
  print('Loading csv results...')
250
250
  df = load_api_results_csv(input_path)
251
251
 
@@ -256,23 +256,23 @@ def convert_csv_to_json(input_path,output_path=None,overwrite=True):
256
256
  "classifier": "unknown",
257
257
  "classification_completion_time": "unknown"
258
258
  }
259
-
259
+
260
260
  classification_categories = {}
261
261
  detection_categories = annotation_constants.detector_bbox_categories
262
262
 
263
263
  images = []
264
-
265
- # iFile = 0; row = df.iloc[iFile]
266
- for iFile,row in df.iterrows():
267
-
264
+
265
+ # i_file = 0; row = df.iloc[i_file]
266
+ for i_file,row in df.iterrows():
267
+
268
268
  image = {}
269
269
  image['file'] = row['image_path']
270
270
  image['max_detection_conf'] = round(row['max_confidence'], CONF_DIGITS)
271
- src_detections = row['detections']
271
+ src_detections = row['detections']
272
272
  out_detections = []
273
-
274
- for iDetection,detection in enumerate(src_detections):
275
-
273
+
274
+ for i_detection,detection in enumerate(src_detections):
275
+
276
276
  # Our .csv format was ymin/xmin/ymax/xmax
277
277
  #
278
278
  # Our .json format is xmin/ymin/w/h
@@ -282,91 +282,91 @@ def convert_csv_to_json(input_path,output_path=None,overwrite=True):
282
282
  xmax = detection[3]
283
283
  bbox = [xmin, ymin, xmax-xmin, ymax-ymin]
284
284
  conf = detection[4]
285
- iClass = detection[5]
285
+ i_class = detection[5]
286
286
  out_detection = {}
287
- out_detection['category'] = str(iClass)
287
+ out_detection['category'] = str(i_class)
288
288
  out_detection['conf'] = conf
289
- out_detection['bbox'] = bbox
289
+ out_detection['bbox'] = bbox
290
290
  out_detections.append(out_detection)
291
-
291
+
292
292
  # ...for each detection
293
-
293
+
294
294
  image['detections'] = out_detections
295
295
  images.append(image)
296
-
297
- # ...for each image
296
+
297
+ # ...for each image
298
298
  json_out = {}
299
299
  json_out['info'] = info
300
300
  json_out['detection_categories'] = detection_categories
301
301
  json_out['classification_categories'] = classification_categories
302
302
  json_out['images'] = images
303
-
303
+
304
304
  json.dump(json_out,open(output_path,'w'),indent=1)
305
-
305
+
306
306
  # ...def convert_csv_to_json(...)
307
307
 
308
308
 
309
309
  #%% Interactive driver
310
310
 
311
- if False:
311
+ if False:
312
312
 
313
313
  #%%
314
-
314
+
315
315
  input_path = r'c:\temp\test.json'
316
316
  min_confidence = None
317
317
  output_path = input_path + '.csv'
318
318
  convert_json_to_csv(input_path,output_path,min_confidence=min_confidence,
319
319
  omit_bounding_boxes=False)
320
-
320
+
321
321
  #%%
322
-
322
+
323
323
  base_path = r'c:\temp\json'
324
324
  input_paths = os.listdir(base_path)
325
325
  input_paths = [os.path.join(base_path,s) for s in input_paths]
326
-
327
- min_confidence = None
326
+
327
+ min_confidence = None
328
328
  for input_path in input_paths:
329
329
  output_path = input_path + '.csv'
330
330
  convert_json_to_csv(input_path,output_path,min_confidence=min_confidence,
331
- omit_bounding_boxes=True)
332
-
331
+ omit_bounding_boxes=True)
332
+
333
333
  #%% Concatenate .csv files from a folder
334
334
 
335
335
  import glob
336
336
  csv_files = glob.glob(os.path.join(base_path,'*.json.csv' ))
337
337
  master_csv = os.path.join(base_path,'all.csv')
338
-
338
+
339
339
  print('Concatenating {} files to {}'.format(len(csv_files),master_csv))
340
-
340
+
341
341
  header = None
342
342
  with open(master_csv, 'w') as fout:
343
-
343
+
344
344
  for filename in tqdm(csv_files):
345
-
345
+
346
346
  with open(filename) as fin:
347
-
347
+
348
348
  lines = fin.readlines()
349
-
349
+
350
350
  if header is not None:
351
351
  assert lines[0] == header
352
352
  else:
353
353
  header = lines[0]
354
354
  fout.write(header)
355
-
355
+
356
356
  for line in lines[1:]:
357
357
  if len(line.strip()) == 0:
358
- continue
358
+ continue
359
359
  fout.write(line)
360
-
360
+
361
361
  # ...for each .csv file
362
-
362
+
363
363
  # with open(master_csv)
364
-
365
-
364
+
365
+
366
366
  #%% Command-line driver
367
-
368
- def main():
369
-
367
+
368
+ def main(): # noqa
369
+
370
370
  parser = argparse.ArgumentParser()
371
371
  parser.add_argument('input_path',type=str,
372
372
  help='Input filename ending in .json or .csv')
@@ -374,22 +374,22 @@ def main():
374
374
  help='Output filename ending in .json or .csv (defaults to ' + \
375
375
  'input file, with .json/.csv replaced by .csv/.json)')
376
376
  parser.add_argument('--omit_bounding_boxes',action='store_true',
377
- help='Output bounding box text from .csv output (large and usually not useful)')
378
-
377
+ help='Output bounding box text from .csv output (large and usually not useful)')
378
+
379
379
  if len(sys.argv[1:]) == 0:
380
380
  parser.print_help()
381
381
  parser.exit()
382
382
 
383
383
  args = parser.parse_args()
384
-
384
+
385
385
  if args.output_path is None:
386
386
  if args.input_path.endswith('.csv'):
387
387
  args.output_path = args.input_path[:-4] + '.json'
388
388
  elif args.input_path.endswith('.json'):
389
389
  args.output_path = args.input_path[:-5] + '.csv'
390
390
  else:
391
- raise ValueError('Illegal input file extension')
392
-
391
+ raise ValueError('Illegal input file extension')
392
+
393
393
  if args.input_path.endswith('.csv') and args.output_path.endswith('.json'):
394
394
  assert not args.omit_bounding_boxes, \
395
395
  '--omit_bounding_boxes does not apply to csv --> json conversion'
@@ -397,7 +397,7 @@ def main():
397
397
  elif args.input_path.endswith('.json') and args.output_path.endswith('.csv'):
398
398
  convert_json_to_csv(args.input_path,args.output_path,omit_bounding_boxes=args.omit_bounding_boxes)
399
399
  else:
400
- raise ValueError('Illegal format combination')
400
+ raise ValueError('Illegal format combination')
401
401
 
402
402
  if __name__ == '__main__':
403
403
  main()