megadetector 5.0.28__py3-none-any.whl → 10.0.0__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 (197) hide show
  1. megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +2 -2
  2. megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +1 -1
  3. megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +1 -1
  4. megadetector/classification/aggregate_classifier_probs.py +3 -3
  5. megadetector/classification/analyze_failed_images.py +5 -5
  6. megadetector/classification/cache_batchapi_outputs.py +5 -5
  7. megadetector/classification/create_classification_dataset.py +11 -12
  8. megadetector/classification/crop_detections.py +10 -10
  9. megadetector/classification/csv_to_json.py +8 -8
  10. megadetector/classification/detect_and_crop.py +13 -15
  11. megadetector/classification/efficientnet/model.py +8 -8
  12. megadetector/classification/efficientnet/utils.py +6 -5
  13. megadetector/classification/evaluate_model.py +7 -7
  14. megadetector/classification/identify_mislabeled_candidates.py +6 -6
  15. megadetector/classification/json_to_azcopy_list.py +1 -1
  16. megadetector/classification/json_validator.py +29 -32
  17. megadetector/classification/map_classification_categories.py +9 -9
  18. megadetector/classification/merge_classification_detection_output.py +12 -9
  19. megadetector/classification/prepare_classification_script.py +19 -19
  20. megadetector/classification/prepare_classification_script_mc.py +26 -26
  21. megadetector/classification/run_classifier.py +4 -4
  22. megadetector/classification/save_mislabeled.py +6 -6
  23. megadetector/classification/train_classifier.py +1 -1
  24. megadetector/classification/train_classifier_tf.py +9 -9
  25. megadetector/classification/train_utils.py +10 -10
  26. megadetector/data_management/annotations/annotation_constants.py +1 -2
  27. megadetector/data_management/camtrap_dp_to_coco.py +79 -46
  28. megadetector/data_management/cct_json_utils.py +103 -103
  29. megadetector/data_management/cct_to_md.py +49 -49
  30. megadetector/data_management/cct_to_wi.py +33 -33
  31. megadetector/data_management/coco_to_labelme.py +75 -75
  32. megadetector/data_management/coco_to_yolo.py +210 -193
  33. megadetector/data_management/databases/add_width_and_height_to_db.py +86 -12
  34. megadetector/data_management/databases/combine_coco_camera_traps_files.py +40 -40
  35. megadetector/data_management/databases/integrity_check_json_db.py +228 -200
  36. megadetector/data_management/databases/subset_json_db.py +33 -33
  37. megadetector/data_management/generate_crops_from_cct.py +88 -39
  38. megadetector/data_management/get_image_sizes.py +54 -49
  39. megadetector/data_management/labelme_to_coco.py +133 -125
  40. megadetector/data_management/labelme_to_yolo.py +159 -73
  41. megadetector/data_management/lila/create_lila_blank_set.py +81 -83
  42. megadetector/data_management/lila/create_lila_test_set.py +32 -31
  43. megadetector/data_management/lila/create_links_to_md_results_files.py +18 -18
  44. megadetector/data_management/lila/download_lila_subset.py +21 -24
  45. megadetector/data_management/lila/generate_lila_per_image_labels.py +365 -107
  46. megadetector/data_management/lila/get_lila_annotation_counts.py +35 -33
  47. megadetector/data_management/lila/get_lila_image_counts.py +22 -22
  48. megadetector/data_management/lila/lila_common.py +73 -70
  49. megadetector/data_management/lila/test_lila_metadata_urls.py +28 -19
  50. megadetector/data_management/mewc_to_md.py +344 -340
  51. megadetector/data_management/ocr_tools.py +262 -255
  52. megadetector/data_management/read_exif.py +249 -227
  53. megadetector/data_management/remap_coco_categories.py +90 -28
  54. megadetector/data_management/remove_exif.py +81 -21
  55. megadetector/data_management/rename_images.py +187 -187
  56. megadetector/data_management/resize_coco_dataset.py +588 -120
  57. megadetector/data_management/speciesnet_to_md.py +41 -41
  58. megadetector/data_management/wi_download_csv_to_coco.py +55 -55
  59. megadetector/data_management/yolo_output_to_md_output.py +248 -122
  60. megadetector/data_management/yolo_to_coco.py +333 -191
  61. megadetector/detection/change_detection.py +832 -0
  62. megadetector/detection/process_video.py +340 -337
  63. megadetector/detection/pytorch_detector.py +358 -278
  64. megadetector/detection/run_detector.py +399 -186
  65. megadetector/detection/run_detector_batch.py +404 -377
  66. megadetector/detection/run_inference_with_yolov5_val.py +340 -327
  67. megadetector/detection/run_tiled_inference.py +257 -249
  68. megadetector/detection/tf_detector.py +24 -24
  69. megadetector/detection/video_utils.py +332 -295
  70. megadetector/postprocessing/add_max_conf.py +19 -11
  71. megadetector/postprocessing/categorize_detections_by_size.py +45 -45
  72. megadetector/postprocessing/classification_postprocessing.py +468 -433
  73. megadetector/postprocessing/combine_batch_outputs.py +23 -23
  74. megadetector/postprocessing/compare_batch_results.py +590 -525
  75. megadetector/postprocessing/convert_output_format.py +106 -102
  76. megadetector/postprocessing/create_crop_folder.py +347 -147
  77. megadetector/postprocessing/detector_calibration.py +173 -168
  78. megadetector/postprocessing/generate_csv_report.py +508 -499
  79. megadetector/postprocessing/load_api_results.py +48 -27
  80. megadetector/postprocessing/md_to_coco.py +133 -102
  81. megadetector/postprocessing/md_to_labelme.py +107 -90
  82. megadetector/postprocessing/md_to_wi.py +40 -40
  83. megadetector/postprocessing/merge_detections.py +92 -114
  84. megadetector/postprocessing/postprocess_batch_results.py +319 -301
  85. megadetector/postprocessing/remap_detection_categories.py +91 -38
  86. megadetector/postprocessing/render_detection_confusion_matrix.py +214 -205
  87. megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +57 -57
  88. megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +27 -28
  89. megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +704 -679
  90. megadetector/postprocessing/separate_detections_into_folders.py +226 -211
  91. megadetector/postprocessing/subset_json_detector_output.py +265 -262
  92. megadetector/postprocessing/top_folders_to_bottom.py +45 -45
  93. megadetector/postprocessing/validate_batch_results.py +70 -70
  94. megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +52 -52
  95. megadetector/taxonomy_mapping/map_new_lila_datasets.py +18 -19
  96. megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +54 -33
  97. megadetector/taxonomy_mapping/preview_lila_taxonomy.py +67 -67
  98. megadetector/taxonomy_mapping/retrieve_sample_image.py +16 -16
  99. megadetector/taxonomy_mapping/simple_image_download.py +8 -8
  100. megadetector/taxonomy_mapping/species_lookup.py +156 -74
  101. megadetector/taxonomy_mapping/taxonomy_csv_checker.py +14 -14
  102. megadetector/taxonomy_mapping/taxonomy_graph.py +10 -10
  103. megadetector/taxonomy_mapping/validate_lila_category_mappings.py +13 -13
  104. megadetector/utils/ct_utils.py +1049 -211
  105. megadetector/utils/directory_listing.py +21 -77
  106. megadetector/utils/gpu_test.py +22 -22
  107. megadetector/utils/md_tests.py +632 -529
  108. megadetector/utils/path_utils.py +1520 -431
  109. megadetector/utils/process_utils.py +41 -41
  110. megadetector/utils/split_locations_into_train_val.py +62 -62
  111. megadetector/utils/string_utils.py +148 -27
  112. megadetector/utils/url_utils.py +489 -176
  113. megadetector/utils/wi_utils.py +2658 -2526
  114. megadetector/utils/write_html_image_list.py +137 -137
  115. megadetector/visualization/plot_utils.py +34 -30
  116. megadetector/visualization/render_images_with_thumbnails.py +39 -74
  117. megadetector/visualization/visualization_utils.py +487 -435
  118. megadetector/visualization/visualize_db.py +232 -198
  119. megadetector/visualization/visualize_detector_output.py +82 -76
  120. {megadetector-5.0.28.dist-info → megadetector-10.0.0.dist-info}/METADATA +5 -2
  121. megadetector-10.0.0.dist-info/RECORD +139 -0
  122. {megadetector-5.0.28.dist-info → megadetector-10.0.0.dist-info}/WHEEL +1 -1
  123. megadetector/api/batch_processing/api_core/__init__.py +0 -0
  124. megadetector/api/batch_processing/api_core/batch_service/__init__.py +0 -0
  125. megadetector/api/batch_processing/api_core/batch_service/score.py +0 -439
  126. megadetector/api/batch_processing/api_core/server.py +0 -294
  127. megadetector/api/batch_processing/api_core/server_api_config.py +0 -97
  128. megadetector/api/batch_processing/api_core/server_app_config.py +0 -55
  129. megadetector/api/batch_processing/api_core/server_batch_job_manager.py +0 -220
  130. megadetector/api/batch_processing/api_core/server_job_status_table.py +0 -149
  131. megadetector/api/batch_processing/api_core/server_orchestration.py +0 -360
  132. megadetector/api/batch_processing/api_core/server_utils.py +0 -88
  133. megadetector/api/batch_processing/api_core_support/__init__.py +0 -0
  134. megadetector/api/batch_processing/api_core_support/aggregate_results_manually.py +0 -46
  135. megadetector/api/batch_processing/api_support/__init__.py +0 -0
  136. megadetector/api/batch_processing/api_support/summarize_daily_activity.py +0 -152
  137. megadetector/api/batch_processing/data_preparation/__init__.py +0 -0
  138. megadetector/api/synchronous/__init__.py +0 -0
  139. megadetector/api/synchronous/api_core/animal_detection_api/__init__.py +0 -0
  140. megadetector/api/synchronous/api_core/animal_detection_api/api_backend.py +0 -151
  141. megadetector/api/synchronous/api_core/animal_detection_api/api_frontend.py +0 -263
  142. megadetector/api/synchronous/api_core/animal_detection_api/config.py +0 -35
  143. megadetector/api/synchronous/api_core/tests/__init__.py +0 -0
  144. megadetector/api/synchronous/api_core/tests/load_test.py +0 -110
  145. megadetector/data_management/importers/add_nacti_sizes.py +0 -52
  146. megadetector/data_management/importers/add_timestamps_to_icct.py +0 -79
  147. megadetector/data_management/importers/animl_results_to_md_results.py +0 -158
  148. megadetector/data_management/importers/auckland_doc_test_to_json.py +0 -373
  149. megadetector/data_management/importers/auckland_doc_to_json.py +0 -201
  150. megadetector/data_management/importers/awc_to_json.py +0 -191
  151. megadetector/data_management/importers/bellevue_to_json.py +0 -272
  152. megadetector/data_management/importers/cacophony-thermal-importer.py +0 -793
  153. megadetector/data_management/importers/carrizo_shrubfree_2018.py +0 -269
  154. megadetector/data_management/importers/carrizo_trail_cam_2017.py +0 -289
  155. megadetector/data_management/importers/cct_field_adjustments.py +0 -58
  156. megadetector/data_management/importers/channel_islands_to_cct.py +0 -913
  157. megadetector/data_management/importers/eMammal/copy_and_unzip_emammal.py +0 -180
  158. megadetector/data_management/importers/eMammal/eMammal_helpers.py +0 -249
  159. megadetector/data_management/importers/eMammal/make_eMammal_json.py +0 -223
  160. megadetector/data_management/importers/ena24_to_json.py +0 -276
  161. megadetector/data_management/importers/filenames_to_json.py +0 -386
  162. megadetector/data_management/importers/helena_to_cct.py +0 -283
  163. megadetector/data_management/importers/idaho-camera-traps.py +0 -1407
  164. megadetector/data_management/importers/idfg_iwildcam_lila_prep.py +0 -294
  165. megadetector/data_management/importers/import_desert_lion_conservation_camera_traps.py +0 -387
  166. megadetector/data_management/importers/jb_csv_to_json.py +0 -150
  167. megadetector/data_management/importers/mcgill_to_json.py +0 -250
  168. megadetector/data_management/importers/missouri_to_json.py +0 -490
  169. megadetector/data_management/importers/nacti_fieldname_adjustments.py +0 -79
  170. megadetector/data_management/importers/noaa_seals_2019.py +0 -181
  171. megadetector/data_management/importers/osu-small-animals-to-json.py +0 -364
  172. megadetector/data_management/importers/pc_to_json.py +0 -365
  173. megadetector/data_management/importers/plot_wni_giraffes.py +0 -123
  174. megadetector/data_management/importers/prepare_zsl_imerit.py +0 -131
  175. megadetector/data_management/importers/raic_csv_to_md_results.py +0 -416
  176. megadetector/data_management/importers/rspb_to_json.py +0 -356
  177. megadetector/data_management/importers/save_the_elephants_survey_A.py +0 -320
  178. megadetector/data_management/importers/save_the_elephants_survey_B.py +0 -329
  179. megadetector/data_management/importers/snapshot_safari_importer.py +0 -758
  180. megadetector/data_management/importers/snapshot_serengeti_lila.py +0 -1067
  181. megadetector/data_management/importers/snapshotserengeti/make_full_SS_json.py +0 -150
  182. megadetector/data_management/importers/snapshotserengeti/make_per_season_SS_json.py +0 -153
  183. megadetector/data_management/importers/sulross_get_exif.py +0 -65
  184. megadetector/data_management/importers/timelapse_csv_set_to_json.py +0 -490
  185. megadetector/data_management/importers/ubc_to_json.py +0 -399
  186. megadetector/data_management/importers/umn_to_json.py +0 -507
  187. megadetector/data_management/importers/wellington_to_json.py +0 -263
  188. megadetector/data_management/importers/wi_to_json.py +0 -442
  189. megadetector/data_management/importers/zamba_results_to_md_results.py +0 -180
  190. megadetector/data_management/lila/add_locations_to_island_camera_traps.py +0 -101
  191. megadetector/data_management/lila/add_locations_to_nacti.py +0 -151
  192. megadetector/utils/azure_utils.py +0 -178
  193. megadetector/utils/sas_blob_utils.py +0 -509
  194. megadetector-5.0.28.dist-info/RECORD +0 -209
  195. /megadetector/{api/batch_processing/__init__.py → __init__.py} +0 -0
  196. {megadetector-5.0.28.dist-info → megadetector-10.0.0.dist-info}/licenses/LICENSE +0 -0
  197. {megadetector-5.0.28.dist-info → megadetector-10.0.0.dist-info}/top_level.txt +0 -0
