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
@@ -1,416 +0,0 @@
1
- """
2
-
3
- raic_csv_to_md_results.py
4
-
5
- Converts classification+detection results in the .csv format provided to the Snapshot
6
- Serengeti program by the RAIC team to the MD results format.
7
-
8
- The input format is two .csv files:
9
-
10
- * One with results, with columns [unnamed], filename, category, x_center, y_center,
11
- width, height, confidence, datetime
12
-
13
- * One with class IDs and names, with columns CLASS, SPECIES
14
-
15
- Filenames are relative paths to .txt files, but with slashes replaced by underscores, e.g. this
16
- file:
17
-
18
- B04_R1/I__00122.JPG
19
-
20
- ...appears in the .csv file as:
21
-
22
- B04_R1_I__00122.txt
23
-
24
- Image coordinates are in absolute floating-point units, with an upper-left origin.
25
-
26
- Unknowns at the time I'm writing this:
27
-
28
- * I don't know what the unnamed column is, but it looks like an ID I can safely ignore.
29
-
30
- * I believe that MegaDetector was run, then a classifier was run, but there is a
31
- single "confidence" column in the output. I am writing out the results as if they were a
32
- single multi-class detector. This is suspicious given the lack of a human class, which suggests
33
- that this is intended to be run in conjunection with MD.
34
-
35
- * There is no concept of "empty" in this file format, so by default I assume that images with
36
- no annotations in the .csv file were processed and determine to have no detections above some
37
- (unknown) threshold.
38
-
39
- * I'm not currently handling EXIF rotations, as part of the effort to simplify this file
40
- for conversion to R (see below).
41
-
42
- Note to self: this file should not take dependencies on other components of the MD
43
- repo, at the risk of creating some redundancy. I am going to convert this to R,
44
- which will be easier if it's not using any non-standard libraries. Anything in the
45
- "interactive driver" cells gets a pass.
46
-
47
- """
48
-
49
- #%% Imports and constants
50
-
51
- import os
52
- import glob
53
- import json
54
- import sys
55
- import argparse
56
-
57
- import pandas as pd
58
- from PIL import Image
59
-
60
-
61
- #%% Functions from the MD python package
62
-
63
- # ...that I'm choosing to copy and paste to facilitate a conversion of this
64
- # script to R.
65
-
66
- # Should all be lower-case
67
- IMG_EXTENSIONS = ('.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff', '.bmp')
68
-
69
- def _is_image_file(s, img_extensions=IMG_EXTENSIONS):
70
- """
71
- Checks a file's extension against a hard-coded set of image file
72
- extensions. Uses case-insensitive comparison.
73
-
74
- Does not check whether the file exists, only determines whether the filename
75
- implies it's an image file.
76
-
77
- Args:
78
- s (str): filename to evaluate for image-ness
79
- img_extensions (list, optional): list of known image file extensions
80
-
81
- Returns:
82
- bool: True if [s] appears to be an image file, else False
83
- """
84
-
85
- ext = os.path.splitext(s)[1]
86
- return ext.lower() in img_extensions
87
-
88
-
89
- def _find_image_strings(strings):
90
- """
91
- Given a list of strings that are potentially image file names, looks for
92
- strings that actually look like image file names (based on extension).
93
-
94
- Args:
95
- strings (list): list of filenames to check for image-ness
96
-
97
- Returns:
98
- list: the subset of [strings] that appear to be image filenames
99
- """
100
-
101
- return [s for s in strings if _is_image_file(s)]
102
-
103
-
104
- def _find_images(dirname,
105
- recursive=False,
106
- return_relative_paths=False,
107
- convert_slashes=True):
108
- """
109
- Finds all files in a directory that look like image file names. Returns
110
- absolute paths unless return_relative_paths is set. Uses the OS-native
111
- path separator unless convert_slashes is set, in which case will always
112
- use '/'.
113
-
114
- Args:
115
- dirname (str): the folder to search for images
116
- recursive (bool, optional): whether to search recursively
117
- return_relative_paths (str, optional): return paths that are relative
118
- to [dirname], rather than absolute paths
119
- convert_slashes (bool, optional): force forward slashes in return values
120
-
121
- Returns:
122
- list: list of image filenames found in [dirname]
123
- """
124
-
125
- assert os.path.isdir(dirname), '{} is not a folder'.format(dirname)
126
-
127
- if recursive:
128
- strings = glob.glob(os.path.join(dirname, '**', '*.*'), recursive=True)
129
- else:
130
- strings = glob.glob(os.path.join(dirname, '*.*'))
131
-
132
- image_files = _find_image_strings(strings)
133
-
134
- if return_relative_paths:
135
- image_files = [os.path.relpath(fn,dirname) for fn in image_files]
136
-
137
- image_files = sorted(image_files)
138
-
139
- if convert_slashes:
140
- image_files = [fn.replace('\\', '/') for fn in image_files]
141
-
142
- return image_files
143
-
144
-
145
- #%% Main conversion function
146
-
147
- def raic_csv_to_md_results(result_csv_file,
148
- class_mapping_csv_file,
149
- image_folder,
150
- output_file=None,
151
- unannotated_image_handling='empty'):
152
- """
153
- Converts a pair of .csv files (see file header for details) to MD results format.
154
-
155
- Currently errors if image filenames are ambiguous, or if any images referred to in
156
- the results are not available.
157
-
158
- Args:
159
- result_csv_file (str): the results file to read (.csv)
160
- class_mapping_csv_file (str): the class mapping file (.csv)
161
- image_folder (str): the folder containing all the images referred to in
162
- [result_csv_file]
163
- output_file (str, optional): the .json file to which we should write results. Defaults
164
- to [result_csv_file].json
165
- unannotated_image_handling (str, optional): can be "empty" (default) to assume
166
- that images without annotations are empty, "warning", "error", or "skip"
167
-
168
- Returns:
169
- str: the output file written, identical to [output_file] if [output_file] was not None
170
- """
171
-
172
- # Validate arguments
173
- assert os.path.isfile(result_csv_file), \
174
- 'Result file {} not found'.format(result_csv_file)
175
- assert os.path.isfile(class_mapping_csv_file), \
176
- 'Class mapping file {} not found'.format(class_mapping_csv_file)
177
- assert os.path.isdir(image_folder), \
178
- 'Image folder {} not found'.format(image_folder)
179
-
180
- if output_file is None:
181
- output_file = result_csv_file + '.json'
182
-
183
- image_files_relative = _find_images(image_folder,
184
- recursive=True,
185
- return_relative_paths=True,
186
- convert_slashes=True)
187
- image_file_base_flattened_to_image_file_relative = {}
188
- for fn in image_files_relative:
189
- # Convert, e.g. B04_R1/I__00108.JPG to B04_R1_I__00108
190
- fn_flattened = fn.replace('/','_')
191
- fn_flattened_base = os.path.splitext(fn_flattened)[0]
192
- image_file_base_flattened_to_image_file_relative[fn_flattened_base] = \
193
- fn
194
-
195
- # Read the .csv files
196
- df_results = pd.read_csv(result_csv_file)
197
- df_class_mapping = pd.read_csv(class_mapping_csv_file)
198
-
199
- assert 'CLASS' in df_class_mapping.columns and 'SPECIES' in df_class_mapping.columns, \
200
- 'Unexpected column names in class mapping file {}'.format(class_mapping_csv_file)
201
-
202
- category_id_to_name = {}
203
- for i_row,row in df_class_mapping.iterrows():
204
- class_id = int(row['CLASS'])
205
- assert class_id not in category_id_to_name, \
206
- 'Class ID {} occurs more than once in class mapping file {}'.format(
207
- class_id,class_mapping_csv_file)
208
- category_id_to_name[class_id] = row['SPECIES']
209
-
210
- if len(category_id_to_name) != len(set(category_id_to_name.values())):
211
- print('Warning: one or more categories are used more than once in class mapping file {}'.format(
212
- class_mapping_csv_file))
213
-
214
- # Convert results
215
-
216
- fn_relative_to_im = {}
217
-
218
- # i_row = 0; row = df_results.iloc[i_row]
219
- for i_row,row in df_results.iterrows():
220
-
221
- # Map the .txt filename base to a relative path
222
- bn = row['filename']
223
- assert bn.lower().endswith('.txt')
224
- bn_no_ext = os.path.splitext(bn)[0]
225
- assert bn_no_ext in image_file_base_flattened_to_image_file_relative, \
226
- 'No image found for result row {}'.format(row['filename'])
227
-
228
- image_fn_relative = image_file_base_flattened_to_image_file_relative[bn_no_ext]
229
-
230
- # Have we seen another detection for this image?
231
- if image_fn_relative in fn_relative_to_im:
232
-
233
- im = fn_relative_to_im[image_fn_relative]
234
-
235
- # If not, load this image so we can read its size
236
- else:
237
-
238
- image_fn_abs = os.path.join(image_folder,image_fn_relative)
239
- image = Image.open(image_fn_abs)
240
- w = image.size[0]
241
- h = image.size[1]
242
-
243
- im = {}
244
- im['file'] = image_fn_relative
245
- im['width'] = w
246
- im['height'] = h
247
- im['detections'] = []
248
- im['datetime'] = str(row['datetime'])
249
- fn_relative_to_im[image_fn_relative] = im
250
-
251
- # Convert annotation
252
- x_center_abs = row['x_center']
253
- y_center_abs = row['y_center']
254
- box_width_abs = row['width']
255
- box_height_abs = row['height']
256
-
257
- # Convert to relative coordinates
258
- box_left_abs = x_center_abs - (box_width_abs/2.0)
259
- box_top_abs = y_center_abs - (box_height_abs/2.0)
260
- bbox_normalized = [box_left_abs/im['width'],
261
- box_top_abs/im['height'],
262
- box_width_abs/im['width'],
263
- box_height_abs/im['height']]
264
-
265
- category_id = str(int(row['category']))
266
- confidence = row['confidence']
267
- assert isinstance(confidence,float) and confidence <= 1.0 and confidence >= 0.0
268
-
269
- det = {}
270
- im['detections'].append(det)
271
- det['category'] = category_id
272
- det['conf'] = confidence
273
- det['bbox'] = bbox_normalized
274
-
275
- # ...for each row
276
-
277
- n_empty_images = 0
278
-
279
- # Handle images without annotations
280
- for fn_relative in image_files_relative:
281
-
282
- if fn_relative not in fn_relative_to_im:
283
- if unannotated_image_handling == 'empty':
284
- im = {}
285
- im['file'] = fn_relative
286
- im['detections'] = []
287
- fn_relative_to_im[fn_relative] = im
288
- n_empty_images += 1
289
- # Don't bother to read width and height here
290
- elif unannotated_image_handling == 'warning':
291
- print('Warning: image {} is not represented in the .csv results file'.format(fn_relative))
292
- elif unannotated_image_handling == 'error':
293
- raise ValueError('Image {} is not represented in the .csv results file'.format(fn_relative))
294
- elif unannotated_image_handling == 'skip':
295
- continue
296
-
297
- # ...for each image file
298
-
299
- if n_empty_images > 0:
300
- print('Warning: assuming {} of {} images without annotations are empty'.format(
301
- n_empty_images,len(image_files_relative)))
302
-
303
- images = list(fn_relative_to_im.values())
304
-
305
- # The MD output format uses string-ints for category IDs, right now we have ints
306
- detection_categories = {}
307
- for category_id_int in category_id_to_name:
308
- detection_categories[str(category_id_int)] = category_id_to_name[category_id_int]
309
-
310
- info = {}
311
- info['format_version'] = '1.4'
312
- info['detector'] = 'RAIC .csv converter'
313
-
314
- d = {}
315
- d['images'] = images
316
- d['detection_categories'] = detection_categories
317
- d['info'] = info
318
-
319
- with open(output_file,'w') as f:
320
- json.dump(d,f,indent=1)
321
-
322
- return output_file
323
-
324
- # ...def raic_csv_to_md_results(...)
325
-
326
-
327
- #%% Interactive driver
328
-
329
- if False:
330
-
331
- pass
332
-
333
- #%% Test conversion
334
-
335
- base_folder = r'G:\temp\S24_B04_R1_output_annotations_for_Dan'
336
- result_csv_file = os.path.join(base_folder,'S24_B04_R1_output_annotations_for_Dan.csv')
337
- class_mapping_csv_file = os.path.join(base_folder,'categories_key.csv')
338
-
339
- # This is wrong, B04_R1 has to be part of the image paths
340
- # image_folder = os.path.join(base_folder,'B04_R1')
341
-
342
- image_folder = base_folder
343
-
344
- output_file = None
345
- unannotated_image_handling='empty'
346
-
347
- output_file = raic_csv_to_md_results(result_csv_file=result_csv_file,
348
- class_mapping_csv_file=class_mapping_csv_file,
349
- image_folder=image_folder,
350
- output_file=output_file,
351
- unannotated_image_handling=unannotated_image_handling)
352
-
353
- #%% Validate results file
354
-
355
- from megadetector.postprocessing.validate_batch_results import \
356
- ValidateBatchResultsOptions, validate_batch_results
357
-
358
- validation_options = ValidateBatchResultsOptions()
359
- validation_options.check_image_existence = True
360
- validation_options.relative_path_base = image_folder
361
- validation_options.return_data = True
362
-
363
- results = validate_batch_results(output_file,validation_options)
364
- assert len(results['validation_results']['errors']) == 0
365
- assert len(results['validation_results']['warnings']) == 0
366
-
367
-
368
- #%% Preview results
369
-
370
- from megadetector.postprocessing.postprocess_batch_results import \
371
- PostProcessingOptions, process_batch_results
372
-
373
- postprocessing_options = PostProcessingOptions()
374
-
375
- postprocessing_options.md_results_file = output_file
376
- postprocessing_options.output_dir = r'g:\temp\serengeti-conversion-preview'
377
- postprocessing_options.image_base_dir = image_folder
378
- postprocessing_options.confidence_threshold = 0.2
379
- postprocessing_options.num_images_to_sample = None
380
- postprocessing_options.viz_target_width = 1280
381
- postprocessing_options.line_thickness = 4
382
- postprocessing_options.parallelize_rendering_n_cores = 10
383
- postprocessing_options.parallelize_rendering_with_threads = True
384
-
385
- postprocessing_results = process_batch_results(postprocessing_options)
386
-
387
- from megadetector.utils.path_utils import open_file
388
- open_file(postprocessing_results.output_html_file)
389
-
390
-
391
- #%% Command-line driver
392
-
393
- def main():
394
-
395
- parser = argparse.ArgumentParser()
396
- parser.add_argument('result_csv_file', type=str,
397
- help='csv file containing AI results')
398
- parser.add_argument('class_mapping_csv_file', type=str,
399
- help='csv file containing class mappings (with columns CLASS, SPECIES)')
400
- parser.add_argument('image_folder', type=str,
401
- help='folder containing the images referred to in [result_csv_file]')
402
- parser.add_argument('--output_file', type=str, default=None,
403
- help='.json file to which we should write results (defaults to [result_csv_file].json)')
404
-
405
- if len(sys.argv[1:])==0:
406
- parser.print_help()
407
- parser.exit()
408
-
409
- args = parser.parse_args()
410
- raic_csv_to_md_results(result_csv_file=args.result_csv_file,
411
- class_mapping_csv_file=args.class_mapping_csv_file,
412
- image_folder=args.image_folder,
413
- output_file=args.output_file)
414
-
415
- if __name__ == '__main__':
416
- main()