megadetector 5.0.9__py3-none-any.whl → 5.0.11__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 (226) hide show
  1. {megadetector-5.0.9.dist-info → megadetector-5.0.11.dist-info}/LICENSE +0 -0
  2. {megadetector-5.0.9.dist-info → megadetector-5.0.11.dist-info}/METADATA +12 -11
  3. megadetector-5.0.11.dist-info/RECORD +5 -0
  4. megadetector-5.0.11.dist-info/top_level.txt +1 -0
  5. api/__init__.py +0 -0
  6. api/batch_processing/__init__.py +0 -0
  7. api/batch_processing/api_core/__init__.py +0 -0
  8. api/batch_processing/api_core/batch_service/__init__.py +0 -0
  9. api/batch_processing/api_core/batch_service/score.py +0 -439
  10. api/batch_processing/api_core/server.py +0 -294
  11. api/batch_processing/api_core/server_api_config.py +0 -98
  12. api/batch_processing/api_core/server_app_config.py +0 -55
  13. api/batch_processing/api_core/server_batch_job_manager.py +0 -220
  14. api/batch_processing/api_core/server_job_status_table.py +0 -152
  15. api/batch_processing/api_core/server_orchestration.py +0 -360
  16. api/batch_processing/api_core/server_utils.py +0 -92
  17. api/batch_processing/api_core_support/__init__.py +0 -0
  18. api/batch_processing/api_core_support/aggregate_results_manually.py +0 -46
  19. api/batch_processing/api_support/__init__.py +0 -0
  20. api/batch_processing/api_support/summarize_daily_activity.py +0 -152
  21. api/batch_processing/data_preparation/__init__.py +0 -0
  22. api/batch_processing/data_preparation/manage_local_batch.py +0 -2391
  23. api/batch_processing/data_preparation/manage_video_batch.py +0 -327
  24. api/batch_processing/integration/digiKam/setup.py +0 -6
  25. api/batch_processing/integration/digiKam/xmp_integration.py +0 -465
  26. api/batch_processing/integration/eMammal/test_scripts/config_template.py +0 -5
  27. api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +0 -126
  28. api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +0 -55
  29. api/batch_processing/postprocessing/__init__.py +0 -0
  30. api/batch_processing/postprocessing/add_max_conf.py +0 -64
  31. api/batch_processing/postprocessing/categorize_detections_by_size.py +0 -163
  32. api/batch_processing/postprocessing/combine_api_outputs.py +0 -249
  33. api/batch_processing/postprocessing/compare_batch_results.py +0 -958
  34. api/batch_processing/postprocessing/convert_output_format.py +0 -397
  35. api/batch_processing/postprocessing/load_api_results.py +0 -195
  36. api/batch_processing/postprocessing/md_to_coco.py +0 -310
  37. api/batch_processing/postprocessing/md_to_labelme.py +0 -330
  38. api/batch_processing/postprocessing/merge_detections.py +0 -401
  39. api/batch_processing/postprocessing/postprocess_batch_results.py +0 -1904
  40. api/batch_processing/postprocessing/remap_detection_categories.py +0 -170
  41. api/batch_processing/postprocessing/render_detection_confusion_matrix.py +0 -661
  42. api/batch_processing/postprocessing/repeat_detection_elimination/find_repeat_detections.py +0 -211
  43. api/batch_processing/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +0 -82
  44. api/batch_processing/postprocessing/repeat_detection_elimination/repeat_detections_core.py +0 -1631
  45. api/batch_processing/postprocessing/separate_detections_into_folders.py +0 -731
  46. api/batch_processing/postprocessing/subset_json_detector_output.py +0 -696
  47. api/batch_processing/postprocessing/top_folders_to_bottom.py +0 -223
  48. api/synchronous/__init__.py +0 -0
  49. api/synchronous/api_core/animal_detection_api/__init__.py +0 -0
  50. api/synchronous/api_core/animal_detection_api/api_backend.py +0 -152
  51. api/synchronous/api_core/animal_detection_api/api_frontend.py +0 -266
  52. api/synchronous/api_core/animal_detection_api/config.py +0 -35
  53. api/synchronous/api_core/animal_detection_api/data_management/annotations/annotation_constants.py +0 -47
  54. api/synchronous/api_core/animal_detection_api/detection/detector_training/copy_checkpoints.py +0 -43
  55. api/synchronous/api_core/animal_detection_api/detection/detector_training/model_main_tf2.py +0 -114
  56. api/synchronous/api_core/animal_detection_api/detection/process_video.py +0 -543
  57. api/synchronous/api_core/animal_detection_api/detection/pytorch_detector.py +0 -304
  58. api/synchronous/api_core/animal_detection_api/detection/run_detector.py +0 -627
  59. api/synchronous/api_core/animal_detection_api/detection/run_detector_batch.py +0 -1029
  60. api/synchronous/api_core/animal_detection_api/detection/run_inference_with_yolov5_val.py +0 -581
  61. api/synchronous/api_core/animal_detection_api/detection/run_tiled_inference.py +0 -754
  62. api/synchronous/api_core/animal_detection_api/detection/tf_detector.py +0 -165
  63. api/synchronous/api_core/animal_detection_api/detection/video_utils.py +0 -495
  64. api/synchronous/api_core/animal_detection_api/md_utils/azure_utils.py +0 -174
  65. api/synchronous/api_core/animal_detection_api/md_utils/ct_utils.py +0 -262
  66. api/synchronous/api_core/animal_detection_api/md_utils/directory_listing.py +0 -251
  67. api/synchronous/api_core/animal_detection_api/md_utils/matlab_porting_tools.py +0 -97
  68. api/synchronous/api_core/animal_detection_api/md_utils/path_utils.py +0 -416
  69. api/synchronous/api_core/animal_detection_api/md_utils/process_utils.py +0 -110
  70. api/synchronous/api_core/animal_detection_api/md_utils/sas_blob_utils.py +0 -509
  71. api/synchronous/api_core/animal_detection_api/md_utils/string_utils.py +0 -59
  72. api/synchronous/api_core/animal_detection_api/md_utils/url_utils.py +0 -144
  73. api/synchronous/api_core/animal_detection_api/md_utils/write_html_image_list.py +0 -226
  74. api/synchronous/api_core/animal_detection_api/md_visualization/visualization_utils.py +0 -841
  75. api/synchronous/api_core/tests/__init__.py +0 -0
  76. api/synchronous/api_core/tests/load_test.py +0 -110
  77. classification/__init__.py +0 -0
  78. classification/aggregate_classifier_probs.py +0 -108
  79. classification/analyze_failed_images.py +0 -227
  80. classification/cache_batchapi_outputs.py +0 -198
  81. classification/create_classification_dataset.py +0 -627
  82. classification/crop_detections.py +0 -516
  83. classification/csv_to_json.py +0 -226
  84. classification/detect_and_crop.py +0 -855
  85. classification/efficientnet/__init__.py +0 -9
  86. classification/efficientnet/model.py +0 -415
  87. classification/efficientnet/utils.py +0 -610
  88. classification/evaluate_model.py +0 -520
  89. classification/identify_mislabeled_candidates.py +0 -152
  90. classification/json_to_azcopy_list.py +0 -63
  91. classification/json_validator.py +0 -695
  92. classification/map_classification_categories.py +0 -276
  93. classification/merge_classification_detection_output.py +0 -506
  94. classification/prepare_classification_script.py +0 -194
  95. classification/prepare_classification_script_mc.py +0 -228
  96. classification/run_classifier.py +0 -286
  97. classification/save_mislabeled.py +0 -110
  98. classification/train_classifier.py +0 -825
  99. classification/train_classifier_tf.py +0 -724
  100. classification/train_utils.py +0 -322
  101. data_management/__init__.py +0 -0
  102. data_management/annotations/__init__.py +0 -0
  103. data_management/annotations/annotation_constants.py +0 -34
  104. data_management/camtrap_dp_to_coco.py +0 -238
  105. data_management/cct_json_utils.py +0 -395
  106. data_management/cct_to_md.py +0 -176
  107. data_management/cct_to_wi.py +0 -289
  108. data_management/coco_to_labelme.py +0 -272
  109. data_management/coco_to_yolo.py +0 -662
  110. data_management/databases/__init__.py +0 -0
  111. data_management/databases/add_width_and_height_to_db.py +0 -33
  112. data_management/databases/combine_coco_camera_traps_files.py +0 -206
  113. data_management/databases/integrity_check_json_db.py +0 -477
  114. data_management/databases/subset_json_db.py +0 -115
  115. data_management/generate_crops_from_cct.py +0 -149
  116. data_management/get_image_sizes.py +0 -188
  117. data_management/importers/add_nacti_sizes.py +0 -52
  118. data_management/importers/add_timestamps_to_icct.py +0 -79
  119. data_management/importers/animl_results_to_md_results.py +0 -158
  120. data_management/importers/auckland_doc_test_to_json.py +0 -372
  121. data_management/importers/auckland_doc_to_json.py +0 -200
  122. data_management/importers/awc_to_json.py +0 -189
  123. data_management/importers/bellevue_to_json.py +0 -273
  124. data_management/importers/cacophony-thermal-importer.py +0 -796
  125. data_management/importers/carrizo_shrubfree_2018.py +0 -268
  126. data_management/importers/carrizo_trail_cam_2017.py +0 -287
  127. data_management/importers/cct_field_adjustments.py +0 -57
  128. data_management/importers/channel_islands_to_cct.py +0 -913
  129. data_management/importers/eMammal/copy_and_unzip_emammal.py +0 -180
  130. data_management/importers/eMammal/eMammal_helpers.py +0 -249
  131. data_management/importers/eMammal/make_eMammal_json.py +0 -223
  132. data_management/importers/ena24_to_json.py +0 -275
  133. data_management/importers/filenames_to_json.py +0 -385
  134. data_management/importers/helena_to_cct.py +0 -282
  135. data_management/importers/idaho-camera-traps.py +0 -1407
  136. data_management/importers/idfg_iwildcam_lila_prep.py +0 -294
  137. data_management/importers/jb_csv_to_json.py +0 -150
  138. data_management/importers/mcgill_to_json.py +0 -250
  139. data_management/importers/missouri_to_json.py +0 -489
  140. data_management/importers/nacti_fieldname_adjustments.py +0 -79
  141. data_management/importers/noaa_seals_2019.py +0 -181
  142. data_management/importers/pc_to_json.py +0 -365
  143. data_management/importers/plot_wni_giraffes.py +0 -123
  144. data_management/importers/prepare-noaa-fish-data-for-lila.py +0 -359
  145. data_management/importers/prepare_zsl_imerit.py +0 -131
  146. data_management/importers/rspb_to_json.py +0 -356
  147. data_management/importers/save_the_elephants_survey_A.py +0 -320
  148. data_management/importers/save_the_elephants_survey_B.py +0 -332
  149. data_management/importers/snapshot_safari_importer.py +0 -758
  150. data_management/importers/snapshot_safari_importer_reprise.py +0 -665
  151. data_management/importers/snapshot_serengeti_lila.py +0 -1067
  152. data_management/importers/snapshotserengeti/make_full_SS_json.py +0 -150
  153. data_management/importers/snapshotserengeti/make_per_season_SS_json.py +0 -153
  154. data_management/importers/sulross_get_exif.py +0 -65
  155. data_management/importers/timelapse_csv_set_to_json.py +0 -490
  156. data_management/importers/ubc_to_json.py +0 -399
  157. data_management/importers/umn_to_json.py +0 -507
  158. data_management/importers/wellington_to_json.py +0 -263
  159. data_management/importers/wi_to_json.py +0 -441
  160. data_management/importers/zamba_results_to_md_results.py +0 -181
  161. data_management/labelme_to_coco.py +0 -548
  162. data_management/labelme_to_yolo.py +0 -272
  163. data_management/lila/__init__.py +0 -0
  164. data_management/lila/add_locations_to_island_camera_traps.py +0 -97
  165. data_management/lila/add_locations_to_nacti.py +0 -147
  166. data_management/lila/create_lila_blank_set.py +0 -557
  167. data_management/lila/create_lila_test_set.py +0 -151
  168. data_management/lila/create_links_to_md_results_files.py +0 -106
  169. data_management/lila/download_lila_subset.py +0 -177
  170. data_management/lila/generate_lila_per_image_labels.py +0 -515
  171. data_management/lila/get_lila_annotation_counts.py +0 -170
  172. data_management/lila/get_lila_image_counts.py +0 -111
  173. data_management/lila/lila_common.py +0 -300
  174. data_management/lila/test_lila_metadata_urls.py +0 -132
  175. data_management/ocr_tools.py +0 -874
  176. data_management/read_exif.py +0 -681
  177. data_management/remap_coco_categories.py +0 -84
  178. data_management/remove_exif.py +0 -66
  179. data_management/resize_coco_dataset.py +0 -189
  180. data_management/wi_download_csv_to_coco.py +0 -246
  181. data_management/yolo_output_to_md_output.py +0 -441
  182. data_management/yolo_to_coco.py +0 -676
  183. detection/__init__.py +0 -0
  184. detection/detector_training/__init__.py +0 -0
  185. detection/detector_training/model_main_tf2.py +0 -114
  186. detection/process_video.py +0 -703
  187. detection/pytorch_detector.py +0 -337
  188. detection/run_detector.py +0 -779
  189. detection/run_detector_batch.py +0 -1219
  190. detection/run_inference_with_yolov5_val.py +0 -917
  191. detection/run_tiled_inference.py +0 -935
  192. detection/tf_detector.py +0 -188
  193. detection/video_utils.py +0 -606
  194. docs/source/conf.py +0 -43
  195. md_utils/__init__.py +0 -0
  196. md_utils/azure_utils.py +0 -174
  197. md_utils/ct_utils.py +0 -612
  198. md_utils/directory_listing.py +0 -246
  199. md_utils/md_tests.py +0 -968
  200. md_utils/path_utils.py +0 -1044
  201. md_utils/process_utils.py +0 -157
  202. md_utils/sas_blob_utils.py +0 -509
  203. md_utils/split_locations_into_train_val.py +0 -228
  204. md_utils/string_utils.py +0 -92
  205. md_utils/url_utils.py +0 -323
  206. md_utils/write_html_image_list.py +0 -225
  207. md_visualization/__init__.py +0 -0
  208. md_visualization/plot_utils.py +0 -293
  209. md_visualization/render_images_with_thumbnails.py +0 -275
  210. md_visualization/visualization_utils.py +0 -1537
  211. md_visualization/visualize_db.py +0 -551
  212. md_visualization/visualize_detector_output.py +0 -406
  213. megadetector-5.0.9.dist-info/RECORD +0 -224
  214. megadetector-5.0.9.dist-info/top_level.txt +0 -8
  215. taxonomy_mapping/__init__.py +0 -0
  216. taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +0 -491
  217. taxonomy_mapping/map_new_lila_datasets.py +0 -154
  218. taxonomy_mapping/prepare_lila_taxonomy_release.py +0 -142
  219. taxonomy_mapping/preview_lila_taxonomy.py +0 -591
  220. taxonomy_mapping/retrieve_sample_image.py +0 -71
  221. taxonomy_mapping/simple_image_download.py +0 -218
  222. taxonomy_mapping/species_lookup.py +0 -834
  223. taxonomy_mapping/taxonomy_csv_checker.py +0 -159
  224. taxonomy_mapping/taxonomy_graph.py +0 -346
  225. taxonomy_mapping/validate_lila_category_mappings.py +0 -83
  226. {megadetector-5.0.9.dist-info → megadetector-5.0.11.dist-info}/WHEEL +0 -0
