megadetector 10.0.15__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.
Files changed (147) hide show
  1. megadetector/__init__.py +0 -0
  2. megadetector/api/__init__.py +0 -0
  3. megadetector/api/batch_processing/integration/digiKam/setup.py +6 -0
  4. megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +465 -0
  5. megadetector/api/batch_processing/integration/eMammal/test_scripts/config_template.py +5 -0
  6. megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +125 -0
  7. megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +55 -0
  8. megadetector/classification/__init__.py +0 -0
  9. megadetector/classification/aggregate_classifier_probs.py +108 -0
  10. megadetector/classification/analyze_failed_images.py +227 -0
  11. megadetector/classification/cache_batchapi_outputs.py +198 -0
  12. megadetector/classification/create_classification_dataset.py +626 -0
  13. megadetector/classification/crop_detections.py +516 -0
  14. megadetector/classification/csv_to_json.py +226 -0
  15. megadetector/classification/detect_and_crop.py +853 -0
  16. megadetector/classification/efficientnet/__init__.py +9 -0
  17. megadetector/classification/efficientnet/model.py +415 -0
  18. megadetector/classification/efficientnet/utils.py +608 -0
  19. megadetector/classification/evaluate_model.py +520 -0
  20. megadetector/classification/identify_mislabeled_candidates.py +152 -0
  21. megadetector/classification/json_to_azcopy_list.py +63 -0
  22. megadetector/classification/json_validator.py +696 -0
  23. megadetector/classification/map_classification_categories.py +276 -0
  24. megadetector/classification/merge_classification_detection_output.py +509 -0
  25. megadetector/classification/prepare_classification_script.py +194 -0
  26. megadetector/classification/prepare_classification_script_mc.py +228 -0
  27. megadetector/classification/run_classifier.py +287 -0
  28. megadetector/classification/save_mislabeled.py +110 -0
  29. megadetector/classification/train_classifier.py +827 -0
  30. megadetector/classification/train_classifier_tf.py +725 -0
  31. megadetector/classification/train_utils.py +323 -0
  32. megadetector/data_management/__init__.py +0 -0
  33. megadetector/data_management/animl_to_md.py +161 -0
  34. megadetector/data_management/annotations/__init__.py +0 -0
  35. megadetector/data_management/annotations/annotation_constants.py +33 -0
  36. megadetector/data_management/camtrap_dp_to_coco.py +270 -0
  37. megadetector/data_management/cct_json_utils.py +566 -0
  38. megadetector/data_management/cct_to_md.py +184 -0
  39. megadetector/data_management/cct_to_wi.py +293 -0
  40. megadetector/data_management/coco_to_labelme.py +284 -0
  41. megadetector/data_management/coco_to_yolo.py +701 -0
  42. megadetector/data_management/databases/__init__.py +0 -0
  43. megadetector/data_management/databases/add_width_and_height_to_db.py +107 -0
  44. megadetector/data_management/databases/combine_coco_camera_traps_files.py +210 -0
  45. megadetector/data_management/databases/integrity_check_json_db.py +563 -0
  46. megadetector/data_management/databases/subset_json_db.py +195 -0
  47. megadetector/data_management/generate_crops_from_cct.py +200 -0
  48. megadetector/data_management/get_image_sizes.py +164 -0
  49. megadetector/data_management/labelme_to_coco.py +559 -0
  50. megadetector/data_management/labelme_to_yolo.py +349 -0
  51. megadetector/data_management/lila/__init__.py +0 -0
  52. megadetector/data_management/lila/create_lila_blank_set.py +556 -0
  53. megadetector/data_management/lila/create_lila_test_set.py +192 -0
  54. megadetector/data_management/lila/create_links_to_md_results_files.py +106 -0
  55. megadetector/data_management/lila/download_lila_subset.py +182 -0
  56. megadetector/data_management/lila/generate_lila_per_image_labels.py +777 -0
  57. megadetector/data_management/lila/get_lila_annotation_counts.py +174 -0
  58. megadetector/data_management/lila/get_lila_image_counts.py +112 -0
  59. megadetector/data_management/lila/lila_common.py +319 -0
  60. megadetector/data_management/lila/test_lila_metadata_urls.py +164 -0
  61. megadetector/data_management/mewc_to_md.py +344 -0
  62. megadetector/data_management/ocr_tools.py +873 -0
  63. megadetector/data_management/read_exif.py +964 -0
  64. megadetector/data_management/remap_coco_categories.py +195 -0
  65. megadetector/data_management/remove_exif.py +156 -0
  66. megadetector/data_management/rename_images.py +194 -0
  67. megadetector/data_management/resize_coco_dataset.py +665 -0
  68. megadetector/data_management/speciesnet_to_md.py +41 -0
  69. megadetector/data_management/wi_download_csv_to_coco.py +247 -0
  70. megadetector/data_management/yolo_output_to_md_output.py +594 -0
  71. megadetector/data_management/yolo_to_coco.py +984 -0
  72. megadetector/data_management/zamba_to_md.py +188 -0
  73. megadetector/detection/__init__.py +0 -0
  74. megadetector/detection/change_detection.py +840 -0
  75. megadetector/detection/process_video.py +479 -0
  76. megadetector/detection/pytorch_detector.py +1451 -0
  77. megadetector/detection/run_detector.py +1267 -0
  78. megadetector/detection/run_detector_batch.py +2172 -0
  79. megadetector/detection/run_inference_with_yolov5_val.py +1314 -0
  80. megadetector/detection/run_md_and_speciesnet.py +1604 -0
  81. megadetector/detection/run_tiled_inference.py +1044 -0
  82. megadetector/detection/tf_detector.py +209 -0
  83. megadetector/detection/video_utils.py +1379 -0
  84. megadetector/postprocessing/__init__.py +0 -0
  85. megadetector/postprocessing/add_max_conf.py +72 -0
  86. megadetector/postprocessing/categorize_detections_by_size.py +166 -0
  87. megadetector/postprocessing/classification_postprocessing.py +1943 -0
  88. megadetector/postprocessing/combine_batch_outputs.py +249 -0
  89. megadetector/postprocessing/compare_batch_results.py +2110 -0
  90. megadetector/postprocessing/convert_output_format.py +403 -0
  91. megadetector/postprocessing/create_crop_folder.py +629 -0
  92. megadetector/postprocessing/detector_calibration.py +570 -0
  93. megadetector/postprocessing/generate_csv_report.py +522 -0
  94. megadetector/postprocessing/load_api_results.py +223 -0
  95. megadetector/postprocessing/md_to_coco.py +428 -0
  96. megadetector/postprocessing/md_to_labelme.py +351 -0
  97. megadetector/postprocessing/md_to_wi.py +41 -0
  98. megadetector/postprocessing/merge_detections.py +392 -0
  99. megadetector/postprocessing/postprocess_batch_results.py +2140 -0
  100. megadetector/postprocessing/remap_detection_categories.py +226 -0
  101. megadetector/postprocessing/render_detection_confusion_matrix.py +677 -0
  102. megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +206 -0
  103. megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +82 -0
  104. megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +1665 -0
  105. megadetector/postprocessing/separate_detections_into_folders.py +795 -0
  106. megadetector/postprocessing/subset_json_detector_output.py +964 -0
  107. megadetector/postprocessing/top_folders_to_bottom.py +238 -0
  108. megadetector/postprocessing/validate_batch_results.py +332 -0
  109. megadetector/taxonomy_mapping/__init__.py +0 -0
  110. megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +491 -0
  111. megadetector/taxonomy_mapping/map_new_lila_datasets.py +211 -0
  112. megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +165 -0
  113. megadetector/taxonomy_mapping/preview_lila_taxonomy.py +543 -0
  114. megadetector/taxonomy_mapping/retrieve_sample_image.py +71 -0
  115. megadetector/taxonomy_mapping/simple_image_download.py +231 -0
  116. megadetector/taxonomy_mapping/species_lookup.py +1008 -0
  117. megadetector/taxonomy_mapping/taxonomy_csv_checker.py +159 -0
  118. megadetector/taxonomy_mapping/taxonomy_graph.py +346 -0
  119. megadetector/taxonomy_mapping/validate_lila_category_mappings.py +83 -0
  120. megadetector/tests/__init__.py +0 -0
  121. megadetector/tests/test_nms_synthetic.py +335 -0
  122. megadetector/utils/__init__.py +0 -0
  123. megadetector/utils/ct_utils.py +1857 -0
  124. megadetector/utils/directory_listing.py +199 -0
  125. megadetector/utils/extract_frames_from_video.py +307 -0
  126. megadetector/utils/gpu_test.py +125 -0
  127. megadetector/utils/md_tests.py +2072 -0
  128. megadetector/utils/path_utils.py +2872 -0
  129. megadetector/utils/process_utils.py +172 -0
  130. megadetector/utils/split_locations_into_train_val.py +237 -0
  131. megadetector/utils/string_utils.py +234 -0
  132. megadetector/utils/url_utils.py +825 -0
  133. megadetector/utils/wi_platform_utils.py +968 -0
  134. megadetector/utils/wi_taxonomy_utils.py +1766 -0
  135. megadetector/utils/write_html_image_list.py +239 -0
  136. megadetector/visualization/__init__.py +0 -0
  137. megadetector/visualization/plot_utils.py +309 -0
  138. megadetector/visualization/render_images_with_thumbnails.py +243 -0
  139. megadetector/visualization/visualization_utils.py +1973 -0
  140. megadetector/visualization/visualize_db.py +630 -0
  141. megadetector/visualization/visualize_detector_output.py +498 -0
  142. megadetector/visualization/visualize_video_output.py +705 -0
  143. megadetector-10.0.15.dist-info/METADATA +115 -0
  144. megadetector-10.0.15.dist-info/RECORD +147 -0
  145. megadetector-10.0.15.dist-info/WHEEL +5 -0
  146. megadetector-10.0.15.dist-info/licenses/LICENSE +19 -0
  147. megadetector-10.0.15.dist-info/top_level.txt +1 -0