@@ -1,373 +0,0 @@
1
- """
2
-
3
- auckland_doc_test_to_json.py
4
-
5
- Convert Auckland DOC data set to COCO camera traps format. This was
6
- for a testing data set where a .csv file was provided with class
7
- information.
8
-
9
- """
10
-
11
- #%% Constants and imports
12
-
13
- import json
14
- import os
15
- import uuid
16
- import pandas as pd
17
- import datetime
18
- import ntpath
19
- import re
20
- import numpy as np
21
-
22
- from tqdm import tqdm
23
-
24
- from megadetector.visualization import visualize_db
25
- from megadetector.data_management.databases import integrity_check_json_db
26
- from megadetector.utils.path_utils import find_images
27
-
28
- input_base_dir = r'e:\auckland-test\2_Testing'
29
-
30
- input_metadata_file = r'G:\auckland-doc\Maukahuka - Auckland Island - Cat camera data Master April 2019 - DOC-5924483.xlsx'
31
-
32
- # Filenames will be stored in the output .json relative to this base dir
33
- output_base_dir = r'g:\auckland-doc'
34
- output_json_filename = os.path.join(output_base_dir, 'auckland-doc-test.json')
35
-
36
- assert os.path.isdir(input_base_dir)
37
- os.makedirs(output_base_dir,exist_ok=True)
38
-
39
- output_encoding = 'utf-8'
40
- read_image_sizes = True
41
-
42
- info = {}
43
- info['year'] = 2020
44
- info['version'] = '1.0'
45
- info['description'] = 'Auckaland DOC Camera Traps (test)'
46
- info['contributor'] = 'Auckland DOC'
47
- info['date_created'] = str(datetime.date.today())
48
-
49
-
50
- #%% Enumerate files
51
-
52
- print('Enumerating files from {}'.format(input_base_dir))
53
- absolute_image_paths = find_images(input_base_dir, recursive=True)
54
- print('Enumerated {} images'.format(len(absolute_image_paths)))
55
-
56
- relative_image_paths = []
57
- for fn in absolute_image_paths:
58
- relative_image_paths.append(os.path.relpath(fn,input_base_dir).replace('\\','/'))
59
-
60
- relative_image_paths_set = set(relative_image_paths)
61
-
62
- assert len(relative_image_paths_set) == len(relative_image_paths)
63
-
64
-
65
- #%% Create unique identifier for each image
66
-
67
- # The ground truth doesn't have full paths in it; create unique identifiers for each image
68
- # based on the camera name and filename.
69
- #
70
- # We store file identifiers as cameraname_filename.
71
- file_identifier_to_relative_paths = {}
72
- camera_names = set()
73
-
74
- # relative_path = relative_image_paths[0]
75
- for relative_path in relative_image_paths:
76
-
77
- # Example relative paths
78
- #
79
- # Summer_Trial_2019/A1_1_42_SD114_20190210/AucklandIsland_A1_1_42_SD114_20190210_01300001.jpg
80
- # Winter_Trial_2019/Installation/10_F4/10_F4_tmp_201908210001.JPG
81
- fn = ntpath.basename(relative_path)
82
-
83
- # Find the camera name
84
- tokens = relative_path.split('/')
85
-
86
- if tokens[1] == 'Installation' or 'Rebait' in tokens[1]:
87
- camera_name = tokens[2]
88
-
89
- else:
90
- # E..g. "A1_1_42_SD114_20190210" in the above example
91
- camera_token = tokens[1]
92
- camera_name = None
93
- m = re.search('^(.+)_SD',camera_token)
94
- if m:
95
- camera_name = m.group(1)
96
- else:
97
- # For camera tokens like C1_5_D_190207
98
- m = re.search('^(.+_.+_.+)',camera_token)
99
- camera_name = m.group(1)
100
-
101
- assert camera_name
102
- camera_names.add(camera_name)
103
-
104
- file_identifier = camera_name + '_' + fn
105
- if file_identifier not in file_identifier_to_relative_paths:
106
- file_identifier_to_relative_paths[file_identifier] = [relative_path]
107
- else:
108
- file_identifier_to_relative_paths[file_identifier].append(relative_path)
109
-
110
- print('Found {} unique camera names'.format(len(camera_names)))
111
-
112
-
113
- #%% Load input data
114
-
115
- input_metadata = pd.read_excel(input_metadata_file)
116
-
117
- print('Read {} columns and {} rows from metadata file'.format(len(input_metadata.columns),
118
- len(input_metadata)))
119
-
120
- # The spreadsheet has a space after "Camera"
121
- input_metadata = input_metadata.rename(columns={'Camera ':'Camera'})
122
-
123
-
124
- #%% Assemble dictionaries
125
-
126
- image_id_to_image = {}
127
- category_name_to_category = {}
128
- annotations = []
129
-
130
- # Force the empty category to be ID 0
131
- empty_category = {}
132
- empty_category['name'] = 'empty'
133
- empty_category['id'] = 0
134
- category_name_to_category['empty'] = empty_category
135
-
136
- rows_not_found_in_folder = []
137
- rows_ambiguous = []
138
- rows_no_filename = []
139
- rows_no_annotation = []
140
-
141
- image_id_to_rows = {}
142
-
143
- next_id = 1
144
-
145
- category_names = ['cat','mouse','unknown','human','pig','sealion','penguin','dog','openadjusted']
146
-
147
- # array([nan, 'Blackbird', 'Bellbird', 'Tomtit', 'Song thrush', 'Pippit',
148
- # 'Pippet', '?', 'Dunnock', 'Song thursh', 'Kakariki', 'Tui', ' ',
149
- # 'Silvereye', 'NZ Pipit', 'Blackbird and Dunnock', 'Unknown',
150
- # 'Pipit', 'Songthrush'], dtype=object)
151
-
152
- def bird_name_to_category_name(bird_name):
153
- bird_name = bird_name.lower().strip().replace(' ','_').replace('song_thursh','song_thrush')
154
- bird_name = bird_name.replace('pippet','pipt').replace('pippit','pipit').replace('nz_pipit','pipit')
155
- if bird_name == '?' or bird_name == '' or bird_name == 'unknown':
156
- category_name = 'unknown_bird'
157
- else:
158
- category_name = bird_name
159
- return category_name
160
-
161
- bird_names = input_metadata.Bird_ID.unique()
162
- for bird_name in bird_names:
163
- if isinstance(bird_name,float):
164
- continue
165
- category_name = bird_name_to_category_name(bird_name)
166
- if category_name not in category_names:
167
- category_names.append(category_name)
168
-
169
- for category_name in category_names:
170
- cat = {}
171
- cat['name'] = category_name
172
- cat['id'] = next_id
173
- next_id = next_id +1
174
- category_name_to_category[category_name] = cat
175
-
176
- def create_annotation(image_id,category_name,count):
177
- assert isinstance(image_id,str)
178
- assert isinstance(category_name,str)
179
- assert isinstance(count,int) or isinstance(count,float)
180
- if isinstance(count,float):
181
- count = int(count)
182
- ann = {}
183
- ann['id'] = str(uuid.uuid1())
184
- ann['image_id'] = image_id
185
- category = category_name_to_category[category_name]
186
- category_id = category['id']
187
- ann['category_id'] = category_id
188
- ann['count'] = count
189
- return ann
190
-
191
- # i_row = 0; row = input_metadata.iloc[i_row]
192
- for i_row,row in tqdm(input_metadata.iterrows(),total=len(input_metadata)):
193
-
194
- # E.g.: AucklandIsland_A1_1_42_SD114_20190210_01300009.jpg
195
- filename = row['File']
196
- if isinstance(filename,float):
197
- rows_no_filename.append(i_row)
198
- continue
199
-
200
- camera_name = row['Camera']
201
- file_identifier = camera_name + '_' + filename
202
- if not file_identifier in file_identifier_to_relative_paths:
203
- rows_not_found_in_folder.append(i_row)
204
- continue
205
-
206
- relative_paths_this_file_id = file_identifier_to_relative_paths[file_identifier]
207
-
208
- if len(relative_paths_this_file_id) == 1:
209
- relative_path = relative_paths_this_file_id[0]
210
- else:
211
-
212
- # We have multiple files matching this identifier, can we uniquely resolve this
213
- # to one of those files based on the camera ID?
214
- matches = [s for s in relative_paths_this_file_id if camera_name in s]
215
- assert len(matches) > 0
216
- if len(matches) > 1:
217
- rows_ambiguous.append(i_row)
218
- continue
219
- relative_path = matches[0]
220
-
221
- assert filename.endswith('.jpg') or filename.endswith('.JPG')
222
- image_id = filename.lower().replace('.jpg','')
223
-
224
- if image_id in image_id_to_rows:
225
- image_id_to_rows[image_id].append(i_row)
226
- continue
227
-
228
- image_id_to_rows[image_id] = [i_row]
229
-
230
- im = {}
231
- im['id'] = image_id
232
- im['file_name'] = relative_path
233
- im['datetime'] = str(row['Date and time'])
234
- im['camera'] = row['Camera']
235
- im['sd_card'] = row['SD_Card']
236
- im['sd_change'] = row['SD_Change']
237
- im['comments'] = row['Comments']
238
-
239
- image_id_to_image[im['id']] = im
240
-
241
- # create_annotation(image_id,category_name,count)
242
-
243
- # 'SD_Change', 'Cat', 'Mouse', 'Bird', 'Bird_ID', 'False_trig', 'Unknown',
244
- # 'Human', 'Collared_cat', 'Cat_ID', 'Pig', 'Sea_lion', 'Open_adjusted',
245
- # 'Penguin', 'Dog', 'Comments', 'Unnamed: 22']
246
-
247
- # Each of these categories is handled a little differently...
248
-
249
- annotations_this_image = []
250
- if (not np.isnan(row['Cat'])):
251
- assert np.isnan(row['Collared_cat'] )
252
- annotations_this_image.append(create_annotation(im['id'],'cat',row['Cat']))
253
-
254
- if (not np.isnan(row['Collared_cat'])):
255
- assert np.isnan(row['Cat'] )
256
- annotations_this_image.append(create_annotation(im['id'],'cat',row['Collared_cat']))
257
-
258
- if (not np.isnan(row['Bird'])):
259
- if isinstance(row['Bird_ID'],str):
260
- category_name = bird_name_to_category_name(row['Bird_ID'])
261
- else:
262
- assert np.isnan(row['Bird_ID'])
263
- category_name = 'unknown_bird'
264
- annotations_this_image.append(create_annotation(im['id'],category_name,row['Bird']))
265
-
266
- if (not np.isnan(row['False_trig'])):
267
- annotations_this_image.append(create_annotation(im['id'],'empty',-1))
268
-
269
- # These are straightforward
270
- for s in ['Mouse','Unknown','Pig','Human','Sea_lion','Penguin','Dog','Open_adjusted']:
271
- if isinstance(row[s],float) or isinstance(row[s],int):
272
- if not np.isnan(row[s]):
273
- annotations_this_image.append(create_annotation(im['id'],s.lower().replace('_',''),row[s]))
274
- elif isinstance(row[s],str):
275
- print('File {}, label {}, value {}'.format(filename,s,row[s]))
276
- else:
277
- raise ValueError('Error handling count value {}'.format(row[s]))
278
-
279
- if len(annotations_this_image) > 1:
280
- print('Multiple annotations for filename {}'.format(filename))
281
-
282
- if len(annotations_this_image) == 0:
283
- rows_no_annotation.append(i_row)
284
-
285
- annotations.extend(annotations_this_image)
286
-
287
- # ...for each image
288
-
289
-
290
- #%% Summarize errors
291
-
292
- print('Of {} rows:\n'.format(len(input_metadata)))
293
-
294
- print('{} images not found in folder'.format(len(rows_not_found_in_folder)))
295
- print('{} images ambiguously mapped'.format(len(rows_ambiguous)))
296
- print('{} images no filename'.format(len(rows_no_filename)))
297
- print('{} images no annotation'.format(len(rows_no_annotation)))
298
- print('{} images handled successfully, {} total annotations'.format(len(image_id_to_image),len(annotations)))
299
-
300
-
301
- #%% Write output .json
302
-
303
- images = list(image_id_to_image.values())
304
- categories = list(category_name_to_category.values())
305
-
306
- data = {}
307
- data['info'] = info
308
- data['images'] = images
309
- data['annotations'] = annotations
310
- data['categories'] = categories
311
-
312
- json.dump(data, open(output_json_filename, 'w'), indent=1)
313
- print('Finished writing json to {}'.format(output_json_filename))
314
-
315
-
316
- #%% Validate .json file
317
-
318
- options = integrity_check_json_db.IntegrityCheckOptions()
319
- options.baseDir = input_base_dir
320
- options.bCheckImageSizes = False
321
- options.bCheckImageExistence = False
322
- options.bFindUnusedImages = False
323
-
324
- sortedCategories, data, _ = integrity_check_json_db.integrity_check_json_db(output_json_filename, options)
325
-
326
-
327
- #%% Preview labels
328
-
329
- viz_options = visualize_db.DbVizOptions()
330
- viz_options.num_to_visualize = 2000
331
- viz_options.trim_to_images_with_bboxes = False
332
- viz_options.add_search_links = False
333
- viz_options.sort_by_filename = False
334
- viz_options.parallelize_rendering = True
335
- viz_options.classes_to_exclude = ['empty']
336
- html_output_file, image_db = visualize_db.visualize_db(db_path=output_json_filename,
337
- output_dir=os.path.join(
338
- output_base_dir, 'preview'),
339
- image_base_dir=input_base_dir,
340
- options=viz_options)
341
- os.startfile(html_output_file)
342
-
343
-
344
- #%% Precision-recall analysis
345
-
346
- from megadetector.postprocessing.postprocess_batch_results import PostProcessingOptions
347
- from megadetector.postprocessing.postprocess_batch_results import process_batch_results
348
-
349
- api_output_file = r'g:\auckland-doc\auckland-doc_20200801\combined_api_outputs\auckland-doc_202008012020.08.01_reformatMaukahuka_Auckland_Island2_TestingSummer_Trial_2019_detections.filtered_rde_0.60_0.85_5_0.05.json'
350
- postprocessing_output_folder = r'G:\auckland-doc\auckland-doc_20200801\postprocessing'
351
- image_base = r'E:\auckland-test\2_Testing'
352
- ground_truth_json_file = output_json_filename
353
-
354
- output_base = os.path.join(postprocessing_output_folder,'pr_analysis')
355
- os.makedirs(output_base,exist_ok=True)
356
-
357
- options = PostProcessingOptions()
358
- options.unlabeled_classes.append('openadjusted')
359
- options.image_base_dir = image_base
360
- options.parallelize_rendering = True
361
- options.include_almost_detections = True
362
- options.num_images_to_sample = 2500
363
- options.confidence_threshold = 0.75
364
- options.almost_detection_confidence_threshold = 0.7
365
- options.ground_truth_json_file = ground_truth_json_file
366
- options.allow_missing_images = True
367
- options.ground_truth_filename_replacements = {}
368
- options.api_output_filename_replacements = {'2020.08.01_reformat\\Maukahuka_Auckland_Island\\2_Testing\\':''}
369
- options.api_output_file = api_output_file
370
- options.output_dir = output_base
371
- ppresults = process_batch_results(options)
372
- os.startfile(ppresults.output_html_file)
373
-
@@ -1,201 +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
-
17
- from tqdm import tqdm
18
-
19
- from megadetector.visualization import visualize_db
20
- from megadetector.data_management.databases import integrity_check_json_db
21
- from megadetector.utils.path_utils import find_images, split_path, insert_before_extension
22
-
23
- # Filenames will be stored in the output .json relative to this base dir
24
- input_base_dir = 'y:\\'
25
- output_base_dir = r'f:\auckland-doc'
26
- output_json_filename = os.path.join(output_base_dir, 'auckland-doc-Maukahuka_Auckland_Island.json')
27
-
28
- assert os.path.isdir(input_base_dir)
29
- os.makedirs(output_base_dir,exist_ok=True)
30
-
31
- output_encoding = 'utf-8'
32
- read_image_sizes = True
33
-
34
- info = {}
35
- info['year'] = 2019
36
- info['version'] = '1.0'
37
- info['description'] = 'Auckaland DOC Camera Traps'
38
- info['contributor'] = 'Auckland DOC'
39
- info['date_created'] = str(datetime.date.today())
40
-
41
-
42
- #%% Enumerate files
43
-
44
- print('Enumerating files from {}'.format(input_base_dir))
45
- image_files = find_images(input_base_dir, bRecursive=True)
46
- print('Enumerated {} images'.format(len(image_files)))
47
-
48
-
49
- #%% Assemble dictionaries
50
-
51
- images = []
52
- image_id_to_image = {}
53
- annotations = []
54
- categories = []
55
-
56
- category_name_to_category = {}
57
- category_id_to_category = {}
58
-
59
- # Force the empty category to be ID 0
60
- empty_category = {}
61
- empty_category['name'] = 'empty'
62
- empty_category['id'] = 0
63
- category_id_to_category[0] = empty_category
64
- categories.append(empty_category)
65
- next_id = 1
66
-
67
- behaviors = set()
68
-
69
- # fn = image_files[0]; print(fn)
70
- for fn in tqdm(image_files):
71
-
72
- # Typically y:\Maukahuka_Auckland_Island\1_Training\Winter_Trial_2019\cat\cat\eat\20190903_IDdY_34_E3_tmp_201908240051.JPG
73
- relative_path = os.path.relpath(fn,input_base_dir)
74
- tokens = split_path(fn)
75
- assert tokens[1] == 'Maukahuka_Auckland_Island'
76
-
77
- trainval_split = tokens[2]
78
- assert trainval_split in ['1_Training','2_Testing']
79
-
80
- # This data set has two top-level folders, "1_Training" (which has class names encoded
81
- # in paths) and "2_Testing" (which has no class information).
82
- if trainval_split == '2_Testing':
83
- category_name = 'test'
84
- else:
85
- category_name = tokens[-3]
86
- if category_name.startswith('2_'):
87
- category_name = category_name.replace('2_', '')
88
- category_name = category_name.lower().strip()
89
-
90
- if category_name not in category_name_to_category:
91
-
92
- category_id = next_id
93
- next_id += 1
94
- category = {}
95
- category['id'] = category_id
96
- category['name'] = category_name
97
- category['count'] = 0
98
- categories.append(category)
99
- category_name_to_category[category_name] = category
100
- category_id_to_category[category_id] = category
101
-
102
- else:
103
-
104
- category = category_name_to_category[category_name]
105
-
106
- category_id = category['id']
107
-
108
- category['count'] += 1
109
- behavior = None
110
- if (category_name) != 'test':
111
- behavior = fn.split('\\')[-2]
112
- behaviors.add(behavior)
113
-
114
- im = {}
115
- im['id'] = str(uuid.uuid1())
116
- im['file_name'] = relative_path
117
- image_id_to_image[im['id']] = im
118
-
119
- images.append(im)
120
-
121
- ann = {}
122
-
123
- ann['id'] = str(uuid.uuid1())
124
- ann['image_id'] = im['id']
125
- ann['category_id'] = category_id
126
- if behavior is not None:
127
- ann['behavior'] = behavior
128
- annotations.append(ann)
129
-
130
- # ...for each image
131
-
132
-
133
- #%% Write output .json
134
-
135
- data = {}
136
- data['info'] = info
137
- data['images'] = images
138
- data['annotations'] = annotations
139
- data['categories'] = categories
140
-
141
- json.dump(data, open(output_json_filename, 'w'), indent=2)
142
- print('Finished writing json to {}'.format(output_json_filename))
143
-
144
-
145
- #%% Write train/test .jsons
146
-
147
- train_images = []; test_images = []
148
- train_annotations = []; test_annotations = []
149
-
150
- for ann in tqdm(annotations):
151
- category_id = ann['category_id']
152
- image_id = ann['image_id']
153
- category_name = category_id_to_category[category_id]['name']
154
- im = image_id_to_image[image_id]
155
- if category_name == 'test':
156
- test_images.append(im)
157
- test_annotations.append(ann)
158
- else:
159
- train_images.append(im)
160
- train_annotations.append(ann)
161
-
162
- train_fn = insert_before_extension(output_json_filename,'train')
163
- test_fn = insert_before_extension(output_json_filename,'test')
164
-
165
- data['images'] = train_images
166
- data['annotations'] = train_annotations
167
- json.dump(data, open(train_fn, 'w'), indent=2)
168
-
169
- data['images'] = test_images
170
- data['annotations'] = test_annotations
171
- json.dump(data, open(test_fn, 'w'), indent=2)
172
-
173
-
174
- #%% Validate .json files
175
-
176
- options = integrity_check_json_db.IntegrityCheckOptions()
177
- options.baseDir = input_base_dir
178
- options.bCheckImageSizes = False
179
- options.bCheckImageExistence = True
180
- options.bFindUnusedImages = True
181
-
182
- sorted_categories, data, _ = integrity_check_json_db.integrity_check_json_db(output_json_filename, options)
183
- sorted_categories, data, _ = integrity_check_json_db.integrity_check_json_db(train_fn, options)
184
- sorted_categories, data, _ = integrity_check_json_db.integrity_check_json_db(test_fn, options)
185
-
186
-
187
- #%% Preview labels
188
-
189
- viz_options = visualize_db.DbVizOptions()
190
- viz_options.num_to_visualize = 2000
191
- viz_options.trim_to_images_with_bboxes = False
192
- viz_options.add_search_links = False
193
- viz_options.sort_by_filename = False
194
- viz_options.parallelize_rendering = True
195
- viz_options.classes_to_exclude = ['test']
196
- html_output_file, image_db = visualize_db.visualize_db(db_path=output_json_filename,
197
- output_dir=os.path.join(
198
- output_base_dir, 'preview'),
199
- image_base_dir=input_base_dir,
200
- options=viz_options)
201
- os.startfile(html_output_file)