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
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
save_the_elephants_survey_B.py
|
|
4
|
-
|
|
5
|
-
Convert the .csv file provided for the Save the Elephants Survey B data set to a
|
|
6
|
-
COCO-camera-traps .json file
|
|
7
|
-
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
#%% Constants and environment
|
|
11
|
-
|
|
12
|
-
from md_visualization import visualize_db
|
|
13
|
-
from data_management.databases import integrity_check_json_db
|
|
14
|
-
import pandas as pd
|
|
15
|
-
import os
|
|
16
|
-
import glob
|
|
17
|
-
import json
|
|
18
|
-
import uuid
|
|
19
|
-
import time
|
|
20
|
-
import humanfriendly
|
|
21
|
-
from PIL import Image
|
|
22
|
-
import numpy as np
|
|
23
|
-
import logging
|
|
24
|
-
from tqdm import tqdm
|
|
25
|
-
|
|
26
|
-
from md_utils.path_utils import find_images
|
|
27
|
-
|
|
28
|
-
input_base = r'z:/ste_2019_08_drop'
|
|
29
|
-
# input_base = r'/mnt/blobfuse/wildlifeblobssc/ste_2019_08_drop'
|
|
30
|
-
input_metadata_file = os.path.join(input_base,'SURVEY B.xlsx')
|
|
31
|
-
|
|
32
|
-
output_base = r'f:/save_the_elephants/survey_b'
|
|
33
|
-
# output_base = r'/home/gramener/survey_b'
|
|
34
|
-
output_json_file = os.path.join(output_base,'ste_survey_b.json')
|
|
35
|
-
image_directory = os.path.join(input_base,'SURVEY B with False Triggers')
|
|
36
|
-
|
|
37
|
-
os.makedirs(output_base,exist_ok=True)
|
|
38
|
-
assert(os.path.isdir(image_directory))
|
|
39
|
-
assert(os.path.isfile(input_metadata_file))
|
|
40
|
-
|
|
41
|
-
# Handle all unstructured fields in the source data as extra fields in the annotations
|
|
42
|
-
mapped_fields = {'No. of Animals in Photo':'num_animals',
|
|
43
|
-
'No. of new indiviauls (first sighting of new individual)':'num_new_individuals',
|
|
44
|
-
'Number Adult Males (first sighting of new individual)':'num_adult_males',
|
|
45
|
-
'Number Adult Females (first sighting of new individual)':'num_adult_females',
|
|
46
|
-
'Number Adult Unknown (first sighting of new individual)':'num_adult_unknown',
|
|
47
|
-
'Number Sub-adult Males (first sighting of new individual)':'num_subadult_males',
|
|
48
|
-
'Number Sub-adult Females (first sighting of new individual)':'num_subadult_females',
|
|
49
|
-
'Number Sub-adult Unknown (first sighting of new individual)':'num_subadult_unknown',
|
|
50
|
-
'Number Juvenile (first sighting of new individual)':'num_juvenile',
|
|
51
|
-
'Number Newborn (first sighting of new individual)':'num_newborn',
|
|
52
|
-
'Activity':'activity',
|
|
53
|
-
'Animal ID':'animal_id',
|
|
54
|
-
'Specific Notes':'notes'}
|
|
55
|
-
|
|
56
|
-
# photo_type really should be an image property, but there are a few conflicts
|
|
57
|
-
# that forced me to handle it as an annotation proprerty
|
|
58
|
-
mapped_fields['Photo Type '] = 'photo_type'
|
|
59
|
-
|
|
60
|
-
#%% Read source data
|
|
61
|
-
|
|
62
|
-
input_metadata = pd.read_excel(input_metadata_file, sheet_name='9. CT Image')
|
|
63
|
-
input_metadata = input_metadata.iloc[2:]
|
|
64
|
-
|
|
65
|
-
print('Read {} columns and {} rows from metadata file'.format(len(input_metadata.columns),
|
|
66
|
-
len(input_metadata)))
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
#%% Map filenames to rows, verify image existence
|
|
70
|
-
|
|
71
|
-
#%% Map filenames to rows, verify image existence
|
|
72
|
-
|
|
73
|
-
start_time = time.time()
|
|
74
|
-
|
|
75
|
-
# Maps relative paths to row indices in input_metadata
|
|
76
|
-
filenames_to_rows = {}
|
|
77
|
-
filenames_with_multiple_annotations = []
|
|
78
|
-
missing_images = []
|
|
79
|
-
|
|
80
|
-
# Build up a map from filenames to a list of rows, checking image existence as we go
|
|
81
|
-
for i_row, fn in tqdm(enumerate(input_metadata['Image Name']), total=len(input_metadata)):
|
|
82
|
-
try:
|
|
83
|
-
# Ignore directories
|
|
84
|
-
if not fn.endswith('.JPG'):
|
|
85
|
-
continue
|
|
86
|
-
|
|
87
|
-
if fn in filenames_to_rows:
|
|
88
|
-
filenames_with_multiple_annotations.append(fn)
|
|
89
|
-
filenames_to_rows[fn].append(i_row)
|
|
90
|
-
else:
|
|
91
|
-
filenames_to_rows[fn] = [i_row]
|
|
92
|
-
image_path = os.path.join(image_directory, fn)
|
|
93
|
-
if not os.path.isfile(image_path):
|
|
94
|
-
missing_images.append(image_path)
|
|
95
|
-
except:
|
|
96
|
-
continue
|
|
97
|
-
|
|
98
|
-
elapsed = time.time() - start_time
|
|
99
|
-
|
|
100
|
-
print('Finished verifying image existence for {} files in {}, found {} filenames with multiple labels, {} missing images'.format(
|
|
101
|
-
len(filenames_to_rows), humanfriendly.format_timespan(elapsed),
|
|
102
|
-
len(filenames_with_multiple_annotations), len(missing_images)))
|
|
103
|
-
|
|
104
|
-
#%% Make sure the multiple-annotation cases make sense
|
|
105
|
-
|
|
106
|
-
if False:
|
|
107
|
-
|
|
108
|
-
#%%
|
|
109
|
-
|
|
110
|
-
fn = filenames_with_multiple_annotations[1000]
|
|
111
|
-
rows = filenames_to_rows[fn]
|
|
112
|
-
assert(len(rows) > 1)
|
|
113
|
-
for i_row in rows:
|
|
114
|
-
print(input_metadata.iloc[i_row]['Species'])
|
|
115
|
-
|
|
116
|
-
#%% Check for images that aren't included in the metadata file
|
|
117
|
-
|
|
118
|
-
# Enumerate all images
|
|
119
|
-
image_full_paths = find_images(image_directory, bRecursive=True)
|
|
120
|
-
|
|
121
|
-
unannotated_images = []
|
|
122
|
-
|
|
123
|
-
for iImage, image_path in tqdm(enumerate(image_full_paths),total=len(image_full_paths)):
|
|
124
|
-
relative_path = os.path.relpath(image_path,image_directory)
|
|
125
|
-
if relative_path not in filenames_to_rows:
|
|
126
|
-
unannotated_images.append(relative_path)
|
|
127
|
-
|
|
128
|
-
print('Finished checking {} images to make sure they\'re in the metadata, found {} unannotated images'.format(
|
|
129
|
-
len(image_full_paths),len(unannotated_images)))
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
#%% Create CCT dictionaries
|
|
133
|
-
|
|
134
|
-
images = []
|
|
135
|
-
annotations = []
|
|
136
|
-
categories = []
|
|
137
|
-
|
|
138
|
-
image_ids_to_images = {}
|
|
139
|
-
|
|
140
|
-
category_name_to_category = {}
|
|
141
|
-
|
|
142
|
-
# Force the empty category to be ID 0
|
|
143
|
-
empty_category = {}
|
|
144
|
-
empty_category['name'] = 'empty'
|
|
145
|
-
empty_category['id'] = 0
|
|
146
|
-
category_name_to_category['empty'] = empty_category
|
|
147
|
-
categories.append(empty_category)
|
|
148
|
-
next_category_id = 1
|
|
149
|
-
|
|
150
|
-
start_time = time.time()
|
|
151
|
-
# i_image = 0; image_name = list(filenames_to_rows.keys())[i_image]
|
|
152
|
-
for image_name in tqdm(list(filenames_to_rows.keys())):
|
|
153
|
-
|
|
154
|
-
# Example filename:
|
|
155
|
-
#
|
|
156
|
-
# 'Site 1_Oloisukut_1\Oloisukut_A11_UP\Service_2\100EK113\EK001382.JPG'
|
|
157
|
-
# 'Site 1_Oloisukut_1\Oloisukut_A11_UP\Service_2.1\100EK113\EK001382.JPG'
|
|
158
|
-
img_id = image_name.replace('\\','/').replace('\n','').replace('/','_').replace(' ','_')
|
|
159
|
-
|
|
160
|
-
row_indices = filenames_to_rows[image_name]
|
|
161
|
-
|
|
162
|
-
# i_row = row_indices[0]
|
|
163
|
-
for i_row in row_indices:
|
|
164
|
-
|
|
165
|
-
row = input_metadata.iloc[i_row]
|
|
166
|
-
assert(row['Image Name'] == image_name)
|
|
167
|
-
try:
|
|
168
|
-
timestamp = row['Date'].strftime("%d/%m/%Y")
|
|
169
|
-
except:
|
|
170
|
-
timestamp = ""
|
|
171
|
-
# timestamp = row['Date']
|
|
172
|
-
station_label = row['Camera Trap Station Label']
|
|
173
|
-
photo_type = row['Photo Type ']
|
|
174
|
-
if isinstance(photo_type,float):
|
|
175
|
-
photo_type = ''
|
|
176
|
-
photo_type = photo_type.strip().lower()
|
|
177
|
-
|
|
178
|
-
if img_id in image_ids_to_images:
|
|
179
|
-
|
|
180
|
-
im = image_ids_to_images[img_id]
|
|
181
|
-
assert im['file_name'] == image_name
|
|
182
|
-
assert im['station_label'] == station_label
|
|
183
|
-
|
|
184
|
-
# There are a small handful of datetime mismatches across annotations
|
|
185
|
-
# for the same image
|
|
186
|
-
# assert im['datetime'] == timestamp
|
|
187
|
-
if im['datetime'] != timestamp:
|
|
188
|
-
print('Warning: timestamp conflict for image {}: {},{}'.format(
|
|
189
|
-
image_name,im['datetime'],timestamp))
|
|
190
|
-
|
|
191
|
-
else:
|
|
192
|
-
|
|
193
|
-
im = {}
|
|
194
|
-
im['id'] = img_id
|
|
195
|
-
im['file_name'] = image_name
|
|
196
|
-
im['datetime'] = timestamp
|
|
197
|
-
im['station_label'] = station_label
|
|
198
|
-
im['photo_type'] = photo_type
|
|
199
|
-
|
|
200
|
-
image_ids_to_images[img_id] = im
|
|
201
|
-
images.append(im)
|
|
202
|
-
|
|
203
|
-
species = row['Species']
|
|
204
|
-
|
|
205
|
-
if (isinstance(species,float) or \
|
|
206
|
-
(isinstance(species,str) and (len(species) == 0))):
|
|
207
|
-
category_name = 'empty'
|
|
208
|
-
elif species.startswith('?'):
|
|
209
|
-
category_name = 'unknown'
|
|
210
|
-
else:
|
|
211
|
-
category_name = species
|
|
212
|
-
|
|
213
|
-
# Special cases based on the 'photo type' field
|
|
214
|
-
if 'vehicle' in photo_type:
|
|
215
|
-
category_name = 'vehicle'
|
|
216
|
-
# Various spellings of 'community'
|
|
217
|
-
elif 'comm' in photo_type:
|
|
218
|
-
category_name = 'human'
|
|
219
|
-
elif 'camera' in photo_type or 'researcher' in photo_type:
|
|
220
|
-
category_name = 'human'
|
|
221
|
-
elif 'livestock' in photo_type:
|
|
222
|
-
category_name = 'livestock'
|
|
223
|
-
elif 'blank' in photo_type:
|
|
224
|
-
category_name = 'empty'
|
|
225
|
-
elif 'plant movement' in photo_type:
|
|
226
|
-
category_name = 'empty'
|
|
227
|
-
|
|
228
|
-
category_name = category_name.strip().lower()
|
|
229
|
-
|
|
230
|
-
# Have we seen this category before?
|
|
231
|
-
if category_name in category_name_to_category:
|
|
232
|
-
category_id = category_name_to_category[category_name]['id']
|
|
233
|
-
else:
|
|
234
|
-
category_id = next_category_id
|
|
235
|
-
category = {}
|
|
236
|
-
category['id'] = category_id
|
|
237
|
-
category['name'] = category_name
|
|
238
|
-
category_name_to_category[category_name] = category
|
|
239
|
-
categories.append(category)
|
|
240
|
-
next_category_id += 1
|
|
241
|
-
|
|
242
|
-
# Create an annotation
|
|
243
|
-
ann = {}
|
|
244
|
-
ann['id'] = str(uuid.uuid1())
|
|
245
|
-
ann['image_id'] = im['id']
|
|
246
|
-
ann['category_id'] = category_id
|
|
247
|
-
|
|
248
|
-
# fieldname = list(mapped_fields.keys())[0]
|
|
249
|
-
for fieldname in mapped_fields:
|
|
250
|
-
target_field = mapped_fields[fieldname]
|
|
251
|
-
val = row[fieldname]
|
|
252
|
-
if isinstance(val,float) and np.isnan(val):
|
|
253
|
-
val = ''
|
|
254
|
-
else:
|
|
255
|
-
val = str(val).strip()
|
|
256
|
-
ann[target_field] = val
|
|
257
|
-
|
|
258
|
-
annotations.append(ann)
|
|
259
|
-
|
|
260
|
-
# ...for each row
|
|
261
|
-
|
|
262
|
-
# ...for each image
|
|
263
|
-
|
|
264
|
-
print('Finished creating CCT dictionaries in {}'.format(
|
|
265
|
-
humanfriendly.format_timespan(elapsed)))
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
#%% Create info struct
|
|
269
|
-
|
|
270
|
-
info = {}
|
|
271
|
-
info['year'] = 2019
|
|
272
|
-
info['version'] = 1
|
|
273
|
-
info['description'] = 'Save the Elephants Survey B'
|
|
274
|
-
info['contributor'] = 'Save the Elephants'
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
#%% Write output
|
|
278
|
-
|
|
279
|
-
json_data = {}
|
|
280
|
-
json_data['images'] = images
|
|
281
|
-
json_data['annotations'] = annotations
|
|
282
|
-
json_data['categories'] = categories
|
|
283
|
-
json_data['info'] = info
|
|
284
|
-
json.dump(json_data, open(output_json_file, 'w'), indent=2)
|
|
285
|
-
|
|
286
|
-
print('Finished writing .json file with {} images, {} annotations, and {} categories'.format(
|
|
287
|
-
len(images),len(annotations),len(categories)))
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
#%% Validate output
|
|
291
|
-
|
|
292
|
-
from data_management.databases import integrity_check_json_db
|
|
293
|
-
|
|
294
|
-
options = integrity_check_json_db.IntegrityCheckOptions()
|
|
295
|
-
options.baseDir = image_directory
|
|
296
|
-
options.bCheckImageSizes = False
|
|
297
|
-
options.bCheckImageExistence = False
|
|
298
|
-
options.bFindUnusedImages = False
|
|
299
|
-
|
|
300
|
-
sortedCategories, data = integrity_check_json_db.integrity_check_json_db(output_json_file,options)
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
#%% Preview labels
|
|
304
|
-
|
|
305
|
-
from md_visualization import visualize_db
|
|
306
|
-
from data_management.databases import integrity_check_json_db
|
|
307
|
-
|
|
308
|
-
viz_options = visualize_db.DbVizOptions()
|
|
309
|
-
viz_options.num_to_visualize = 1000
|
|
310
|
-
viz_options.trim_to_images_with_bboxes = False
|
|
311
|
-
viz_options.add_search_links = True
|
|
312
|
-
viz_options.sort_by_filename = False
|
|
313
|
-
viz_options.parallelize_rendering = True
|
|
314
|
-
html_output_file,image_db = visualize_db.visualize_db(db_path=output_json_file,
|
|
315
|
-
output_dir=os.path.join(output_base,'preview'),
|
|
316
|
-
image_base_dir=image_directory,
|
|
317
|
-
options=viz_options)
|
|
318
|
-
os.startfile(html_output_file)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
#%% Scrap
|
|
322
|
-
|
|
323
|
-
if False:
|
|
324
|
-
|
|
325
|
-
pass
|
|
326
|
-
|
|
327
|
-
#%% Find unique photo types
|
|
328
|
-
|
|
329
|
-
annotations = image_db['annotations']
|
|
330
|
-
photo_types = set()
|
|
331
|
-
for ann in tqdm(annotations):
|
|
332
|
-
photo_types.add(ann['photo_type'])
|