@@ -0,0 +1,184 @@
1
+ """
2
+
3
+ cct_to_md.py
4
+
5
+ "Converts" a COCO Camera Traps file to a MD results file. Currently ignores
6
+ non-bounding-box annotations, and gives all annotations a confidence of 1.0.
7
+
8
+ The only reason to do this is if you are going to add information to an existing
9
+ CCT-formatted dataset, and you want to do that in Timelapse.
10
+
11
+ Currently assumes that width and height are present in the input data, does not
12
+ read them from images.
13
+
14
+ """
15
+
16
+ #%% Constants and imports
17
+
18
+ import os
19
+ import json
20
+
21
+ from collections import defaultdict
22
+ from tqdm import tqdm
23
+
24
+
25
+ #%% Functions
26
+
27
+ def cct_to_md(input_filename,output_filename=None):
28
+ """
29
+ "Converts" a COCO Camera Traps file to a MD results file. Currently ignores
30
+ non-bounding-box annotations. If the semi-standard "score" field is present in
31
+ an annotation, or the totally non-standard "conf" field is present, it will be
32
+ transferred to the output, otherwise a confidence value of 1.0 is assumed for
33
+ all annotations.
34
+
35
+ The main reason to run this script the scenario where you are going to add information
36
+ to an existing CCT-formatted dataset, and you want to do that in Timelapse.
37
+
38
+ Currently assumes that width and height are present in the input data, does not
39
+ read them from images.
40
+
41
+ Args:
42
+ input_filename (str): the COCO Camera Traps .json file to read
43
+ output_filename (str, optional): the .json file to write in MD results format
44
+
45
+ Returns:
46
+ dict: MD-formatted results, identical to the content of [output_filename] if
47
+ [output_filename] is not None
48
+ """
49
+
50
+ ## Validate input
51
+
52
+ assert os.path.isfile(input_filename)
53
+
54
+ if (output_filename is None):
55
+
56
+ tokens = os.path.splitext(input_filename)
57
+ assert len(tokens) == 2
58
+ output_filename = tokens[0] + '_md-format' + tokens[1]
59
+
60
+
61
+ ## Read input
62
+
63
+ with open(input_filename,'r') as f:
64
+ d = json.load(f)
65
+
66
+ for s in ['annotations','images','categories']:
67
+ assert s in d.keys(), 'Cannot find key {} in input file, is this a CCT file?'.format(s)
68
+
69
+
70
+ ## Prepare metadata
71
+
72
+ image_id_to_annotations = defaultdict(list)
73
+
74
+ # ann = d['annotations'][0]
75
+ for ann in tqdm(d['annotations']):
76
+ image_id_to_annotations[ann['image_id']].append(ann)
77
+
78
+ category_id_to_name = {}
79
+ for cat in d['categories']:
80
+ category_id_to_name[str(cat['id'])] = cat['name']
81
+
82
+ results = {}
83
+
84
+ info = {}
85
+ info['format_version'] = '1.4'
86
+ info['detector'] = 'cct_to_md'
87
+ results['info'] = info
88
+ results['detection_categories'] = category_id_to_name
89
+
90
+
91
+ ## Process images
92
+
93
+ images_out = []
94
+
95
+ # im = d['images'][0]
96
+ for im in tqdm(d['images']):
97
+
98
+ im_out = {}
99
+ im_out['file'] = im['file_name']
100
+ im_out['location'] = im['location']
101
+ im_out['id'] = im['id']
102
+
103
+ image_h = im['height']
104
+ image_w = im['width']
105
+
106
+ detections = []
107
+
108
+ annotations_this_image = image_id_to_annotations[im['id']]
109
+
110
+ # This field is no longer included in MD output files by default
111
+ # max_detection_conf = 0
112
+
113
+ for ann in annotations_this_image:
114
+
115
+ if 'bbox' in ann:
116
+
117
+ det = {}
118
+ det['category'] = str(ann['category_id'])
119
+ if 'score' in ann:
120
+ det['conf'] = ann['score']
121
+ elif 'conf' in ann:
122
+ det['conf'] = ann['conf']
123
+ else:
124
+ det['conf'] = 1.0
125
+
126
+ # MegaDetector: [x,y,width,height] (normalized, origin upper-left)
127
+ # CCT: [x,y,width,height] (absolute, origin upper-left)
128
+ bbox_in = ann['bbox']
129
+ bbox_out = [bbox_in[0]/image_w,bbox_in[1]/image_h,
130
+ bbox_in[2]/image_w,bbox_in[3]/image_h]
131
+ det['bbox'] = bbox_out
132
+ detections.append(det)
133
+
134
+ # ...if there's a bounding box
135
+
136
+ # ...for each annotation
137
+
138
+ im_out['detections'] = detections
139
+
140
+ # This field is no longer included in MD output files by default
141
+ # im_out['max_detection_conf'] = max_detection_conf
142
+
143
+ images_out.append(im_out)
144
+
145
+ # ...for each image
146
+
147
+
148
+ ## Write output
149
+
150
+ results['images'] = images_out
151
+
152
+ if output_filename is not None:
153
+ with open(output_filename,'w') as f:
154
+ json.dump(results, f, indent=1)
155
+
156
+ return results
157
+
158
+ # ...cct_to_md()
159
+
160
+
161
+ #%% Interactive driver
162
+
163
+ if False:
164
+
165
+ pass
166
+
167
+ #%%
168
+
169
+ input_filename = r"G:\temp\noaa_estuary_fish.json"
170
+ output_filename = None
171
+ output_filename = cct_to_md(input_filename,output_filename)
172
+
173
+ #%%
174
+
175
+ from megadetector.visualization import visualize_detector_output
176
+
177
+ visualize_detector_output.visualize_detector_output(
178
+ detector_output_path=output_filename,
179
+ out_dir=r'g:\temp\fish_output',
180
+ images_dir=r'g:\temp\noaa_estuary_fish-images\JPEGImages',
181
+ output_image_width=-1,
182
+ sample=100,
183
+ render_detections_only=True)
184
+
@@ -0,0 +1,293 @@
1
+ """
2
+
3
+ cct_to_wi.py
4
+
5
+ Converts COCO Camera Traps .json files to the Wildlife Insights
6
+ batch upload format.
7
+
8
+ **This is very much just a demo script; all the relevant constants are hard-coded
9
+ at the top of main().**
10
+
11
+ But given that caveat, it works. You need to set up all the paths in the "paths" cell
12
+ at the top of main().
13
+
14
+ Also see:
15
+
16
+ * https://github.com/ConservationInternational/Wildlife-Insights----Data-Migration
17
+ * https://data.naturalsciences.org/wildlife-insights/taxonomy/search
18
+
19
+ """
20
+
21
+ #%% Imports
22
+
23
+ import os
24
+ import json
25
+ import pandas as pd
26
+ from collections import defaultdict
27
+
28
+
29
+ #%% Main wrapper
30
+
31
+ def main(): # noqa
32
+ """
33
+ Converts COCO Camera Traps .json files to the Wildlife Insights
34
+ batch upload format; to use this, you need to modify all the paths in the "Paths"
35
+ cell.
36
+ """
37
+
38
+ #%% Paths
39
+
40
+ # A COCO camera traps file with information about this dataset
41
+ input_file = r'c:\temp\camera_trap_images_no_people\bellevue_camera_traps.2020-12-26.json'
42
+
43
+ # A .json dictionary mapping common names in this dataset to dictionaries with the
44
+ # WI taxonomy fields: common_name, wi_taxon_id, class, order, family, genus, species
45
+ taxonomy_file = r'c:\temp\camera_trap_images_no_people\bellevue_camera_traps_to_wi.json'
46
+
47
+ # The folder where the .csv template files live
48
+ templates_dir = r'c:\temp\wi_batch_upload_templates'
49
+
50
+ # The folder to which you want to write WI-formatted .csv files
51
+ output_base = r'c:\temp\wi_output'
52
+
53
+
54
+ #%% Path validation
55
+
56
+ assert os.path.isfile(input_file)
57
+ assert os.path.isfile(taxonomy_file)
58
+ assert os.path.isdir(templates_dir)
59
+ os.makedirs(output_base,exist_ok = True)
60
+
61
+
62
+ #%% Constants
63
+
64
+ projects_file_name = 'Template Wildlife Insights Batch Upload - Projectv1.0.csv'
65
+ deployments_file_name = 'Template Wildlife Insights Batch Upload - Deploymentv1.0.csv'
66
+ images_file_name = 'Template Wildlife Insights Batch Upload - Imagev1.0.csv'
67
+ cameras_file_name = 'Template Wildlife Insights Batch Upload - Camerav1.0.csv'
68
+
69
+ assert all([os.path.isfile(os.path.join(templates_dir,fn)) for fn in \
70
+ [projects_file_name,deployments_file_name,images_file_name,cameras_file_name]])
71
+
72
+
73
+ #%% Project information
74
+
75
+ project_info = {}
76
+ project_info['project_name'] = 'Bellevue Camera Traps'
77
+ project_info['project_id'] = 'bct_001'
78
+ project_info['project_short_name'] = 'BCT'
79
+ project_info['project_objectives'] = 'none'
80
+ project_info['project_species'] = 'Multiple'
81
+ project_info['project_species_individual'] = ''
82
+ project_info['project_sensor_layout'] = 'Convenience'
83
+ project_info['project_sensor_layout_targeted_type'] = ''
84
+ project_info['project_bait_use'] = 'No'
85
+ project_info['project_bait_type'] = 'None'
86
+ project_info['project_stratification'] = 'No'
87
+ project_info['project_stratification_type'] = ''
88
+ project_info['project_sensor_method'] = 'Sensor Detection'
89
+ project_info['project_individual_animals'] = 'No'
90
+ project_info['project_admin'] = 'Dan Morris'
91
+ project_info['project_admin_email'] = 'cameratraps@lila.science'
92
+ project_info['country_code'] = 'USA'
93
+ project_info['embargo'] = str(0)
94
+ project_info['initiative_id'] = ''
95
+ project_info['metadata_license'] = 'CC0'
96
+ project_info['image_license'] = 'CC0'
97
+
98
+ project_info['project_blank_images'] = 'No'
99
+ project_info['project_sensor_cluster'] = 'No'
100
+
101
+ camera_info = {}
102
+ camera_info['project_id'] = project_info['project_id']
103
+ camera_info['camera_id'] = '0000'
104
+ camera_info['make'] = ''
105
+ camera_info['model'] = ''
106
+ camera_info['serial_number'] = ''
107
+ camera_info['year_purchased'] = ''
108
+
109
+ deployment_info = {}
110
+
111
+ deployment_info['project_id'] = project_info['project_id']
112
+ deployment_info['deployment_id'] = 'test_deployment'
113
+ deployment_info['subproject_name'] = 'test_subproject'
114
+ deployment_info['subproject_design'] = ''
115
+ deployment_info['placename'] = 'yard'
116
+ deployment_info['longitude'] = '47.6101'
117
+ deployment_info['latitude'] = '-122.2015'
118
+ deployment_info['start_date'] = '2016-01-01 00:00:00'
119
+ deployment_info['end_date'] = '2026-01-01 00:00:00'
120
+ deployment_info['event_name'] = ''
121
+ deployment_info['event_description'] = ''
122
+ deployment_info['event_type'] = ''
123
+ deployment_info['bait_type'] = ''
124
+ deployment_info['bait_description'] = ''
125
+ deployment_info['feature_type'] = 'None'
126
+ deployment_info['feature_type_methodology'] = ''
127
+ deployment_info['camera_id'] = camera_info['camera_id']
128
+ deployment_info['quiet_period'] = str(60)
129
+ deployment_info['camera_functioning'] = 'Camera Functioning'
130
+ deployment_info['sensor_height'] = 'Chest height'
131
+ deployment_info['height_other'] = ''
132
+ deployment_info['sensor_orientation'] = 'Parallel'
133
+ deployment_info['orientation_other'] = ''
134
+ deployment_info['recorded_by'] = 'Dan Morris'
135
+
136
+ image_info = {}
137
+ image_info['identified_by'] = 'Dan Morris'
138
+
139
+
140
+ #%% Read templates
141
+
142
+ def parse_fields(templates_dir,file_name):
143
+
144
+ with open(os.path.join(templates_dir,file_name),'r') as f:
145
+ lines = f.readlines()
146
+ lines = [s.strip() for s in lines if len(s.strip().replace(',','')) > 0]
147
+ assert len(lines) == 1, 'Error processing template {}'.format(file_name)
148
+ fields = lines[0].split(',')
149
+ print('Parsed {} columns from {}'.format(len(fields),file_name))
150
+ return fields
151
+
152
+ projects_fields = parse_fields(templates_dir,projects_file_name)
153
+ deployments_fields = parse_fields(templates_dir,deployments_file_name)
154
+ images_fields = parse_fields(templates_dir,images_file_name)
155
+ cameras_fields = parse_fields(templates_dir,cameras_file_name)
156
+
157
+
158
+ #%% Compare dictionary to template lists
159
+
160
+ def compare_info_to_template(info,template_fields,name):
161
+
162
+ for s in info.keys():
163
+ assert s in template_fields,'Field {} not specified in {}_fields'.format(s,name)
164
+ for s in template_fields:
165
+ assert s in info.keys(),'Field {} not specified in {}_info'.format(s,name)
166
+
167
+
168
+ def write_table(file_name,info,template_fields):
169
+
170
+ assert len(info) == len(template_fields)
171
+
172
+ project_output_file = os.path.join(output_base,file_name)
173
+ with open(project_output_file,'w') as f:
174
+
175
+ # Write the header
176
+ for i_field,s in enumerate(template_fields):
177
+ f.write(s)
178
+ if i_field != len(template_fields)-1:
179
+ f.write(',')
180
+ f.write('\n')
181
+
182
+ # Write values
183
+ for i_field,s in enumerate(template_fields):
184
+ f.write(info[s])
185
+ if i_field != len(template_fields)-1:
186
+ f.write(',')
187
+ f.write('\n')
188
+
189
+
190
+ #%% Project file
191
+
192
+ compare_info_to_template(project_info,projects_fields,'project')
193
+ write_table(projects_file_name,project_info,projects_fields)
194
+
195
+
196
+ #%% Camera file
197
+
198
+ compare_info_to_template(camera_info,cameras_fields,'camera')
199
+ write_table(cameras_file_name,camera_info,cameras_fields)
200
+
201
+
202
+ #%% Deployment file
203
+
204
+ compare_info_to_template(deployment_info,deployments_fields,'deployment')
205
+ write_table(deployments_file_name,deployment_info,deployments_fields)
206
+
207
+
208
+ #%% Images file
209
+
210
+ # Read .json file with image information
211
+ with open(input_file,'r') as f:
212
+ input_data = json.load(f)
213
+
214
+ # Read taxonomy dictionary
215
+ with open(taxonomy_file,'r') as f:
216
+ taxonomy_mapping = json.load(f)
217
+
218
+ url_base = taxonomy_mapping['url_base']
219
+ taxonomy_mapping = taxonomy_mapping['taxonomy']
220
+
221
+ # Populate output information
222
+ # df = pd.DataFrame(columns = images_fields)
223
+
224
+ category_id_to_name = {cat['id']:cat['name'] for cat in input_data['categories']}
225
+
226
+ image_id_to_annotations = defaultdict(list)
227
+
228
+ annotations = input_data['annotations']
229
+
230
+ # annotation = annotations[0]
231
+ for annotation in annotations:
232
+ image_id_to_annotations[annotation['image_id']].append(
233
+ category_id_to_name[annotation['category_id']])
234
+
235
+ rows = []
236
+
237
+ # im = input_data['images'][0]
238
+ for im in input_data['images']:
239
+
240
+ row = {}
241
+
242
+ url = url_base + im['file_name'].replace('\\','/')
243
+ row['project_id'] = project_info['project_id']
244
+ row['deployment_id'] = deployment_info['deployment_id']
245
+ row['image_id'] = im['id']
246
+ row['location'] = url
247
+ row['identified_by'] = image_info['identified_by']
248
+
249
+ category_names = image_id_to_annotations[im['id']]
250
+ assert len(category_names) == 1
251
+ category_name = category_names[0]
252
+
253
+ taxon_info = taxonomy_mapping[category_name]
254
+
255
+ assert len(taxon_info.keys()) == 7
256
+
257
+ for s in taxon_info.keys():
258
+ row[s] = taxon_info[s]
259
+
260
+ # We don't have counts, but we can differentiate between zero and 1
261
+ if category_name == 'empty':
262
+ row['number_of_objects'] = 0
263
+ else:
264
+ row['number_of_objects'] = 1
265
+
266
+ assert isinstance(im['datetime'],str)
267
+
268
+ row['uncertainty'] = None
269
+ row['timestamp'] = im['datetime']
270
+ row['highlighted'] = 0
271
+ row['age'] = None
272
+ row['sex'] = None
273
+ row['animal_recognizable'] = 'No'
274
+ row['individual_id'] = None
275
+ row['individual_animal_notes'] = None
276
+ row['markings'] = None
277
+
278
+ assert len(row) == len(images_fields)
279
+ rows.append(row)
280
+
281
+ # ...for each image
282
+
283
+ df = pd.DataFrame(rows)
284
+
285
+ df.to_csv(os.path.join(output_base,images_file_name),index=False)
286
+
287
+ # ...main()
288
+
289
+
290
+ #%% Command-line driver
291
+
292
+ if __name__ == '__main__':
293
+ main()