megadetector 10.0.13__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/__init__.py +0 -0
- megadetector/api/__init__.py +0 -0
- megadetector/api/batch_processing/integration/digiKam/setup.py +6 -0
- megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +465 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/config_template.py +5 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +125 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +55 -0
- megadetector/classification/__init__.py +0 -0
- megadetector/classification/aggregate_classifier_probs.py +108 -0
- megadetector/classification/analyze_failed_images.py +227 -0
- megadetector/classification/cache_batchapi_outputs.py +198 -0
- megadetector/classification/create_classification_dataset.py +626 -0
- megadetector/classification/crop_detections.py +516 -0
- megadetector/classification/csv_to_json.py +226 -0
- megadetector/classification/detect_and_crop.py +853 -0
- megadetector/classification/efficientnet/__init__.py +9 -0
- megadetector/classification/efficientnet/model.py +415 -0
- megadetector/classification/efficientnet/utils.py +608 -0
- megadetector/classification/evaluate_model.py +520 -0
- megadetector/classification/identify_mislabeled_candidates.py +152 -0
- megadetector/classification/json_to_azcopy_list.py +63 -0
- megadetector/classification/json_validator.py +696 -0
- megadetector/classification/map_classification_categories.py +276 -0
- megadetector/classification/merge_classification_detection_output.py +509 -0
- megadetector/classification/prepare_classification_script.py +194 -0
- megadetector/classification/prepare_classification_script_mc.py +228 -0
- megadetector/classification/run_classifier.py +287 -0
- megadetector/classification/save_mislabeled.py +110 -0
- megadetector/classification/train_classifier.py +827 -0
- megadetector/classification/train_classifier_tf.py +725 -0
- megadetector/classification/train_utils.py +323 -0
- megadetector/data_management/__init__.py +0 -0
- megadetector/data_management/animl_to_md.py +161 -0
- megadetector/data_management/annotations/__init__.py +0 -0
- megadetector/data_management/annotations/annotation_constants.py +33 -0
- megadetector/data_management/camtrap_dp_to_coco.py +270 -0
- megadetector/data_management/cct_json_utils.py +566 -0
- megadetector/data_management/cct_to_md.py +184 -0
- megadetector/data_management/cct_to_wi.py +293 -0
- megadetector/data_management/coco_to_labelme.py +284 -0
- megadetector/data_management/coco_to_yolo.py +702 -0
- megadetector/data_management/databases/__init__.py +0 -0
- megadetector/data_management/databases/add_width_and_height_to_db.py +107 -0
- megadetector/data_management/databases/combine_coco_camera_traps_files.py +210 -0
- megadetector/data_management/databases/integrity_check_json_db.py +528 -0
- megadetector/data_management/databases/subset_json_db.py +195 -0
- megadetector/data_management/generate_crops_from_cct.py +200 -0
- megadetector/data_management/get_image_sizes.py +164 -0
- megadetector/data_management/labelme_to_coco.py +559 -0
- megadetector/data_management/labelme_to_yolo.py +349 -0
- megadetector/data_management/lila/__init__.py +0 -0
- megadetector/data_management/lila/create_lila_blank_set.py +556 -0
- megadetector/data_management/lila/create_lila_test_set.py +187 -0
- megadetector/data_management/lila/create_links_to_md_results_files.py +106 -0
- megadetector/data_management/lila/download_lila_subset.py +182 -0
- megadetector/data_management/lila/generate_lila_per_image_labels.py +777 -0
- megadetector/data_management/lila/get_lila_annotation_counts.py +174 -0
- megadetector/data_management/lila/get_lila_image_counts.py +112 -0
- megadetector/data_management/lila/lila_common.py +319 -0
- megadetector/data_management/lila/test_lila_metadata_urls.py +164 -0
- megadetector/data_management/mewc_to_md.py +344 -0
- megadetector/data_management/ocr_tools.py +873 -0
- megadetector/data_management/read_exif.py +964 -0
- megadetector/data_management/remap_coco_categories.py +195 -0
- megadetector/data_management/remove_exif.py +156 -0
- megadetector/data_management/rename_images.py +194 -0
- megadetector/data_management/resize_coco_dataset.py +663 -0
- megadetector/data_management/speciesnet_to_md.py +41 -0
- megadetector/data_management/wi_download_csv_to_coco.py +247 -0
- megadetector/data_management/yolo_output_to_md_output.py +594 -0
- megadetector/data_management/yolo_to_coco.py +876 -0
- megadetector/data_management/zamba_to_md.py +188 -0
- megadetector/detection/__init__.py +0 -0
- megadetector/detection/change_detection.py +840 -0
- megadetector/detection/process_video.py +479 -0
- megadetector/detection/pytorch_detector.py +1451 -0
- megadetector/detection/run_detector.py +1267 -0
- megadetector/detection/run_detector_batch.py +2159 -0
- megadetector/detection/run_inference_with_yolov5_val.py +1314 -0
- megadetector/detection/run_md_and_speciesnet.py +1494 -0
- megadetector/detection/run_tiled_inference.py +1038 -0
- megadetector/detection/tf_detector.py +209 -0
- megadetector/detection/video_utils.py +1379 -0
- megadetector/postprocessing/__init__.py +0 -0
- megadetector/postprocessing/add_max_conf.py +72 -0
- megadetector/postprocessing/categorize_detections_by_size.py +166 -0
- megadetector/postprocessing/classification_postprocessing.py +1752 -0
- megadetector/postprocessing/combine_batch_outputs.py +249 -0
- megadetector/postprocessing/compare_batch_results.py +2110 -0
- megadetector/postprocessing/convert_output_format.py +403 -0
- megadetector/postprocessing/create_crop_folder.py +629 -0
- megadetector/postprocessing/detector_calibration.py +570 -0
- megadetector/postprocessing/generate_csv_report.py +522 -0
- megadetector/postprocessing/load_api_results.py +223 -0
- megadetector/postprocessing/md_to_coco.py +428 -0
- megadetector/postprocessing/md_to_labelme.py +351 -0
- megadetector/postprocessing/md_to_wi.py +41 -0
- megadetector/postprocessing/merge_detections.py +392 -0
- megadetector/postprocessing/postprocess_batch_results.py +2077 -0
- megadetector/postprocessing/remap_detection_categories.py +226 -0
- megadetector/postprocessing/render_detection_confusion_matrix.py +677 -0
- megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +206 -0
- megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +82 -0
- megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +1665 -0
- megadetector/postprocessing/separate_detections_into_folders.py +795 -0
- megadetector/postprocessing/subset_json_detector_output.py +964 -0
- megadetector/postprocessing/top_folders_to_bottom.py +238 -0
- megadetector/postprocessing/validate_batch_results.py +332 -0
- megadetector/taxonomy_mapping/__init__.py +0 -0
- megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +491 -0
- megadetector/taxonomy_mapping/map_new_lila_datasets.py +213 -0
- megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +165 -0
- megadetector/taxonomy_mapping/preview_lila_taxonomy.py +543 -0
- megadetector/taxonomy_mapping/retrieve_sample_image.py +71 -0
- megadetector/taxonomy_mapping/simple_image_download.py +224 -0
- megadetector/taxonomy_mapping/species_lookup.py +1008 -0
- megadetector/taxonomy_mapping/taxonomy_csv_checker.py +159 -0
- megadetector/taxonomy_mapping/taxonomy_graph.py +346 -0
- megadetector/taxonomy_mapping/validate_lila_category_mappings.py +83 -0
- megadetector/tests/__init__.py +0 -0
- megadetector/tests/test_nms_synthetic.py +335 -0
- megadetector/utils/__init__.py +0 -0
- megadetector/utils/ct_utils.py +1857 -0
- megadetector/utils/directory_listing.py +199 -0
- megadetector/utils/extract_frames_from_video.py +307 -0
- megadetector/utils/gpu_test.py +125 -0
- megadetector/utils/md_tests.py +2072 -0
- megadetector/utils/path_utils.py +2832 -0
- megadetector/utils/process_utils.py +172 -0
- megadetector/utils/split_locations_into_train_val.py +237 -0
- megadetector/utils/string_utils.py +234 -0
- megadetector/utils/url_utils.py +825 -0
- megadetector/utils/wi_platform_utils.py +968 -0
- megadetector/utils/wi_taxonomy_utils.py +1759 -0
- megadetector/utils/write_html_image_list.py +239 -0
- megadetector/visualization/__init__.py +0 -0
- megadetector/visualization/plot_utils.py +309 -0
- megadetector/visualization/render_images_with_thumbnails.py +243 -0
- megadetector/visualization/visualization_utils.py +1940 -0
- megadetector/visualization/visualize_db.py +630 -0
- megadetector/visualization/visualize_detector_output.py +479 -0
- megadetector/visualization/visualize_video_output.py +705 -0
- megadetector-10.0.13.dist-info/METADATA +134 -0
- megadetector-10.0.13.dist-info/RECORD +147 -0
- megadetector-10.0.13.dist-info/WHEEL +5 -0
- megadetector-10.0.13.dist-info/licenses/LICENSE +19 -0
- megadetector-10.0.13.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,284 @@
|
|
|
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
|
+
import sys
|
|
17
|
+
import argparse
|
|
18
|
+
|
|
19
|
+
from tqdm import tqdm
|
|
20
|
+
from collections import defaultdict
|
|
21
|
+
|
|
22
|
+
from megadetector.visualization.visualization_utils import open_image
|
|
23
|
+
from megadetector.detection.run_detector import FAILURE_IMAGE_OPEN
|
|
24
|
+
from megadetector.utils import ct_utils
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
#%% Functions
|
|
28
|
+
|
|
29
|
+
def get_labelme_dict_for_image_from_coco_record(im,annotations,categories,info=None):
|
|
30
|
+
"""
|
|
31
|
+
For the given image struct in COCO format and associated list of annotations, reformats the
|
|
32
|
+
detections into labelme format.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
im (dict): image dict, as loaded from a COCO .json file; 'height' and 'width' are required
|
|
36
|
+
annotations (list): a list of annotations that refer to this image (this function errors if
|
|
37
|
+
that's not the case)
|
|
38
|
+
categories (list): a list of category in dicts in COCO format ({'id':x,'name':'s'})
|
|
39
|
+
info (dict, optional): a dict to store in a non-standard "custom_info" field in the output
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
dict: a dict in labelme format, suitable for writing to a labelme .json file
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
image_base_name = os.path.basename(im['file_name'])
|
|
46
|
+
|
|
47
|
+
output_dict = {}
|
|
48
|
+
if info is not None:
|
|
49
|
+
output_dict['custom_info'] = info
|
|
50
|
+
output_dict['version'] = '5.3.0a0'
|
|
51
|
+
output_dict['flags'] = {}
|
|
52
|
+
output_dict['shapes'] = []
|
|
53
|
+
output_dict['imagePath'] = image_base_name
|
|
54
|
+
output_dict['imageHeight'] = im['height']
|
|
55
|
+
output_dict['imageWidth'] = im['width']
|
|
56
|
+
output_dict['imageData'] = None
|
|
57
|
+
|
|
58
|
+
# Store COCO categories in case we want to reconstruct the original IDs later
|
|
59
|
+
output_dict['coco_categories'] = categories
|
|
60
|
+
|
|
61
|
+
category_id_to_name = {c['id']:c['name'] for c in categories}
|
|
62
|
+
|
|
63
|
+
if 'flags' in im:
|
|
64
|
+
output_dict['flags'] = im['flags']
|
|
65
|
+
|
|
66
|
+
# ann = annotations[0]
|
|
67
|
+
for ann in annotations:
|
|
68
|
+
|
|
69
|
+
assert ann['image_id'] == im['id'], 'Annotation {} does not refer to image {}'.format(
|
|
70
|
+
ann['id'],im['id'])
|
|
71
|
+
|
|
72
|
+
if 'bbox' not in ann:
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
shape = {}
|
|
76
|
+
shape['label'] = category_id_to_name[ann['category_id']]
|
|
77
|
+
shape['shape_type'] = 'rectangle'
|
|
78
|
+
shape['description'] = ''
|
|
79
|
+
shape['group_id'] = None
|
|
80
|
+
|
|
81
|
+
# COCO boxes are [x_min, y_min, width_of_box, height_of_box] (absolute)
|
|
82
|
+
#
|
|
83
|
+
# labelme boxes are [[x0,y0],[x1,y1]] (absolute)
|
|
84
|
+
x0 = ann['bbox'][0]
|
|
85
|
+
y0 = ann['bbox'][1]
|
|
86
|
+
x1 = ann['bbox'][0] + ann['bbox'][2]
|
|
87
|
+
y1 = ann['bbox'][1] + ann['bbox'][3]
|
|
88
|
+
|
|
89
|
+
shape['points'] = [[x0,y0],[x1,y1]]
|
|
90
|
+
output_dict['shapes'].append(shape)
|
|
91
|
+
|
|
92
|
+
# ...for each detection
|
|
93
|
+
|
|
94
|
+
return output_dict
|
|
95
|
+
|
|
96
|
+
# ...def get_labelme_dict_for_image()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def coco_to_labelme(coco_data,image_base,overwrite=False,bypass_image_size_check=False,verbose=False):
|
|
100
|
+
"""
|
|
101
|
+
For all the images in [coco_data] (a dict or a filename), write a .json file in
|
|
102
|
+
labelme format alongside the corresponding relative path within image_base.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
coco_data (dict or str): path to a COCO-formatted .json file, or an already-loaded
|
|
106
|
+
COCO-formatted dict
|
|
107
|
+
image_base (str): path where images live (filenames in [coco_data] should be relative to
|
|
108
|
+
[image_base]); this is also where labelme files will be written
|
|
109
|
+
overwrite (bool, optional): overwrite existing .json files
|
|
110
|
+
bypass_image_size_check (bool, optional): if you're sure that the COCO data already has
|
|
111
|
+
correct 'width' and 'height' fields, this bypasses the somewhat-slow loading of
|
|
112
|
+
each image to fetch image sizes
|
|
113
|
+
verbose (bool, optional): enable additional debug output
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
# Load COCO data if necessary
|
|
117
|
+
if isinstance(coco_data,str):
|
|
118
|
+
with open(coco_data,'r') as f:
|
|
119
|
+
coco_data = json.load(f)
|
|
120
|
+
assert isinstance(coco_data,dict)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## Read image sizes if necessary
|
|
124
|
+
|
|
125
|
+
if bypass_image_size_check:
|
|
126
|
+
|
|
127
|
+
print('Bypassing size check')
|
|
128
|
+
|
|
129
|
+
else:
|
|
130
|
+
|
|
131
|
+
# TODO: parallelize this loop
|
|
132
|
+
|
|
133
|
+
print('Reading/validating image sizes...')
|
|
134
|
+
|
|
135
|
+
# im = coco_data['images'][0]
|
|
136
|
+
for im in tqdm(coco_data['images']):
|
|
137
|
+
|
|
138
|
+
# Make sure this file exists
|
|
139
|
+
im_full_path = os.path.join(image_base,im['file_name'])
|
|
140
|
+
assert os.path.isfile(im_full_path), 'Image file {} does not exist'.format(im_full_path)
|
|
141
|
+
|
|
142
|
+
# Load w/h information if necessary
|
|
143
|
+
if 'height' not in im or 'width' not in im:
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
pil_im = open_image(im_full_path)
|
|
147
|
+
im['width'] = pil_im.width
|
|
148
|
+
im['height'] = pil_im.height
|
|
149
|
+
except Exception:
|
|
150
|
+
print('Warning: cannot open image {}'.format(im_full_path))
|
|
151
|
+
if 'failure' not in im:
|
|
152
|
+
im['failure'] = FAILURE_IMAGE_OPEN
|
|
153
|
+
|
|
154
|
+
# ...if we need to read w/h information
|
|
155
|
+
|
|
156
|
+
# ...for each image
|
|
157
|
+
|
|
158
|
+
# ...if we need to load image sizes
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
## Generate labelme files
|
|
162
|
+
|
|
163
|
+
print('Generating .json files...')
|
|
164
|
+
|
|
165
|
+
image_id_to_annotations = defaultdict(list)
|
|
166
|
+
for ann in coco_data['annotations']:
|
|
167
|
+
image_id_to_annotations[ann['image_id']].append(ann)
|
|
168
|
+
|
|
169
|
+
n_json_files_written = 0
|
|
170
|
+
n_json_files_error = 0
|
|
171
|
+
n_json_files_exist = 0
|
|
172
|
+
|
|
173
|
+
# Write output
|
|
174
|
+
for im in tqdm(coco_data['images']):
|
|
175
|
+
|
|
176
|
+
# Skip this image if it failed to load in whatever system generated this COCO file
|
|
177
|
+
skip_image = False
|
|
178
|
+
|
|
179
|
+
# Errors are represented differently depending on the source
|
|
180
|
+
for error_string in ('failure','error'):
|
|
181
|
+
if (error_string in im) and (im[error_string] is not None):
|
|
182
|
+
if verbose:
|
|
183
|
+
print('Warning: skipping labelme file generation for failed image {}'.format(
|
|
184
|
+
im['file_name']))
|
|
185
|
+
skip_image = True
|
|
186
|
+
n_json_files_error += 1
|
|
187
|
+
break
|
|
188
|
+
if skip_image:
|
|
189
|
+
continue
|
|
190
|
+
|
|
191
|
+
im_full_path = os.path.join(image_base,im['file_name'])
|
|
192
|
+
json_path = os.path.splitext(im_full_path)[0] + '.json'
|
|
193
|
+
|
|
194
|
+
if (not overwrite) and (os.path.isfile(json_path)):
|
|
195
|
+
if verbose:
|
|
196
|
+
print('Skipping existing file {}'.format(json_path))
|
|
197
|
+
n_json_files_exist += 1
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
annotations_this_image = image_id_to_annotations[im['id']]
|
|
201
|
+
output_dict = get_labelme_dict_for_image_from_coco_record(im,
|
|
202
|
+
annotations_this_image,
|
|
203
|
+
coco_data['categories'],
|
|
204
|
+
info=None)
|
|
205
|
+
|
|
206
|
+
n_json_files_written += 1
|
|
207
|
+
ct_utils.write_json(json_path, output_dict)
|
|
208
|
+
|
|
209
|
+
# ...for each image
|
|
210
|
+
|
|
211
|
+
print('\nWrote {} .json files (skipped {} for errors, {} because they exist)'.format(
|
|
212
|
+
n_json_files_written,n_json_files_error,n_json_files_exist))
|
|
213
|
+
|
|
214
|
+
# ...def coco_to_labelme()
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
#%% Interactive driver
|
|
218
|
+
|
|
219
|
+
if False:
|
|
220
|
+
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
#%% Configure options
|
|
224
|
+
|
|
225
|
+
coco_file = \
|
|
226
|
+
r'C:\\temp\\snapshot-exploration\\images\\training-images-good\\training-images-good_from_yolo.json'
|
|
227
|
+
image_folder = os.path.dirname(coco_file)
|
|
228
|
+
overwrite = True
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
#%% Programmatic execution
|
|
232
|
+
|
|
233
|
+
coco_to_labelme(coco_data=coco_file,image_base=image_folder,overwrite=overwrite)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
#%% Command-line execution
|
|
237
|
+
|
|
238
|
+
s = 'python coco_to_labelme.py "{}" "{}"'.format(coco_file,image_folder)
|
|
239
|
+
if overwrite:
|
|
240
|
+
s += ' --overwrite'
|
|
241
|
+
|
|
242
|
+
print(s)
|
|
243
|
+
import clipboard; clipboard.copy(s)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
#%% Opening labelme
|
|
247
|
+
|
|
248
|
+
s = 'python labelme {}'.format(image_folder)
|
|
249
|
+
print(s)
|
|
250
|
+
import clipboard; clipboard.copy(s)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
#%% Command-line driver
|
|
254
|
+
|
|
255
|
+
def main(): # noqa
|
|
256
|
+
|
|
257
|
+
parser = argparse.ArgumentParser(
|
|
258
|
+
description='Convert a COCO database to labelme annotation format')
|
|
259
|
+
|
|
260
|
+
parser.add_argument(
|
|
261
|
+
'coco_file',
|
|
262
|
+
type=str,
|
|
263
|
+
help='Path to COCO data file (.json)')
|
|
264
|
+
|
|
265
|
+
parser.add_argument(
|
|
266
|
+
'image_base',
|
|
267
|
+
type=str,
|
|
268
|
+
help='Path to images (also the output folder)')
|
|
269
|
+
|
|
270
|
+
parser.add_argument(
|
|
271
|
+
'--overwrite',
|
|
272
|
+
action='store_true',
|
|
273
|
+
help='Overwrite existing labelme .json files')
|
|
274
|
+
|
|
275
|
+
if len(sys.argv[1:]) == 0:
|
|
276
|
+
parser.print_help()
|
|
277
|
+
parser.exit()
|
|
278
|
+
|
|
279
|
+
args = parser.parse_args()
|
|
280
|
+
|
|
281
|
+
coco_to_labelme(coco_data=args.coco_file,image_base=args.image_base,overwrite=args.overwrite)
|
|
282
|
+
|
|
283
|
+
if __name__ == '__main__':
|
|
284
|
+
main()
|