megadetector 5.0.10__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.
- {megadetector-5.0.10.dist-info → megadetector-5.0.11.dist-info}/LICENSE +0 -0
- {megadetector-5.0.10.dist-info → megadetector-5.0.11.dist-info}/METADATA +12 -11
- megadetector-5.0.11.dist-info/RECORD +5 -0
- megadetector-5.0.11.dist-info/top_level.txt +1 -0
- api/__init__.py +0 -0
- api/batch_processing/__init__.py +0 -0
- api/batch_processing/api_core/__init__.py +0 -0
- api/batch_processing/api_core/batch_service/__init__.py +0 -0
- api/batch_processing/api_core/batch_service/score.py +0 -439
- api/batch_processing/api_core/server.py +0 -294
- api/batch_processing/api_core/server_api_config.py +0 -98
- api/batch_processing/api_core/server_app_config.py +0 -55
- api/batch_processing/api_core/server_batch_job_manager.py +0 -220
- api/batch_processing/api_core/server_job_status_table.py +0 -152
- api/batch_processing/api_core/server_orchestration.py +0 -360
- api/batch_processing/api_core/server_utils.py +0 -92
- api/batch_processing/api_core_support/__init__.py +0 -0
- api/batch_processing/api_core_support/aggregate_results_manually.py +0 -46
- api/batch_processing/api_support/__init__.py +0 -0
- api/batch_processing/api_support/summarize_daily_activity.py +0 -152
- api/batch_processing/data_preparation/__init__.py +0 -0
- api/batch_processing/data_preparation/manage_local_batch.py +0 -2391
- api/batch_processing/data_preparation/manage_video_batch.py +0 -327
- api/batch_processing/integration/digiKam/setup.py +0 -6
- api/batch_processing/integration/digiKam/xmp_integration.py +0 -465
- api/batch_processing/integration/eMammal/test_scripts/config_template.py +0 -5
- api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +0 -126
- api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +0 -55
- api/batch_processing/postprocessing/__init__.py +0 -0
- api/batch_processing/postprocessing/add_max_conf.py +0 -64
- api/batch_processing/postprocessing/categorize_detections_by_size.py +0 -163
- api/batch_processing/postprocessing/combine_api_outputs.py +0 -249
- api/batch_processing/postprocessing/compare_batch_results.py +0 -958
- api/batch_processing/postprocessing/convert_output_format.py +0 -397
- api/batch_processing/postprocessing/load_api_results.py +0 -195
- api/batch_processing/postprocessing/md_to_coco.py +0 -310
- api/batch_processing/postprocessing/md_to_labelme.py +0 -330
- api/batch_processing/postprocessing/merge_detections.py +0 -401
- api/batch_processing/postprocessing/postprocess_batch_results.py +0 -1904
- api/batch_processing/postprocessing/remap_detection_categories.py +0 -170
- api/batch_processing/postprocessing/render_detection_confusion_matrix.py +0 -661
- api/batch_processing/postprocessing/repeat_detection_elimination/find_repeat_detections.py +0 -211
- api/batch_processing/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +0 -82
- api/batch_processing/postprocessing/repeat_detection_elimination/repeat_detections_core.py +0 -1631
- api/batch_processing/postprocessing/separate_detections_into_folders.py +0 -731
- api/batch_processing/postprocessing/subset_json_detector_output.py +0 -696
- api/batch_processing/postprocessing/top_folders_to_bottom.py +0 -223
- api/synchronous/__init__.py +0 -0
- api/synchronous/api_core/animal_detection_api/__init__.py +0 -0
- api/synchronous/api_core/animal_detection_api/api_backend.py +0 -152
- api/synchronous/api_core/animal_detection_api/api_frontend.py +0 -266
- api/synchronous/api_core/animal_detection_api/config.py +0 -35
- api/synchronous/api_core/animal_detection_api/data_management/annotations/annotation_constants.py +0 -47
- api/synchronous/api_core/animal_detection_api/detection/detector_training/copy_checkpoints.py +0 -43
- api/synchronous/api_core/animal_detection_api/detection/detector_training/model_main_tf2.py +0 -114
- api/synchronous/api_core/animal_detection_api/detection/process_video.py +0 -543
- api/synchronous/api_core/animal_detection_api/detection/pytorch_detector.py +0 -304
- api/synchronous/api_core/animal_detection_api/detection/run_detector.py +0 -627
- api/synchronous/api_core/animal_detection_api/detection/run_detector_batch.py +0 -1029
- api/synchronous/api_core/animal_detection_api/detection/run_inference_with_yolov5_val.py +0 -581
- api/synchronous/api_core/animal_detection_api/detection/run_tiled_inference.py +0 -754
- api/synchronous/api_core/animal_detection_api/detection/tf_detector.py +0 -165
- api/synchronous/api_core/animal_detection_api/detection/video_utils.py +0 -495
- api/synchronous/api_core/animal_detection_api/md_utils/azure_utils.py +0 -174
- api/synchronous/api_core/animal_detection_api/md_utils/ct_utils.py +0 -262
- api/synchronous/api_core/animal_detection_api/md_utils/directory_listing.py +0 -251
- api/synchronous/api_core/animal_detection_api/md_utils/matlab_porting_tools.py +0 -97
- api/synchronous/api_core/animal_detection_api/md_utils/path_utils.py +0 -416
- api/synchronous/api_core/animal_detection_api/md_utils/process_utils.py +0 -110
- api/synchronous/api_core/animal_detection_api/md_utils/sas_blob_utils.py +0 -509
- api/synchronous/api_core/animal_detection_api/md_utils/string_utils.py +0 -59
- api/synchronous/api_core/animal_detection_api/md_utils/url_utils.py +0 -144
- api/synchronous/api_core/animal_detection_api/md_utils/write_html_image_list.py +0 -226
- api/synchronous/api_core/animal_detection_api/md_visualization/visualization_utils.py +0 -841
- api/synchronous/api_core/tests/__init__.py +0 -0
- api/synchronous/api_core/tests/load_test.py +0 -110
- classification/__init__.py +0 -0
- classification/aggregate_classifier_probs.py +0 -108
- classification/analyze_failed_images.py +0 -227
- classification/cache_batchapi_outputs.py +0 -198
- classification/create_classification_dataset.py +0 -627
- classification/crop_detections.py +0 -516
- classification/csv_to_json.py +0 -226
- classification/detect_and_crop.py +0 -855
- classification/efficientnet/__init__.py +0 -9
- classification/efficientnet/model.py +0 -415
- classification/efficientnet/utils.py +0 -610
- classification/evaluate_model.py +0 -520
- classification/identify_mislabeled_candidates.py +0 -152
- classification/json_to_azcopy_list.py +0 -63
- classification/json_validator.py +0 -695
- classification/map_classification_categories.py +0 -276
- classification/merge_classification_detection_output.py +0 -506
- classification/prepare_classification_script.py +0 -194
- classification/prepare_classification_script_mc.py +0 -228
- classification/run_classifier.py +0 -286
- classification/save_mislabeled.py +0 -110
- classification/train_classifier.py +0 -825
- classification/train_classifier_tf.py +0 -724
- classification/train_utils.py +0 -322
- data_management/__init__.py +0 -0
- data_management/annotations/__init__.py +0 -0
- data_management/annotations/annotation_constants.py +0 -34
- data_management/camtrap_dp_to_coco.py +0 -238
- data_management/cct_json_utils.py +0 -395
- data_management/cct_to_md.py +0 -176
- data_management/cct_to_wi.py +0 -289
- data_management/coco_to_labelme.py +0 -272
- data_management/coco_to_yolo.py +0 -662
- data_management/databases/__init__.py +0 -0
- data_management/databases/add_width_and_height_to_db.py +0 -33
- data_management/databases/combine_coco_camera_traps_files.py +0 -206
- data_management/databases/integrity_check_json_db.py +0 -477
- data_management/databases/subset_json_db.py +0 -115
- data_management/generate_crops_from_cct.py +0 -149
- data_management/get_image_sizes.py +0 -188
- data_management/importers/add_nacti_sizes.py +0 -52
- data_management/importers/add_timestamps_to_icct.py +0 -79
- data_management/importers/animl_results_to_md_results.py +0 -158
- data_management/importers/auckland_doc_test_to_json.py +0 -372
- data_management/importers/auckland_doc_to_json.py +0 -200
- data_management/importers/awc_to_json.py +0 -189
- data_management/importers/bellevue_to_json.py +0 -273
- data_management/importers/cacophony-thermal-importer.py +0 -796
- data_management/importers/carrizo_shrubfree_2018.py +0 -268
- data_management/importers/carrizo_trail_cam_2017.py +0 -287
- data_management/importers/cct_field_adjustments.py +0 -57
- data_management/importers/channel_islands_to_cct.py +0 -913
- data_management/importers/eMammal/copy_and_unzip_emammal.py +0 -180
- data_management/importers/eMammal/eMammal_helpers.py +0 -249
- data_management/importers/eMammal/make_eMammal_json.py +0 -223
- data_management/importers/ena24_to_json.py +0 -275
- data_management/importers/filenames_to_json.py +0 -385
- data_management/importers/helena_to_cct.py +0 -282
- data_management/importers/idaho-camera-traps.py +0 -1407
- data_management/importers/idfg_iwildcam_lila_prep.py +0 -294
- data_management/importers/jb_csv_to_json.py +0 -150
- data_management/importers/mcgill_to_json.py +0 -250
- data_management/importers/missouri_to_json.py +0 -489
- data_management/importers/nacti_fieldname_adjustments.py +0 -79
- data_management/importers/noaa_seals_2019.py +0 -181
- data_management/importers/pc_to_json.py +0 -365
- data_management/importers/plot_wni_giraffes.py +0 -123
- data_management/importers/prepare-noaa-fish-data-for-lila.py +0 -359
- data_management/importers/prepare_zsl_imerit.py +0 -131
- data_management/importers/rspb_to_json.py +0 -356
- data_management/importers/save_the_elephants_survey_A.py +0 -320
- data_management/importers/save_the_elephants_survey_B.py +0 -332
- data_management/importers/snapshot_safari_importer.py +0 -758
- data_management/importers/snapshot_safari_importer_reprise.py +0 -665
- data_management/importers/snapshot_serengeti_lila.py +0 -1067
- data_management/importers/snapshotserengeti/make_full_SS_json.py +0 -150
- data_management/importers/snapshotserengeti/make_per_season_SS_json.py +0 -153
- data_management/importers/sulross_get_exif.py +0 -65
- data_management/importers/timelapse_csv_set_to_json.py +0 -490
- data_management/importers/ubc_to_json.py +0 -399
- data_management/importers/umn_to_json.py +0 -507
- data_management/importers/wellington_to_json.py +0 -263
- data_management/importers/wi_to_json.py +0 -441
- data_management/importers/zamba_results_to_md_results.py +0 -181
- data_management/labelme_to_coco.py +0 -548
- data_management/labelme_to_yolo.py +0 -272
- data_management/lila/__init__.py +0 -0
- data_management/lila/add_locations_to_island_camera_traps.py +0 -97
- data_management/lila/add_locations_to_nacti.py +0 -147
- data_management/lila/create_lila_blank_set.py +0 -557
- data_management/lila/create_lila_test_set.py +0 -151
- data_management/lila/create_links_to_md_results_files.py +0 -106
- data_management/lila/download_lila_subset.py +0 -177
- data_management/lila/generate_lila_per_image_labels.py +0 -515
- data_management/lila/get_lila_annotation_counts.py +0 -170
- data_management/lila/get_lila_image_counts.py +0 -111
- data_management/lila/lila_common.py +0 -300
- data_management/lila/test_lila_metadata_urls.py +0 -132
- data_management/ocr_tools.py +0 -874
- data_management/read_exif.py +0 -681
- data_management/remap_coco_categories.py +0 -84
- data_management/remove_exif.py +0 -66
- data_management/resize_coco_dataset.py +0 -189
- data_management/wi_download_csv_to_coco.py +0 -246
- data_management/yolo_output_to_md_output.py +0 -441
- data_management/yolo_to_coco.py +0 -676
- detection/__init__.py +0 -0
- detection/detector_training/__init__.py +0 -0
- detection/detector_training/model_main_tf2.py +0 -114
- detection/process_video.py +0 -703
- detection/pytorch_detector.py +0 -337
- detection/run_detector.py +0 -779
- detection/run_detector_batch.py +0 -1219
- detection/run_inference_with_yolov5_val.py +0 -917
- detection/run_tiled_inference.py +0 -935
- detection/tf_detector.py +0 -188
- detection/video_utils.py +0 -606
- docs/source/conf.py +0 -43
- md_utils/__init__.py +0 -0
- md_utils/azure_utils.py +0 -174
- md_utils/ct_utils.py +0 -612
- md_utils/directory_listing.py +0 -246
- md_utils/md_tests.py +0 -968
- md_utils/path_utils.py +0 -1044
- md_utils/process_utils.py +0 -157
- md_utils/sas_blob_utils.py +0 -509
- md_utils/split_locations_into_train_val.py +0 -228
- md_utils/string_utils.py +0 -92
- md_utils/url_utils.py +0 -323
- md_utils/write_html_image_list.py +0 -225
- md_visualization/__init__.py +0 -0
- md_visualization/plot_utils.py +0 -293
- md_visualization/render_images_with_thumbnails.py +0 -275
- md_visualization/visualization_utils.py +0 -1537
- md_visualization/visualize_db.py +0 -551
- md_visualization/visualize_detector_output.py +0 -406
- megadetector-5.0.10.dist-info/RECORD +0 -224
- megadetector-5.0.10.dist-info/top_level.txt +0 -8
- taxonomy_mapping/__init__.py +0 -0
- taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +0 -491
- taxonomy_mapping/map_new_lila_datasets.py +0 -154
- taxonomy_mapping/prepare_lila_taxonomy_release.py +0 -142
- taxonomy_mapping/preview_lila_taxonomy.py +0 -591
- taxonomy_mapping/retrieve_sample_image.py +0 -71
- taxonomy_mapping/simple_image_download.py +0 -218
- taxonomy_mapping/species_lookup.py +0 -834
- taxonomy_mapping/taxonomy_csv_checker.py +0 -159
- taxonomy_mapping/taxonomy_graph.py +0 -346
- taxonomy_mapping/validate_lila_category_mappings.py +0 -83
- {megadetector-5.0.10.dist-info → megadetector-5.0.11.dist-info}/WHEEL +0 -0
data_management/cct_to_wi.py
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
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():
|
|
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
|
-
row['uncertainty'] = None
|
|
267
|
-
row['timestamp'] = im['datetime']; assert isinstance(im['datetime'],str)
|
|
268
|
-
row['highlighted'] = 0
|
|
269
|
-
row['age'] = None
|
|
270
|
-
row['sex'] = None
|
|
271
|
-
row['animal_recognizable'] = 'No'
|
|
272
|
-
row['individual_id'] = None
|
|
273
|
-
row['individual_animal_notes'] = None
|
|
274
|
-
row['markings'] = None
|
|
275
|
-
|
|
276
|
-
assert len(row) == len(images_fields)
|
|
277
|
-
rows.append(row)
|
|
278
|
-
|
|
279
|
-
df = pd.DataFrame(rows)
|
|
280
|
-
|
|
281
|
-
df.to_csv(os.path.join(output_base,images_file_name),index=False)
|
|
282
|
-
|
|
283
|
-
# ...main()
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
#%% Command-line driver
|
|
287
|
-
|
|
288
|
-
if __name__ == '__main__':
|
|
289
|
-
main()
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
coco_to_labelme.py
|
|
4
|
-
|
|
5
|
-
Converts a COCO dataset to labelme format (one .json per image file).
|
|
6
|
-
|
|
7
|
-
If you want to convert YOLO-formatted data to labelme format, use yolo_to_coco, then
|
|
8
|
-
coco_to_labelme.
|
|
9
|
-
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
#%% Imports and constants
|
|
13
|
-
|
|
14
|
-
import os
|
|
15
|
-
import json
|
|
16
|
-
|
|
17
|
-
from tqdm import tqdm
|
|
18
|
-
from collections import defaultdict
|
|
19
|
-
|
|
20
|
-
from md_visualization.visualization_utils import open_image
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
#%% Functions
|
|
24
|
-
|
|
25
|
-
def get_labelme_dict_for_image_from_coco_record(im,annotations,categories,info=None):
|
|
26
|
-
"""
|
|
27
|
-
For the given image struct in COCO format and associated list of annotations, reformats the
|
|
28
|
-
detections into labelme format.
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
im (dict): image dict, as loaded from a COCO .json file; 'height' and 'width' are required
|
|
32
|
-
annotations (list): a list of annotations that refer to this image (this function errors if
|
|
33
|
-
that's not the case)
|
|
34
|
-
categories (list): a list of category in dicts in COCO format ({'id':x,'name':'s'})
|
|
35
|
-
info (dict, optional): a dict to store in a non-standard "custom_info" field in the output
|
|
36
|
-
|
|
37
|
-
Returns:
|
|
38
|
-
dict: a dict in labelme format, suitable for writing to a labelme .json file
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
image_base_name = os.path.basename(im['file_name'])
|
|
42
|
-
|
|
43
|
-
output_dict = {}
|
|
44
|
-
if info is not None:
|
|
45
|
-
output_dict['custom_info'] = info
|
|
46
|
-
output_dict['version'] = '5.3.0a0'
|
|
47
|
-
output_dict['flags'] = {}
|
|
48
|
-
output_dict['shapes'] = []
|
|
49
|
-
output_dict['imagePath'] = image_base_name
|
|
50
|
-
output_dict['imageHeight'] = im['height']
|
|
51
|
-
output_dict['imageWidth'] = im['width']
|
|
52
|
-
output_dict['imageData'] = None
|
|
53
|
-
|
|
54
|
-
# Store COCO categories in case we want to reconstruct the original IDs later
|
|
55
|
-
output_dict['coco_categories'] = categories
|
|
56
|
-
|
|
57
|
-
category_id_to_name = {c['id']:c['name'] for c in categories}
|
|
58
|
-
|
|
59
|
-
if 'flags' in im:
|
|
60
|
-
output_dict['flags'] = im['flags']
|
|
61
|
-
|
|
62
|
-
# ann = annotations[0]
|
|
63
|
-
for ann in annotations:
|
|
64
|
-
|
|
65
|
-
assert ann['image_id'] == im['id'], 'Annotation {} does not refer to image {}'.format(
|
|
66
|
-
ann['id'],im['id'])
|
|
67
|
-
|
|
68
|
-
if 'bbox' not in ann:
|
|
69
|
-
continue
|
|
70
|
-
|
|
71
|
-
shape = {}
|
|
72
|
-
shape['label'] = category_id_to_name[ann['category_id']]
|
|
73
|
-
shape['shape_type'] = 'rectangle'
|
|
74
|
-
shape['description'] = ''
|
|
75
|
-
shape['group_id'] = None
|
|
76
|
-
|
|
77
|
-
# COCO boxes are [x_min, y_min, width_of_box, height_of_box] (absolute)
|
|
78
|
-
#
|
|
79
|
-
# labelme boxes are [[x0,y0],[x1,y1]] (absolute)
|
|
80
|
-
x0 = ann['bbox'][0]
|
|
81
|
-
y0 = ann['bbox'][1]
|
|
82
|
-
x1 = ann['bbox'][0] + ann['bbox'][2]
|
|
83
|
-
y1 = ann['bbox'][1] + ann['bbox'][3]
|
|
84
|
-
|
|
85
|
-
shape['points'] = [[x0,y0],[x1,y1]]
|
|
86
|
-
output_dict['shapes'].append(shape)
|
|
87
|
-
|
|
88
|
-
# ...for each detection
|
|
89
|
-
|
|
90
|
-
return output_dict
|
|
91
|
-
|
|
92
|
-
# ...def get_labelme_dict_for_image()
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def coco_to_labelme(coco_data,image_base,overwrite=False,bypass_image_size_check=False,verbose=False):
|
|
96
|
-
"""
|
|
97
|
-
For all the images in [coco_data] (a dict or a filename), write a .json file in
|
|
98
|
-
labelme format alongside the corresponding relative path within image_base.
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
# Load COCO data if necessary
|
|
102
|
-
if isinstance(coco_data,str):
|
|
103
|
-
with open(coco_data,'r') as f:
|
|
104
|
-
coco_data = json.load(f)
|
|
105
|
-
assert isinstance(coco_data,dict)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
## Read image sizes if necessary
|
|
109
|
-
|
|
110
|
-
if bypass_image_size_check:
|
|
111
|
-
|
|
112
|
-
print('Bypassing size check')
|
|
113
|
-
|
|
114
|
-
else:
|
|
115
|
-
|
|
116
|
-
# TODO: parallelize this loop
|
|
117
|
-
|
|
118
|
-
print('Reading/validating image sizes...')
|
|
119
|
-
|
|
120
|
-
# im = coco_data['images'][0]
|
|
121
|
-
for im in tqdm(coco_data['images']):
|
|
122
|
-
|
|
123
|
-
# Make sure this file exists
|
|
124
|
-
im_full_path = os.path.join(image_base,im['file_name'])
|
|
125
|
-
assert os.path.isfile(im_full_path), 'Image file {} does not exist'.format(im_full_path)
|
|
126
|
-
|
|
127
|
-
# Load w/h information if necessary
|
|
128
|
-
if 'height' not in im or 'width' not in im:
|
|
129
|
-
|
|
130
|
-
try:
|
|
131
|
-
pil_im = open_image(im_full_path)
|
|
132
|
-
im['width'] = pil_im.width
|
|
133
|
-
im['height'] = pil_im.height
|
|
134
|
-
except Exception:
|
|
135
|
-
print('Warning: cannot open image {}'.format(im_full_path))
|
|
136
|
-
if 'failure' not in im:
|
|
137
|
-
im['failure'] = 'Failure image access'
|
|
138
|
-
|
|
139
|
-
# ...if we need to read w/h information
|
|
140
|
-
|
|
141
|
-
# ...for each image
|
|
142
|
-
|
|
143
|
-
# ...if we need to load image sizes
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
## Generate labelme files
|
|
147
|
-
|
|
148
|
-
print('Generating .json files...')
|
|
149
|
-
|
|
150
|
-
image_id_to_annotations = defaultdict(list)
|
|
151
|
-
for ann in coco_data['annotations']:
|
|
152
|
-
image_id_to_annotations[ann['image_id']].append(ann)
|
|
153
|
-
|
|
154
|
-
n_json_files_written = 0
|
|
155
|
-
n_json_files_error = 0
|
|
156
|
-
n_json_files_exist = 0
|
|
157
|
-
|
|
158
|
-
# Write output
|
|
159
|
-
for im in tqdm(coco_data['images']):
|
|
160
|
-
|
|
161
|
-
# Skip this image if it failed to load in whatever system generated this COCO file
|
|
162
|
-
skip_image = False
|
|
163
|
-
|
|
164
|
-
# Errors are represented differently depending on the source
|
|
165
|
-
for error_string in ('failure','error'):
|
|
166
|
-
if (error_string in im) and (im[error_string] is not None):
|
|
167
|
-
if verbose:
|
|
168
|
-
print('Warning: skipping labelme file generation for failed image {}'.format(
|
|
169
|
-
im['file_name']))
|
|
170
|
-
skip_image = True
|
|
171
|
-
n_json_files_error += 1
|
|
172
|
-
break
|
|
173
|
-
if skip_image:
|
|
174
|
-
continue
|
|
175
|
-
|
|
176
|
-
im_full_path = os.path.join(image_base,im['file_name'])
|
|
177
|
-
json_path = os.path.splitext(im_full_path)[0] + '.json'
|
|
178
|
-
|
|
179
|
-
if (not overwrite) and (os.path.isfile(json_path)):
|
|
180
|
-
if verbose:
|
|
181
|
-
print('Skipping existing file {}'.format(json_path))
|
|
182
|
-
n_json_files_exist += 1
|
|
183
|
-
continue
|
|
184
|
-
|
|
185
|
-
annotations_this_image = image_id_to_annotations[im['id']]
|
|
186
|
-
output_dict = get_labelme_dict_for_image_from_coco_record(im,
|
|
187
|
-
annotations_this_image,
|
|
188
|
-
coco_data['categories'],
|
|
189
|
-
info=None)
|
|
190
|
-
|
|
191
|
-
n_json_files_written += 1
|
|
192
|
-
with open(json_path,'w') as f:
|
|
193
|
-
json.dump(output_dict,f,indent=1)
|
|
194
|
-
|
|
195
|
-
# ...for each image
|
|
196
|
-
|
|
197
|
-
print('\nWrote {} .json files (skipped {} for errors, {} because they exist)'.format(
|
|
198
|
-
n_json_files_written,n_json_files_error,n_json_files_exist))
|
|
199
|
-
|
|
200
|
-
# ...def coco_to_labelme()
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
#%% Interactive driver
|
|
204
|
-
|
|
205
|
-
if False:
|
|
206
|
-
|
|
207
|
-
pass
|
|
208
|
-
|
|
209
|
-
#%% Configure options
|
|
210
|
-
|
|
211
|
-
coco_file = \
|
|
212
|
-
r'C:\\temp\\snapshot-exploration\\images\\training-images-good\\training-images-good_from_yolo.json'
|
|
213
|
-
image_folder = os.path.dirname(coco_file)
|
|
214
|
-
overwrite = True
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
#%% Programmatic execution
|
|
218
|
-
|
|
219
|
-
coco_to_labelme(coco_data=coco_file,image_base=image_folder,overwrite=overwrite)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
#%% Command-line execution
|
|
223
|
-
|
|
224
|
-
s = 'python coco_to_labelme.py "{}" "{}"'.format(coco_file,image_folder)
|
|
225
|
-
if overwrite:
|
|
226
|
-
s += ' --overwrite'
|
|
227
|
-
|
|
228
|
-
print(s)
|
|
229
|
-
import clipboard; clipboard.copy(s)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
#%% Opening labelme
|
|
233
|
-
|
|
234
|
-
s = 'python labelme {}'.format(image_folder)
|
|
235
|
-
print(s)
|
|
236
|
-
import clipboard; clipboard.copy(s)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
#%% Command-line driver
|
|
240
|
-
|
|
241
|
-
import sys,argparse
|
|
242
|
-
|
|
243
|
-
def main():
|
|
244
|
-
|
|
245
|
-
parser = argparse.ArgumentParser(
|
|
246
|
-
description='Convert a COCO database to labelme annotation format')
|
|
247
|
-
|
|
248
|
-
parser.add_argument(
|
|
249
|
-
'coco_file',
|
|
250
|
-
type=str,
|
|
251
|
-
help='Path to COCO data file (.json)')
|
|
252
|
-
|
|
253
|
-
parser.add_argument(
|
|
254
|
-
'image_base',
|
|
255
|
-
type=str,
|
|
256
|
-
help='Path to images (also the output folder)')
|
|
257
|
-
|
|
258
|
-
parser.add_argument(
|
|
259
|
-
'--overwrite',
|
|
260
|
-
action='store_true',
|
|
261
|
-
help='Overwrite existing labelme .json files')
|
|
262
|
-
|
|
263
|
-
if len(sys.argv[1:]) == 0:
|
|
264
|
-
parser.print_help()
|
|
265
|
-
parser.exit()
|
|
266
|
-
|
|
267
|
-
args = parser.parse_args()
|
|
268
|
-
|
|
269
|
-
coco_to_labelme(coco_data=args.coco_file,image_base=args.image_base,overwrite=args.overwrite)
|
|
270
|
-
|
|
271
|
-
if __name__ == '__main__':
|
|
272
|
-
main()
|