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.
- 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 +701 -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 +563 -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 +192 -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 +665 -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 +984 -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 +2172 -0
- megadetector/detection/run_inference_with_yolov5_val.py +1314 -0
- megadetector/detection/run_md_and_speciesnet.py +1604 -0
- megadetector/detection/run_tiled_inference.py +1044 -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 +1943 -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 +2140 -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 +211 -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 +231 -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 +2872 -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 +1766 -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 +1973 -0
- megadetector/visualization/visualize_db.py +630 -0
- megadetector/visualization/visualize_detector_output.py +498 -0
- megadetector/visualization/visualize_video_output.py +705 -0
- megadetector-10.0.15.dist-info/METADATA +115 -0
- megadetector-10.0.15.dist-info/RECORD +147 -0
- megadetector-10.0.15.dist-info/WHEEL +5 -0
- megadetector-10.0.15.dist-info/licenses/LICENSE +19 -0
- megadetector-10.0.15.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
add_max_conf.py
|
|
4
|
+
|
|
5
|
+
The MD output format included a "max_detection_conf" field with each image
|
|
6
|
+
up to and including version 1.2; it was removed as of version 1.3 (it's
|
|
7
|
+
redundant with the individual detection confidence values).
|
|
8
|
+
|
|
9
|
+
Just in case someone took a dependency on that field, this script allows you
|
|
10
|
+
to add it back to an existing .json file.
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
#%% Imports and constants
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import json
|
|
18
|
+
import sys
|
|
19
|
+
import argparse
|
|
20
|
+
|
|
21
|
+
from megadetector.utils.ct_utils import get_max_conf
|
|
22
|
+
from megadetector.utils.ct_utils import write_json
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
#%% Main function
|
|
26
|
+
|
|
27
|
+
def add_max_conf(input_file,output_file):
|
|
28
|
+
"""
|
|
29
|
+
Add maximum confidence values to [input_file] and write the results to [output_file].
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
input_file (str): MD-formatted .json file to which we should add maxconf values
|
|
33
|
+
output_file (str): output .json file
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
assert os.path.isfile(input_file), "Can't find input file {}".format(input_file)
|
|
37
|
+
|
|
38
|
+
with open(input_file,'r') as f:
|
|
39
|
+
d = json.load(f)
|
|
40
|
+
|
|
41
|
+
for im in d['images']:
|
|
42
|
+
|
|
43
|
+
max_conf = get_max_conf(im)
|
|
44
|
+
|
|
45
|
+
if 'max_detection_conf' in im:
|
|
46
|
+
assert abs(max_conf - im['max_detection_conf']) < 0.00001
|
|
47
|
+
else:
|
|
48
|
+
im['max_detection_conf'] = max_conf
|
|
49
|
+
|
|
50
|
+
write_json(output_file,d)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
#%% Driver
|
|
54
|
+
|
|
55
|
+
def main(): # noqa
|
|
56
|
+
|
|
57
|
+
parser = argparse.ArgumentParser()
|
|
58
|
+
parser.add_argument('input_file',type=str,
|
|
59
|
+
help='Input .json file')
|
|
60
|
+
parser.add_argument('output_file',type=str,
|
|
61
|
+
help='Output .json file')
|
|
62
|
+
|
|
63
|
+
if len(sys.argv[1:]) == 0:
|
|
64
|
+
parser.print_help()
|
|
65
|
+
parser.exit()
|
|
66
|
+
|
|
67
|
+
args = parser.parse_args()
|
|
68
|
+
add_max_conf(args.input_file, args.output_file)
|
|
69
|
+
|
|
70
|
+
if __name__ == '__main__':
|
|
71
|
+
main()
|
|
72
|
+
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
categorize_detections_by_size.py
|
|
4
|
+
|
|
5
|
+
Given a MegaDetector .json file, creates a separate category for bounding boxes
|
|
6
|
+
above one or more size thresholds.
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
#%% Constants and imports
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
from collections import defaultdict
|
|
15
|
+
from tqdm import tqdm
|
|
16
|
+
|
|
17
|
+
from megadetector.utils.ct_utils import write_json
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
#%% Support classes
|
|
21
|
+
|
|
22
|
+
class SizeCategorizationOptions:
|
|
23
|
+
"""
|
|
24
|
+
Options used to parameterize categorize_detections_by_size().
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
|
|
29
|
+
#: Thresholds to use for separation, as a fraction of the image size.
|
|
30
|
+
#:
|
|
31
|
+
#: Should be sorted from smallest to largest.
|
|
32
|
+
self.size_thresholds = [0.95]
|
|
33
|
+
|
|
34
|
+
#: List of category numbers to use in separation; uses all categories if None
|
|
35
|
+
self.categories_to_separate = None
|
|
36
|
+
|
|
37
|
+
#: Dimension to use for thresholding; can be "size", "width", or "height"
|
|
38
|
+
self.measurement = 'size'
|
|
39
|
+
|
|
40
|
+
#: Categories to assign to thresholded ranges; should have the same length as
|
|
41
|
+
#: "size_thresholds".
|
|
42
|
+
self.size_category_names = ['large_detection']
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
#%% Main functions
|
|
46
|
+
|
|
47
|
+
def categorize_detections_by_size(input_file,output_file=None,options=None):
|
|
48
|
+
"""
|
|
49
|
+
Given a MegaDetector .json file, creates a separate category for bounding boxes
|
|
50
|
+
above one or more size thresholds, optionally writing results to [output_file].
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
input_file (str): file to process
|
|
54
|
+
output_file (str, optional): optional output file
|
|
55
|
+
options (SizeCategorizationOptions, optional): categorization parameters
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
dict: data loaded from [input_file], with the new size-based categories.
|
|
59
|
+
Identical to what's written to [output_file], if [output_file] is not None.
|
|
60
|
+
"""
|
|
61
|
+
if options is None:
|
|
62
|
+
options = SizeCategorizationOptions()
|
|
63
|
+
|
|
64
|
+
if options.categories_to_separate is not None:
|
|
65
|
+
options.categories_to_separate = \
|
|
66
|
+
[str(c) for c in options.categories_to_separate]
|
|
67
|
+
|
|
68
|
+
assert len(options.size_thresholds) == len(options.size_category_names), \
|
|
69
|
+
'Options struct should have the same number of category names and size thresholds'
|
|
70
|
+
|
|
71
|
+
# Sort size thresholds and names from largest to smallest
|
|
72
|
+
options.size_category_names = [x for _,x in sorted(zip(options.size_thresholds, # noqa
|
|
73
|
+
options.size_category_names),reverse=True)]
|
|
74
|
+
options.size_thresholds = sorted(options.size_thresholds,reverse=True)
|
|
75
|
+
|
|
76
|
+
with open(input_file) as f:
|
|
77
|
+
data = json.load(f)
|
|
78
|
+
|
|
79
|
+
detection_categories = data['detection_categories']
|
|
80
|
+
category_keys = list(detection_categories.keys())
|
|
81
|
+
category_keys = [int(k) for k in category_keys]
|
|
82
|
+
max_key = max(category_keys)
|
|
83
|
+
|
|
84
|
+
threshold_to_category_id = {}
|
|
85
|
+
for i_threshold,threshold in enumerate(options.size_thresholds):
|
|
86
|
+
|
|
87
|
+
category_id = str(max_key+1)
|
|
88
|
+
max_key += 1
|
|
89
|
+
detection_categories[category_id] = options.size_category_names[i_threshold]
|
|
90
|
+
threshold_to_category_id[i_threshold] = category_id
|
|
91
|
+
|
|
92
|
+
print('Creating category for {} with ID {}'.format(
|
|
93
|
+
options.size_category_names[i_threshold],category_id))
|
|
94
|
+
|
|
95
|
+
images = data['images']
|
|
96
|
+
|
|
97
|
+
print('Loaded {} images'.format(len(images)))
|
|
98
|
+
|
|
99
|
+
# For each image...
|
|
100
|
+
#
|
|
101
|
+
# im = images[0]
|
|
102
|
+
|
|
103
|
+
category_id_to_count = defaultdict(int)
|
|
104
|
+
|
|
105
|
+
for im in tqdm(images):
|
|
106
|
+
|
|
107
|
+
if im['detections'] is None:
|
|
108
|
+
assert im['failure'] is not None and len(im['failure']) > 0
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
# d = im['detections'][0]
|
|
112
|
+
for d in im['detections']:
|
|
113
|
+
|
|
114
|
+
# Are there really any detections here?
|
|
115
|
+
if (d is None) or ('bbox' not in d) or (d['bbox'] is None):
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
# Is this a category we're supposed to process?
|
|
119
|
+
if (options.categories_to_separate is not None) and \
|
|
120
|
+
(d['category'] not in options.categories_to_separate):
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
# https://github.com/agentmorris/MegaDetector/tree/main/megadetector/api/batch_processing#detector-outputs
|
|
124
|
+
w = d['bbox'][2]
|
|
125
|
+
h = d['bbox'][3]
|
|
126
|
+
detection_size = w*h
|
|
127
|
+
|
|
128
|
+
metric = None
|
|
129
|
+
|
|
130
|
+
if options.measurement == 'size':
|
|
131
|
+
metric = detection_size
|
|
132
|
+
elif options.measurement == 'width':
|
|
133
|
+
metric = w
|
|
134
|
+
else:
|
|
135
|
+
assert options.measurement == 'height', 'Unrecognized measurement metric'
|
|
136
|
+
metric = h
|
|
137
|
+
assert metric is not None
|
|
138
|
+
|
|
139
|
+
for i_threshold,threshold in enumerate(options.size_thresholds):
|
|
140
|
+
|
|
141
|
+
if metric >= threshold:
|
|
142
|
+
|
|
143
|
+
category_id = threshold_to_category_id[i_threshold]
|
|
144
|
+
|
|
145
|
+
category_id_to_count[category_id] += 1
|
|
146
|
+
d['category'] = category_id
|
|
147
|
+
|
|
148
|
+
break
|
|
149
|
+
|
|
150
|
+
# ...for each threshold
|
|
151
|
+
# ...for each detection
|
|
152
|
+
|
|
153
|
+
# ...for each image
|
|
154
|
+
|
|
155
|
+
for i_threshold in range(0,len(options.size_thresholds)):
|
|
156
|
+
category_name = options.size_category_names[i_threshold]
|
|
157
|
+
category_id = threshold_to_category_id[i_threshold]
|
|
158
|
+
category_count = category_id_to_count[category_id]
|
|
159
|
+
print('Found {} detections in category {}'.format(category_count,category_name))
|
|
160
|
+
|
|
161
|
+
if output_file is not None:
|
|
162
|
+
write_json(output_file,data)
|
|
163
|
+
|
|
164
|
+
return data
|
|
165
|
+
|
|
166
|
+
# ...def categorize_detections_by_size()
|