@@ -1,200 +0,0 @@
1
- """
2
-
3
- auckland_doc_to_json.py
4
-
5
- Convert Auckland DOC data set to COCO camera traps format. This was
6
- for a training data set where class names were encoded in path names.
7
-
8
- """
9
-
10
- #%% Constants and imports
11
-
12
- import json
13
- import os
14
- import uuid
15
- import datetime
16
- from tqdm import tqdm
17
-
18
- from md_visualization import visualize_db
19
- from data_management.databases import integrity_check_json_db
20
- from md_utils.path_utils import find_images, split_path, insert_before_extension
21
-
22
- # Filenames will be stored in the output .json relative to this base dir
23
- input_base_dir = 'y:\\'
24
- output_base_dir = r'f:\auckland-doc'
25
- output_json_filename = os.path.join(output_base_dir, 'auckland-doc-Maukahuka_Auckland_Island.json')
26
-
27
- assert os.path.isdir(input_base_dir)
28
- os.makedirs(output_base_dir,exist_ok=True)
29
-
30
- output_encoding = 'utf-8'
31
- read_image_sizes = True
32
-
33
- info = {}
34
- info['year'] = 2019
35
- info['version'] = '1.0'
36
- info['description'] = 'Auckaland DOC Camera Traps'
37
- info['contributor'] = 'Auckland DOC'
38
- info['date_created'] = str(datetime.date.today())
39
-
40
-
41
- #%% Enumerate files
42
-
43
- print('Enumerating files from {}'.format(input_base_dir))
44
- image_files = find_images(input_base_dir, bRecursive=True)
45
- print('Enumerated {} images'.format(len(image_files)))
46
-
47
-
48
- #%% Assemble dictionaries
49
-
50
- images = []
51
- image_id_to_image = {}
52
- annotations = []
53
- categories = []
54
-
55
- category_name_to_category = {}
56
- category_id_to_category = {}
57
-
58
- # Force the empty category to be ID 0
59
- empty_category = {}
60
- empty_category['name'] = 'empty'
61
- empty_category['id'] = 0
62
- category_id_to_category[0] = empty_category
63
- categories.append(empty_category)
64
- next_id = 1
65
-
66
- behaviors = set()
67
-
68
- # fn = image_files[0]; print(fn)
69
- for fn in tqdm(image_files):
70
-
71
- # Typically y:\Maukahuka_Auckland_Island\1_Training\Winter_Trial_2019\cat\cat\eat\20190903_IDdY_34_E3_tmp_201908240051.JPG
72
- relative_path = os.path.relpath(fn,input_base_dir)
73
- tokens = split_path(fn)
74
- assert tokens[1] == 'Maukahuka_Auckland_Island'
75
-
76
- trainval_split = tokens[2]
77
- assert trainval_split in ['1_Training','2_Testing']
78
-
79
- # This data set has two top-level folders, "1_Training" (which has class names encoded
80
- # in paths) and "2_Testing" (which has no class information).
81
- if trainval_split == '2_Testing':
82
- category_name = 'test'
83
- else:
84
- category_name = tokens[-3]
85
- if category_name.startswith('2_'):
86
- category_name = category_name.replace('2_', '')
87
- category_name = category_name.lower().strip()
88
-
89
- if category_name not in category_name_to_category:
90
-
91
- category_id = next_id
92
- next_id += 1
93
- category = {}
94
- category['id'] = category_id
95
- category['name'] = category_name
96
- category['count'] = 0
97
- categories.append(category)
98
- category_name_to_category[category_name] = category
99
- category_id_to_category[category_id] = category
100
-
101
- else:
102
-
103
- category = category_name_to_category[category_name]
104
-
105
- category_id = category['id']
106
-
107
- category['count'] += 1
108
- behavior = None
109
- if (category_name) != 'test':
110
- behavior = fn.split('\\')[-2]
111
- behaviors.add(behavior)
112
-
113
- im = {}
114
- im['id'] = str(uuid.uuid1())
115
- im['file_name'] = relative_path
116
- image_id_to_image[im['id']] = im
117
-
118
- images.append(im)
119
-
120
- ann = {}
121
-
122
- ann['id'] = str(uuid.uuid1())
123
- ann['image_id'] = im['id']
124
- ann['category_id'] = category_id
125
- if behavior is not None:
126
- ann['behavior'] = behavior
127
- annotations.append(ann)
128
-
129
- # ...for each image
130
-
131
-
132
- #%% Write output .json
133
-
134
- data = {}
135
- data['info'] = info
136
- data['images'] = images
137
- data['annotations'] = annotations
138
- data['categories'] = categories
139
-
140
- json.dump(data, open(output_json_filename, 'w'), indent=2)
141
- print('Finished writing json to {}'.format(output_json_filename))
142
-
143
-
144
- #%% Write train/test .jsons
145
-
146
- train_images = []; test_images = []
147
- train_annotations = []; test_annotations = []
148
-
149
- for ann in tqdm(annotations):
150
- category_id = ann['category_id']
151
- image_id = ann['image_id']
152
- category_name = category_id_to_category[category_id]['name']
153
- im = image_id_to_image[image_id]
154
- if category_name == 'test':
155
- test_images.append(im)
156
- test_annotations.append(ann)
157
- else:
158
- train_images.append(im)
159
- train_annotations.append(ann)
160
-
161
- train_fn = insert_before_extension(output_json_filename,'train')
162
- test_fn = insert_before_extension(output_json_filename,'test')
163
-
164
- data['images'] = train_images
165
- data['annotations'] = train_annotations
166
- json.dump(data, open(train_fn, 'w'), indent=2)
167
-
168
- data['images'] = test_images
169
- data['annotations'] = test_annotations
170
- json.dump(data, open(test_fn, 'w'), indent=2)
171
-
172
-
173
- #%% Validate .json files
174
-
175
- options = integrity_check_json_db.IntegrityCheckOptions()
176
- options.baseDir = input_base_dir
177
- options.bCheckImageSizes = False
178
- options.bCheckImageExistence = True
179
- options.bFindUnusedImages = True
180
-
181
- sorted_categories, data, _ = integrity_check_json_db.integrity_check_json_db(output_json_filename, options)
182
- sorted_categories, data, _ = integrity_check_json_db.integrity_check_json_db(train_fn, options)
183
- sorted_categories, data, _ = integrity_check_json_db.integrity_check_json_db(test_fn, options)
184
-
185
-
186
- #%% Preview labels
187
-
188
- viz_options = visualize_db.DbVizOptions()
189
- viz_options.num_to_visualize = 2000
190
- viz_options.trim_to_images_with_bboxes = False
191
- viz_options.add_search_links = False
192
- viz_options.sort_by_filename = False
193
- viz_options.parallelize_rendering = True
194
- viz_options.classes_to_exclude = ['test']
195
- html_output_file, image_db = visualize_db.visualize_db(db_path=output_json_filename,
196
- output_dir=os.path.join(
197
- output_base_dir, 'preview'),
198
- image_base_dir=input_base_dir,
199
- options=viz_options)
200
- os.startfile(html_output_file)
@@ -1,189 +0,0 @@
1
- """
2
-
3
- awc_to_json.py
4
-
5
- Convert a particular .csv file from Australian Wildlife Conservancy to CCT format.
6
-
7
- """
8
-
9
- #%% Constants and environment
10
-
11
- import pandas as pd
12
- import uuid
13
- import json
14
- import time
15
- from tqdm import tqdm
16
- import humanfriendly
17
- import os
18
- import PIL
19
- from md_visualization import visualize_db
20
- from md_utils import path_utils
21
-
22
- input_metadata_file = r"D:\wildlife_data\awc\awc_imageinfo.csv"
23
- output_file = r"D:\wildlife_data\awc\awc_imageinfo.json"
24
- image_base = r"D:\wildlife_data\awc"
25
- preview_base = r"D:\wildlife_data\awc\label_preview"
26
-
27
- filename_replacements = {'D:\\Wet Tropics':'WetTropics'}
28
- category_mappings = {'none':'empty'}
29
-
30
-
31
- #%% Read source data
32
-
33
- input_metadata = pd.read_csv(input_metadata_file)
34
-
35
- print('Read {} columns and {} rows from metadata file'.format(len(input_metadata.columns),
36
- len(input_metadata)))
37
-
38
-
39
- #%% Main loop over labels
40
-
41
- startTime = time.time()
42
-
43
- relativePathToImage = {}
44
-
45
- images = []
46
- annotations = []
47
- categoryIDToCategories = {}
48
- missingFiles = []
49
-
50
- duplicateImageIDs = set()
51
-
52
- # Force the empty category to be ID 0
53
- emptyCat = {}
54
- emptyCat['name'] = 'empty'
55
- emptyCat['id'] = 0
56
- categoryIDToCategories[0] = emptyCat
57
-
58
- # iRow = 0; row = input_metadata.iloc[iRow]
59
- for iRow,row in tqdm(input_metadata.iterrows(),total=len(input_metadata)):
60
-
61
- # ImageID,FileName,FilePath,SpeciesID,CommonName
62
- imageID = str(row['ImageID'])
63
- fn = row['FileName']
64
- for k in filename_replacements:
65
- dirName = row['FilePath'].replace(k,filename_replacements[k])
66
- relativePath = os.path.join(dirName,fn)
67
-
68
- # This makes an assumption of one annotation per image, which happens to be
69
- # true in this data set.
70
- if relativePath in relativePathToImage:
71
-
72
- im = relativePathToImage[relativePath]
73
- assert im['id'] == imageID
74
- duplicateImageIDs.add(imageID)
75
-
76
- else:
77
- im = {}
78
- im['id'] = imageID
79
- im['file_name'] = relativePath
80
- im['seq_id'] = '-1'
81
- images.append(im)
82
- relativePathToImage[relativePath] = im
83
-
84
- fullPath = os.path.join(image_base,relativePath)
85
-
86
- if not os.path.isfile(fullPath):
87
-
88
- missingFiles.append(fullPath)
89
-
90
- else:
91
- # Retrieve image width and height
92
- pilImage = PIL.Image.open(fullPath)
93
- width, height = pilImage.size
94
- im['width'] = width
95
- im['height'] = height
96
-
97
- categoryName = row['CommonName'].lower()
98
- if categoryName in category_mappings:
99
- categoryName = category_mappings[categoryName]
100
-
101
- categoryID = row['SpeciesID']
102
- assert isinstance(categoryID,int)
103
-
104
- if categoryID not in categoryIDToCategories:
105
- category = {}
106
- category['name'] = categoryName
107
- category['id'] = categoryID
108
- categoryIDToCategories[categoryID] = category
109
- else:
110
- assert categoryIDToCategories[categoryID]['name'] == categoryName
111
-
112
- # Create an annotation
113
- ann = {}
114
-
115
- # The Internet tells me this guarantees uniqueness to a reasonable extent, even
116
- # beyond the sheer improbability of collisions.
117
- ann['id'] = str(uuid.uuid1())
118
- ann['image_id'] = im['id']
119
- ann['category_id'] = categoryID
120
-
121
- annotations.append(ann)
122
-
123
- categories = list(categoryIDToCategories.values())
124
-
125
- elapsed = time.time() - startTime
126
- print('Finished verifying file loop in {}, {} images, {} missing images, {} repeat labels'.format(
127
- humanfriendly.format_timespan(elapsed), len(images), len(missingFiles), len(duplicateImageIDs)))
128
-
129
-
130
- #%% Check for images that aren't included in the metadata file
131
-
132
- # Enumerate all images
133
- # list(relativePathToImage.keys())[0]
134
-
135
- imageFullPaths = path_utils.find_images(image_base,bRecursive=True)
136
- unmatchedFiles = []
137
-
138
- for iImage,imagePath in enumerate(imageFullPaths):
139
-
140
- fn = os.path.relpath(imagePath,image_base)
141
- if fn not in relativePathToImage:
142
- unmatchedFiles.append(fn)
143
-
144
- print('Finished checking {} images to make sure they\'re in the metadata, found {} mismatches'.format(
145
- len(imageFullPaths),len(unmatchedFiles)))
146
-
147
-
148
- #%% Create info struct
149
-
150
- info = {}
151
- info['year'] = 2019
152
- info['version'] = 1
153
- info['description'] = 'COCO style database'
154
- info['secondary_contributor'] = 'Converted to COCO .json by Dan Morris'
155
- info['contributor'] = ''
156
-
157
-
158
- #%% Write output
159
-
160
- json_data = {}
161
- json_data['images'] = images
162
- json_data['annotations'] = annotations
163
- json_data['categories'] = categories
164
- json_data['info'] = info
165
- json.dump(json_data, open(output_file,'w'), indent=4)
166
-
167
- print('Finished writing .json file with {} images, {} annotations, and {} categories'.format(
168
- len(images),len(annotations),len(categories)))
169
-
170
-
171
- #%% Validate the database's integrity
172
-
173
- from data_management.databases import integrity_check_json_db
174
-
175
- options = integrity_check_json_db.IntegrityCheckOptions()
176
- sortedCategories,data = integrity_check_json_db.integrity_check_json_db(output_file, options)
177
-
178
-
179
- #%% Render a bunch of images to make sure the labels got carried along correctly
180
-
181
- bbox_db_path = output_file
182
- output_dir = preview_base
183
-
184
- options = visualize_db.BboxDbVizOptions()
185
- options.num_to_visualize = 1000
186
- options.sort_by_filename = False
187
-
188
- htmlOutputFile = visualize_db.visualize_db(bbox_db_path,output_dir,image_base,options)
189
-
@@ -1,273 +0,0 @@
1
- """
2
-
3
- bellevue_to_json.py
4
-
5
- "Bellevue Camera Traps" is the rather unremarkable camera trap data set
6
- used by one of the repo's maintainers for testing. It's organized as:
7
-
8
- approximate_date/[loose_camera_specifier/]/species
9
-
10
- E.g.:
11
-
12
- "2018.03.30\coyote\DSCF0091.JPG"
13
- "2018.07.18\oldcam\empty\DSCF0001.JPG"
14
-
15
- """
16
-
17
- #%% Constants and imports
18
-
19
- import json
20
- import os
21
- import uuid
22
- import datetime
23
-
24
- from PIL import Image
25
- from PIL.ExifTags import TAGS
26
- from tqdm import tqdm
27
-
28
- from md_utils.path_utils import find_images
29
-
30
- # Filenames will be stored in the output .json relative to this base dir
31
- base_dir = r'C:\temp\camera_trap_images_no_people'
32
- output_base = r'c:\temp\previews'
33
- output_filename = os.path.join(base_dir,'bellevue_camera_traps.{}.json'.format(str(datetime.date.today())))
34
-
35
- class_mappings = {'transitional':'unlabeled','moving':'unlabeled','setup':'unlabeled','blurry':'unlabeled','transitional':'unlabeled','junk':'unlabeled','unknown':'unlabeled','blurry':'unlabeled'}
36
- class_mappings['dan'] = 'human'
37
- class_mappings['dan_and_dog'] = 'human,dog'
38
- class_mappings['dan and dog'] = 'human,dog'
39
- class_mappings['unknown'] = 'unknown animal'
40
- class_mappings['racoon'] = 'raccoon'
41
-
42
-
43
- info = {}
44
- info['year'] = 2020
45
- info['version'] = '2.0'
46
- info['description'] = 'Bellevue Camera Traps'
47
- info['contributor'] = 'Dan Morris'
48
- info['date_created'] = str(datetime.date.today())
49
-
50
- max_files = -1
51
-
52
- max_seconds_within_sequence = 10.0
53
-
54
- assert os.path.isdir(base_dir)
55
-
56
- #%% Exif functions
57
-
58
- def get_exif_tags(fn=None,im=None):
59
-
60
- assert (fn is not None) or (im is not None)
61
- ret = {}
62
- if im is None:
63
- im = Image.open(fn)
64
- info = im._getexif()
65
- for tag, value in info.items():
66
- decoded = TAGS.get(tag, tag)
67
- ret[decoded] = value
68
-
69
- return ret
70
-
71
-
72
- #%% Enumerate files, create image/annotation/category info
73
-
74
- annotations = []
75
-
76
- category_name_to_category = {}
77
-
78
- # Force the empty category to be ID 0
79
- empty_category = {}
80
- empty_category['id'] = 0
81
- empty_category['name'] = 'empty'
82
- category_name_to_category['empty'] = empty_category
83
- next_category_id = 1
84
-
85
- # Keep track of unique camera folders
86
- camera_folders = set()
87
-
88
- # Each element will be a dictionary with fields:
89
- #
90
- # relative_path, width, height, datetime
91
- images = []
92
- non_image_files = []
93
-
94
- print('Enumerating files from {}'.format(base_dir))
95
-
96
- image_files = find_images(base_dir,recursive=True)
97
- print('Enumerated {} images'.format(len(image_files)))
98
-
99
- # fname = image_files[0]
100
- for fname in tqdm(image_files):
101
-
102
- if max_files >= 0 and len(images) > max_files:
103
- print('Warning: early break at {} files'.format(max_files))
104
- break
105
-
106
- full_path = fname
107
- relative_path = os.path.relpath(full_path,base_dir)
108
-
109
- try:
110
- im = Image.open(full_path)
111
- h = im.height
112
- w = im.width
113
- tags = get_exif_tags(None,im)
114
- s = tags['DateTimeOriginal']
115
- dt = datetime.datetime.strptime(s,'%Y:%m:%d %H:%M:%S')
116
- except:
117
- # Corrupt or not an image
118
- print('Warning: could not read {}'.format(fname))
119
- non_image_files.append(full_path)
120
- continue
121
-
122
- # Store file info
123
- image_info = {}
124
- image_info['file_name'] = relative_path
125
- image_info['width'] = w
126
- image_info['height'] = h
127
- image_info['datetime'] = dt
128
- image_info['location'] = 'unknown'
129
- image_info['id'] = str(uuid.uuid4())
130
-
131
- images.append(image_info)
132
-
133
- # E.g. 2018.03.30/coyote/DSCF0091.JPG
134
- relative_path = image_info['file_name'].replace('\\','/')
135
- tokens = relative_path.split('/')
136
- camera_path_tokens = tokens[0:-2]
137
- camera_path = '/'.join(camera_path_tokens)
138
- camera_folders.add(camera_path)
139
- image_info['camera_path'] = camera_path
140
-
141
- category_name = tokens[-2].lower()
142
- if category_name in class_mappings:
143
- category_name = class_mappings[category_name]
144
-
145
- if category_name not in category_name_to_category:
146
- category = {}
147
- category['id'] = next_category_id
148
- category['name'] = category_name
149
- next_category_id = next_category_id + 1
150
- category_name_to_category[category_name] = category
151
- else:
152
- category = category_name_to_category[category_name]
153
-
154
- annotation = {}
155
- annotation['sequence_level_annotation'] = False
156
- annotation['id'] = str(uuid.uuid4())
157
- annotation['category_id'] = category['id']
158
- annotation['image_id'] = image_info['id']
159
- annotations.append(annotation)
160
-
161
- # ...for each image file
162
-
163
- assert len(annotations) == len(images)
164
-
165
- categories = list(category_name_to_category.values())
166
-
167
-
168
- #%% Synthesize sequence information
169
-
170
- print('Found {} camera folders'.format(len(camera_folders)))
171
-
172
- camera_folders = list(camera_folders)
173
-
174
- all_sequences = set()
175
-
176
- # Sort images by time within each folder
177
- # camera_path = camera_folders[0]
178
- for i_camera,camera_path in enumerate(camera_folders):
179
-
180
- images_this_camera = [im for im in images if im['camera_path'] == camera_path]
181
- sorted_images_this_camera = sorted(images_this_camera, key = lambda im: im['datetime'])
182
-
183
- current_sequence_id = None
184
- next_sequence_index = 0
185
- previous_datetime = None
186
-
187
- # previous_datetime = sorted_images_this_camera[0]['datetime']
188
- # im = sorted_images_this_camera[1]
189
- for im in sorted_images_this_camera:
190
-
191
- if previous_datetime is None:
192
- delta = None
193
- else:
194
- delta = (im['datetime'] - previous_datetime).total_seconds()
195
-
196
- # Start a new sequence if necessary
197
- if delta is None or delta > max_seconds_within_sequence:
198
- next_sequence_index = 0
199
- current_sequence_id = str(uuid.uuid4())
200
- all_sequences.add(current_sequence_id)
201
-
202
- im['seq_id'] = current_sequence_id
203
- im['seq_num_frames'] = None
204
- im['frame_num'] = next_sequence_index
205
- next_sequence_index = next_sequence_index + 1
206
- previous_datetime = im['datetime']
207
-
208
- # ...for each image in this camera
209
-
210
- # ...for each camera
211
-
212
- print('Created {} sequences from {} images'.format(len(all_sequences),len(images)))
213
-
214
- # Fill in seq_num_frames
215
- num_frames_per_sequence = {}
216
- for seq_id in all_sequences:
217
- images_this_sequence = [im for im in images if im['seq_id'] == seq_id]
218
- num_frames_per_sequence[seq_id] = len(images_this_sequence)
219
- for im in images_this_sequence:
220
- im['seq_num_frames'] = len(images_this_sequence)
221
-
222
-
223
- #%% A little cleanup
224
-
225
- for im in tqdm(images):
226
- if 'camera_path' in im:
227
- del im['camera_path']
228
- if not isinstance(im['datetime'],str):
229
- im['datetime'] = str(im['datetime'])
230
-
231
-
232
- #%% Write output .json
233
-
234
- data = {}
235
- data['info'] = info
236
- data['images'] = images
237
- data['annotations'] = annotations
238
- data['categories'] = categories
239
-
240
- json.dump(data, open(output_filename,'w'), indent=1)
241
-
242
- print('Finished writing json to {}'.format(output_filename))
243
-
244
-
245
- #%% Validate data
246
-
247
- from data_management.databases import integrity_check_json_db
248
-
249
- options = integrity_check_json_db.IntegrityCheckOptions()
250
- options.baseDir = base_dir
251
- options.bCheckImageSizes = False
252
- options.bCheckImageExistence = True
253
- options.bFindUnusedImages = False
254
-
255
- sorted_categories = integrity_check_json_db.integrity_check_json_db(output_filename,options)
256
-
257
-
258
- #%% Label previews
259
-
260
- from md_visualization import visualize_db
261
-
262
- viz_options = visualize_db.DbVizOptions()
263
- viz_options.num_to_visualize = None
264
- viz_options.parallelize_rendering_n_cores = 8
265
- viz_options.parallelize_rendering = True
266
- viz_options.trim_to_images_with_bboxes = False
267
- viz_options.add_search_links = True
268
- viz_options.sort_by_filename = False
269
- html_output_file,image_db = visualize_db.visualize_db(output_filename,
270
- os.path.join(output_base,'preview'),
271
- base_dir,viz_options)
272
- os.startfile(html_output_file)
273
-