megadetector 5.0.2__py3-none-any.whl → 5.0.4__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.
- api/batch_processing/postprocessing/md_to_labelme.py +67 -38
- classification/merge_classification_detection_output.py +1 -1
- data_management/importers/cacophony-thermal-importer.py +1 -1
- detection/process_video.py +1 -1
- detection/pytorch_detector.py +25 -7
- detection/run_detector.py +69 -1
- detection/run_detector_batch.py +8 -1
- md_utils/url_utils.py +4 -3
- md_visualization/visualization_utils.py +1 -1
- megadetector-5.0.4.dist-info/METADATA +141 -0
- {megadetector-5.0.2.dist-info → megadetector-5.0.4.dist-info}/RECORD +14 -14
- megadetector-5.0.2.dist-info/METADATA +0 -295
- {megadetector-5.0.2.dist-info → megadetector-5.0.4.dist-info}/LICENSE +0 -0
- {megadetector-5.0.2.dist-info → megadetector-5.0.4.dist-info}/WHEEL +0 -0
- {megadetector-5.0.2.dist-info → megadetector-5.0.4.dist-info}/top_level.txt +0 -0
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# md_to_labelme.py
|
|
4
4
|
#
|
|
5
5
|
# "Converts" a MegaDetector output .json file to labelme format (one .json per image
|
|
6
|
-
# file). "Convert" is in quotes because this is an opinionated transformation
|
|
7
|
-
# confidence threshold.
|
|
6
|
+
# file). "Convert" is in quotes because this is an opinionated transformation that
|
|
7
|
+
# requires a confidence threshold.
|
|
8
8
|
#
|
|
9
9
|
# TODO:
|
|
10
10
|
#
|
|
@@ -24,13 +24,65 @@ from md_visualization.visualization_utils import open_image
|
|
|
24
24
|
from md_utils.ct_utils import truncate_float
|
|
25
25
|
|
|
26
26
|
output_precision = 3
|
|
27
|
+
default_confidence_threshold = 0.15
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
#%% Functions
|
|
30
31
|
|
|
31
|
-
def
|
|
32
|
+
def get_labelme_dict_for_image(im,image_base_name,category_id_to_name,info=None,confidence_threshold=None):
|
|
33
|
+
"""
|
|
34
|
+
For the given image struct in MD results format, reformat the detections into
|
|
35
|
+
labelme format. Returns a dict.
|
|
36
|
+
"""
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
if confidence_threshold is None:
|
|
39
|
+
confidence_threshold = -1.0
|
|
40
|
+
|
|
41
|
+
output_dict = {}
|
|
42
|
+
if info is not None:
|
|
43
|
+
output_dict['md_info'] = info
|
|
44
|
+
output_dict['version'] = '5.3.0a0'
|
|
45
|
+
output_dict['flags'] = {}
|
|
46
|
+
output_dict['shapes'] = []
|
|
47
|
+
output_dict['imagePath'] = image_base_name
|
|
48
|
+
output_dict['imageHeight'] = im['height']
|
|
49
|
+
output_dict['imageWidth'] = im['width']
|
|
50
|
+
output_dict['imageData'] = None
|
|
51
|
+
|
|
52
|
+
for det in im['detections']:
|
|
53
|
+
|
|
54
|
+
if det['conf'] < confidence_threshold:
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
shape = {}
|
|
58
|
+
shape['conf'] = det['conf']
|
|
59
|
+
shape['label'] = category_id_to_name[det['category']]
|
|
60
|
+
shape['shape_type'] = 'rectangle'
|
|
61
|
+
shape['description'] = ''
|
|
62
|
+
shape['group_id'] = None
|
|
63
|
+
|
|
64
|
+
# MD boxes are [x_min, y_min, width_of_box, height_of_box] (relative)
|
|
65
|
+
#
|
|
66
|
+
# labelme boxes are [[x0,y0],[x1,y1]] (absolute)
|
|
67
|
+
x0 = truncate_float(det['bbox'][0] * im['width'],output_precision)
|
|
68
|
+
y0 = truncate_float(det['bbox'][1] * im['height'],output_precision)
|
|
69
|
+
x1 = truncate_float(x0 + det['bbox'][2] * im['width'],output_precision)
|
|
70
|
+
y1 = truncate_float(y0 + det['bbox'][3] * im['height'],output_precision)
|
|
71
|
+
shape['points'] = [[x0,y0],[x1,y1]]
|
|
72
|
+
output_dict['shapes'].append(shape)
|
|
73
|
+
|
|
74
|
+
# ...for each detection
|
|
75
|
+
|
|
76
|
+
return output_dict
|
|
77
|
+
|
|
78
|
+
# ...def get_labelme_dict_for_image()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def md_to_labelme(results_file,image_base,confidence_threshold=None,overwrite=False):
|
|
82
|
+
"""
|
|
83
|
+
For all the images in [results_file], write a .json file in labelme format alongside the
|
|
84
|
+
corresponding relative path within image_base.
|
|
85
|
+
"""
|
|
34
86
|
|
|
35
87
|
# Load MD results
|
|
36
88
|
with open(results_file,'r') as f:
|
|
@@ -57,45 +109,20 @@ def md_to_labelme(results_file,image_base,confidence_threshold,overwrite=False):
|
|
|
57
109
|
print('Skipping existing file {}'.format(json_path))
|
|
58
110
|
continue
|
|
59
111
|
|
|
60
|
-
output_dict =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
output_dict['imagePath'] = os.path.basename(im_full_path)
|
|
66
|
-
output_dict['imageHeight'] = im['height']
|
|
67
|
-
output_dict['imageWidth'] = im['width']
|
|
68
|
-
output_dict['imageData'] = None
|
|
69
|
-
|
|
70
|
-
for det in im['detections']:
|
|
71
|
-
|
|
72
|
-
if det['conf'] < confidence_threshold:
|
|
73
|
-
continue
|
|
74
|
-
|
|
75
|
-
shape = {}
|
|
76
|
-
shape['conf'] = det['conf']
|
|
77
|
-
shape['label'] = md_results['detection_categories'][det['category']]
|
|
78
|
-
shape['shape_type'] = 'rectangle'
|
|
79
|
-
shape['description'] = ''
|
|
80
|
-
shape['group_id'] = None
|
|
81
|
-
|
|
82
|
-
# MD boxes are [x_min, y_min, width_of_box, height_of_box] (relative)
|
|
83
|
-
#
|
|
84
|
-
# labelme boxes are [[x0,y0],[x1,y1]] (absolute)
|
|
85
|
-
x0 = truncate_float(det['bbox'][0] * im['width'],output_precision)
|
|
86
|
-
y0 = truncate_float(det['bbox'][1] * im['height'],output_precision)
|
|
87
|
-
x1 = truncate_float(x0 + det['bbox'][2] * im['width'],output_precision)
|
|
88
|
-
y1 = truncate_float(y0 + det['bbox'][3] * im['height'],output_precision)
|
|
89
|
-
shape['points'] = [[x0,y0],[x1,y1]]
|
|
90
|
-
output_dict['shapes'].append(shape)
|
|
91
|
-
|
|
92
|
-
# ...for each detection
|
|
112
|
+
output_dict = get_labelme_dict_for_image(im,
|
|
113
|
+
image_base_name=os.path.basename(im_full_path),
|
|
114
|
+
category_id_to_name=md_results['detection_categories'],
|
|
115
|
+
info=md_results['info'],
|
|
116
|
+
confidence_threshold=confidence_threshold)
|
|
93
117
|
|
|
94
118
|
with open(json_path,'w') as f:
|
|
95
119
|
json.dump(output_dict,f,indent=1)
|
|
96
120
|
|
|
97
121
|
# ...for each image
|
|
98
122
|
|
|
123
|
+
# ...def md_to_labelme()
|
|
124
|
+
|
|
125
|
+
|
|
99
126
|
#%% Interactive driver
|
|
100
127
|
|
|
101
128
|
if False:
|
|
@@ -131,7 +158,9 @@ def main():
|
|
|
131
158
|
parser.add_argument(
|
|
132
159
|
'confidence_threshold',
|
|
133
160
|
type=float,
|
|
134
|
-
|
|
161
|
+
default=default_confidence_threshold,
|
|
162
|
+
help='Confidence threshold (default {})'.format(default_confidence_threshold)
|
|
163
|
+
)
|
|
135
164
|
|
|
136
165
|
parser.add_argument(
|
|
137
166
|
'--overwrite',
|
|
@@ -484,7 +484,7 @@ def process_file(fn_relative,verbose=False):
|
|
|
484
484
|
if tag['label'] in tag_mappings:
|
|
485
485
|
tag['label'] = tag_mappings[tag['label']]
|
|
486
486
|
|
|
487
|
-
# Discard tags below the
|
|
487
|
+
# Discard tags below the minimum confidence
|
|
488
488
|
if tag['confidence'] >= confidence_threshold:
|
|
489
489
|
valid_tags.append(tag)
|
|
490
490
|
else:
|
detection/process_video.py
CHANGED
|
@@ -103,7 +103,7 @@ def process_video(options):
|
|
|
103
103
|
# TODO:
|
|
104
104
|
#
|
|
105
105
|
# This is a lazy fix to an issue... if multiple users run this script, the
|
|
106
|
-
# "process_camera_trap_video" is owned by the first person who creates it, and others
|
|
106
|
+
# "process_camera_trap_video" folder is owned by the first person who creates it, and others
|
|
107
107
|
# can't write to it. I could create uniquely-named folders, but I philosophically prefer
|
|
108
108
|
# to put all the individual UUID-named folders within a larger folder, so as to be a
|
|
109
109
|
# good tempdir citizen. So, the lazy fix is to make this world-writable.
|
detection/pytorch_detector.py
CHANGED
|
@@ -40,7 +40,8 @@ if try_yolov5_import and not utils_imported:
|
|
|
40
40
|
utils_imported = True
|
|
41
41
|
print('Imported YOLOv5 from YOLOv5 package')
|
|
42
42
|
except Exception:
|
|
43
|
-
print('YOLOv5 module import failed, falling back to path-based import')
|
|
43
|
+
# print('YOLOv5 module import failed, falling back to path-based import')
|
|
44
|
+
pass
|
|
44
45
|
|
|
45
46
|
# If we haven't succeeded yet, import from the ultralytics package
|
|
46
47
|
if try_ultralytics_import and not utils_imported:
|
|
@@ -59,7 +60,8 @@ if try_ultralytics_import and not utils_imported:
|
|
|
59
60
|
utils_imported = True
|
|
60
61
|
print('Imported YOLOv5 from ultralytics package')
|
|
61
62
|
except Exception:
|
|
62
|
-
print('Ultralytics module import failed, falling back to yolov5 import')
|
|
63
|
+
# print('Ultralytics module import failed, falling back to yolov5 import')
|
|
64
|
+
pass
|
|
63
65
|
|
|
64
66
|
# If we haven't succeeded yet, import from the YOLOv5 repo
|
|
65
67
|
if not utils_imported:
|
|
@@ -83,7 +85,7 @@ assert utils_imported, 'YOLOv5 import error'
|
|
|
83
85
|
|
|
84
86
|
print(f'Using PyTorch version {torch.__version__}')
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
|
|
87
89
|
#%% Classes
|
|
88
90
|
|
|
89
91
|
class PTDetector:
|
|
@@ -114,7 +116,19 @@ class PTDetector:
|
|
|
114
116
|
|
|
115
117
|
@staticmethod
|
|
116
118
|
def _load_model(model_pt_path, device):
|
|
117
|
-
|
|
119
|
+
|
|
120
|
+
# There are two very slightly different ways to load the model, (1) using the
|
|
121
|
+
# map_location=device parameter to torch.load and (2) calling .to(device) after
|
|
122
|
+
# loading the model. The former is what we did for a zillion years, but is not
|
|
123
|
+
# supported on Apple silicon at of 2029.09. Switching to the latter causes
|
|
124
|
+
# very slight changes to the output, which always make me nervous, so I'm not
|
|
125
|
+
# doing a wholesale swap just yet. Instead, we'll just do this on M1 hardware.
|
|
126
|
+
use_map_location = (device != 'mps')
|
|
127
|
+
|
|
128
|
+
if use_map_location:
|
|
129
|
+
checkpoint = torch.load(model_pt_path, map_location=device)
|
|
130
|
+
else:
|
|
131
|
+
checkpoint = torch.load(model_pt_path)
|
|
118
132
|
|
|
119
133
|
# Compatibility fix that allows us to load older YOLOv5 models with
|
|
120
134
|
# newer versions of YOLOv5/PT
|
|
@@ -122,12 +136,16 @@ class PTDetector:
|
|
|
122
136
|
t = type(m)
|
|
123
137
|
if t is torch.nn.Upsample and not hasattr(m, 'recompute_scale_factor'):
|
|
124
138
|
m.recompute_scale_factor = None
|
|
139
|
+
|
|
140
|
+
if use_map_location:
|
|
141
|
+
model = checkpoint['model'].float().fuse().eval()
|
|
142
|
+
else:
|
|
143
|
+
model = checkpoint['model'].float().fuse().eval().to(device)
|
|
125
144
|
|
|
126
|
-
model = checkpoint['model'].float().fuse().eval() # FP32 model
|
|
127
145
|
return model
|
|
128
146
|
|
|
129
|
-
def generate_detections_one_image(self, img_original, image_id,
|
|
130
|
-
detection_threshold, image_size=None,
|
|
147
|
+
def generate_detections_one_image(self, img_original, image_id='unknown',
|
|
148
|
+
detection_threshold=0.00001, image_size=None,
|
|
131
149
|
skip_image_resizing=False):
|
|
132
150
|
"""
|
|
133
151
|
Apply the detector to an image.
|
detection/run_detector.py
CHANGED
|
@@ -127,6 +127,15 @@ DEFAULT_BOX_EXPANSION = 0
|
|
|
127
127
|
DEFAULT_LABEL_FONT_SIZE = 16
|
|
128
128
|
DETECTION_FILENAME_INSERT = '_detections'
|
|
129
129
|
|
|
130
|
+
# The model filenames "MDV5A", "MDV5B", and "MDV4" are special; they will trigger an
|
|
131
|
+
# automatic model download to the system temp folder, or they will use the paths specified in the
|
|
132
|
+
# $MDV4, $MDV5A, or $MDV5B environment variables if they exist.
|
|
133
|
+
downloadable_models = {
|
|
134
|
+
'MDV4':'https://github.com/agentmorris/MegaDetector/releases/download/v4.1/md_v4.1.0.pb',
|
|
135
|
+
'MDV5A':'https://github.com/agentmorris/MegaDetector/releases/download/v5.0/md_v5a.0.0.pt',
|
|
136
|
+
'MDV5B':'https://github.com/agentmorris/MegaDetector/releases/download/v5.0/md_v5b.0.0.pt'
|
|
137
|
+
}
|
|
138
|
+
|
|
130
139
|
|
|
131
140
|
#%% Utility functions
|
|
132
141
|
|
|
@@ -257,6 +266,9 @@ def load_detector(model_file, force_cpu=False):
|
|
|
257
266
|
Load a TF or PT detector, depending on the extension of model_file.
|
|
258
267
|
"""
|
|
259
268
|
|
|
269
|
+
# Possibly automatically download the model
|
|
270
|
+
model_file = try_download_known_detector(model_file)
|
|
271
|
+
|
|
260
272
|
start_time = time.time()
|
|
261
273
|
if model_file.endswith('.pb'):
|
|
262
274
|
from detection.tf_detector import TFDetector
|
|
@@ -290,6 +302,9 @@ def load_and_run_detector(model_file, image_file_names, output_dir,
|
|
|
290
302
|
print('Warning: no files available')
|
|
291
303
|
return
|
|
292
304
|
|
|
305
|
+
# Possibly automatically download the model
|
|
306
|
+
model_file = try_download_known_detector(model_file)
|
|
307
|
+
|
|
293
308
|
print('GPU available: {}'.format(is_gpu_available(model_file)))
|
|
294
309
|
|
|
295
310
|
detector = load_detector(model_file)
|
|
@@ -429,6 +444,55 @@ def load_and_run_detector(model_file, image_file_names, output_dir,
|
|
|
429
444
|
# ...def load_and_run_detector()
|
|
430
445
|
|
|
431
446
|
|
|
447
|
+
def download_model(model_name,force_download=False):
|
|
448
|
+
"""
|
|
449
|
+
Download one of the known models to local temp space if it hasn't already been downloaded
|
|
450
|
+
"""
|
|
451
|
+
|
|
452
|
+
import tempfile
|
|
453
|
+
from md_utils.url_utils import download_url
|
|
454
|
+
model_tempdir = os.path.join(tempfile.gettempdir(), 'megadetector_models')
|
|
455
|
+
os.makedirs(model_tempdir,exist_ok=True)
|
|
456
|
+
|
|
457
|
+
# This is a lazy fix to an issue... if multiple users run this script, the
|
|
458
|
+
# "megadetector_models" folder is owned by the first person who creates it, and others
|
|
459
|
+
# can't write to it. I could create uniquely-named folders, but I philosophically prefer
|
|
460
|
+
# to put all the individual UUID-named folders within a larger folder, so as to be a
|
|
461
|
+
# good tempdir citizen. So, the lazy fix is to make this world-writable.
|
|
462
|
+
try:
|
|
463
|
+
os.chmod(model_tempdir,0o777)
|
|
464
|
+
except Exception:
|
|
465
|
+
pass
|
|
466
|
+
if model_name not in downloadable_models:
|
|
467
|
+
print('Unrecognized downloadable model {}'.format(model_name))
|
|
468
|
+
return None
|
|
469
|
+
url = downloadable_models[model_name]
|
|
470
|
+
destination_filename = os.path.join(model_tempdir,url.split('/')[-1])
|
|
471
|
+
local_file = download_url(url, destination_filename=destination_filename, progress_updater=None,
|
|
472
|
+
force_download=force_download, verbose=True)
|
|
473
|
+
return local_file
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def try_download_known_detector(detector_file):
|
|
477
|
+
"""
|
|
478
|
+
Check whether detector_file is really the name of a known model, in which case we will
|
|
479
|
+
either read the actual filename from the corresponding environment variable or download
|
|
480
|
+
(if necessary) to local temp space. Otherwise just returns the input string.
|
|
481
|
+
"""
|
|
482
|
+
|
|
483
|
+
if detector_file in downloadable_models:
|
|
484
|
+
if detector_file in os.environ:
|
|
485
|
+
fn = os.environ[detector_file]
|
|
486
|
+
print('Reading MD location from environment variable {}: {}'.format(
|
|
487
|
+
detector_file,fn))
|
|
488
|
+
detector_file = fn
|
|
489
|
+
else:
|
|
490
|
+
print('Downloading model {}'.format(detector_file))
|
|
491
|
+
detector_file = download_model(detector_file)
|
|
492
|
+
return detector_file
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
432
496
|
#%% Command-line driver
|
|
433
497
|
|
|
434
498
|
def main():
|
|
@@ -438,7 +502,7 @@ def main():
|
|
|
438
502
|
|
|
439
503
|
parser.add_argument(
|
|
440
504
|
'detector_file',
|
|
441
|
-
help='Path
|
|
505
|
+
help='Path detector model file (.pb or .pt). Can also be MDV4, MDV5A, or MDV5B to request automatic download.')
|
|
442
506
|
|
|
443
507
|
# Must specify either an image file or a directory
|
|
444
508
|
group = parser.add_mutually_exclusive_group(required=True)
|
|
@@ -506,6 +570,10 @@ def main():
|
|
|
506
570
|
|
|
507
571
|
args = parser.parse_args()
|
|
508
572
|
|
|
573
|
+
# If the specified detector file is really the name of a known model, find
|
|
574
|
+
# (and possibly download) that model
|
|
575
|
+
args.detector_file = try_download_known_detector(args.detector_file)
|
|
576
|
+
|
|
509
577
|
assert os.path.exists(args.detector_file), 'detector file {} does not exist'.format(
|
|
510
578
|
args.detector_file)
|
|
511
579
|
assert 0.0 < args.threshold <= 1.0, 'Confidence threshold needs to be between 0 and 1'
|
detection/run_detector_batch.py
CHANGED
|
@@ -64,6 +64,7 @@ from multiprocessing.pool import Pool as workerpool
|
|
|
64
64
|
import detection.run_detector as run_detector
|
|
65
65
|
from detection.run_detector import is_gpu_available,\
|
|
66
66
|
load_detector,\
|
|
67
|
+
try_download_known_detector,\
|
|
67
68
|
get_detector_version_from_filename,\
|
|
68
69
|
get_detector_metadata_from_version_string
|
|
69
70
|
|
|
@@ -413,6 +414,8 @@ def load_and_run_detector_batch(model_file, image_file_names, checkpoint_path=No
|
|
|
413
414
|
|
|
414
415
|
already_processed = set([i['file'] for i in results])
|
|
415
416
|
|
|
417
|
+
model_file = try_download_known_detector(model_file)
|
|
418
|
+
|
|
416
419
|
print('GPU available: {}'.format(is_gpu_available(model_file)))
|
|
417
420
|
|
|
418
421
|
if n_cores > 1 and is_gpu_available(model_file):
|
|
@@ -743,7 +746,7 @@ def main():
|
|
|
743
746
|
description='Module to run a TF/PT animal detection model on lots of images')
|
|
744
747
|
parser.add_argument(
|
|
745
748
|
'detector_file',
|
|
746
|
-
help='Path to detector model file (.pb or .pt)')
|
|
749
|
+
help='Path to detector model file (.pb or .pt). Can also be MDV4, MDV5A, or MDV5B to request automatic download.')
|
|
747
750
|
parser.add_argument(
|
|
748
751
|
'image_file',
|
|
749
752
|
help='Path to a single image file, a JSON file containing a list of paths to images, or a directory')
|
|
@@ -838,6 +841,10 @@ def main():
|
|
|
838
841
|
|
|
839
842
|
args = parser.parse_args()
|
|
840
843
|
|
|
844
|
+
# If the specified detector file is really the name of a known model, find
|
|
845
|
+
# (and possibly download) that model
|
|
846
|
+
args.detector_file = try_download_known_detector(args.detector_file)
|
|
847
|
+
|
|
841
848
|
assert os.path.exists(args.detector_file), \
|
|
842
849
|
'detector file {} does not exist'.format(args.detector_file)
|
|
843
850
|
assert 0.0 < args.threshold <= 1.0, 'Confidence threshold needs to be between 0 and 1'
|
md_utils/url_utils.py
CHANGED
|
@@ -17,9 +17,6 @@ import requests
|
|
|
17
17
|
from tqdm import tqdm
|
|
18
18
|
from urllib.parse import urlparse
|
|
19
19
|
|
|
20
|
-
# pip install progressbar2
|
|
21
|
-
import progressbar
|
|
22
|
-
|
|
23
20
|
url_utils_temp_dir = None
|
|
24
21
|
max_path_len = 255
|
|
25
22
|
|
|
@@ -36,6 +33,10 @@ class DownloadProgressBar():
|
|
|
36
33
|
|
|
37
34
|
def __call__(self, block_num, block_size, total_size):
|
|
38
35
|
if not self.pbar:
|
|
36
|
+
# This is a pretty random import I'd rather not depend on outside of the
|
|
37
|
+
# rare case where it's used, so importing locally
|
|
38
|
+
# pip install progressbar2
|
|
39
|
+
import progressbar
|
|
39
40
|
self.pbar = progressbar.ProgressBar(max_value=total_size)
|
|
40
41
|
self.pbar.start()
|
|
41
42
|
|
|
@@ -160,7 +160,7 @@ def resize_image(image, target_width, target_height=-1):
|
|
|
160
160
|
# w = ar * h
|
|
161
161
|
target_width = int(aspect_ratio * target_height)
|
|
162
162
|
|
|
163
|
-
# This parameter changed between Pillow
|
|
163
|
+
# This parameter changed between Pillow versions 9 and 10, and for a bit, I'd like to
|
|
164
164
|
# support both.
|
|
165
165
|
try:
|
|
166
166
|
resized_image = image.resize((target_width, target_height), Image.ANTIALIAS)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: megadetector
|
|
3
|
+
Version: 5.0.4
|
|
4
|
+
Summary: MegaDetector is an AI model that helps conservation folks spend less time doing boring things with camera trap images.
|
|
5
|
+
Author-email: Your friendly neighborhood MegaDetector team <cameratraps@lila.science>
|
|
6
|
+
Maintainer-email: Your friendly neighborhood MegaDetector team <cameratraps@lila.science>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Project-URL: Homepage, https://github.com/agentmorris/MegaDetector
|
|
28
|
+
Project-URL: Bug Reports, https://github.com/agentmorris/MegaDetector/issues
|
|
29
|
+
Project-URL: Source, https://github.com/agentmorris/MegaDetector
|
|
30
|
+
Keywords: camera traps,conservation,wildlife,ai
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Requires-Python: >=3.9
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
License-File: LICENSE
|
|
37
|
+
Requires-Dist: Pillow >=9.5
|
|
38
|
+
Requires-Dist: tqdm >=4.64.0
|
|
39
|
+
Requires-Dist: jsonpickle >=3.0.2
|
|
40
|
+
Requires-Dist: humanfriendly >=10.0
|
|
41
|
+
Requires-Dist: numpy >=1.26.0
|
|
42
|
+
Requires-Dist: matplotlib >=3.8.0
|
|
43
|
+
Requires-Dist: opencv-python >=4.8.0
|
|
44
|
+
Requires-Dist: requests >=2.31.0
|
|
45
|
+
Requires-Dist: pyqtree >=1.0.0
|
|
46
|
+
Requires-Dist: seaborn >=0.12.2
|
|
47
|
+
Requires-Dist: scikit-learn >=1.3.1
|
|
48
|
+
Requires-Dist: pandas >=2.1.1
|
|
49
|
+
Requires-Dist: PyYAML >=6.0.1
|
|
50
|
+
Requires-Dist: torch >=2.0.1
|
|
51
|
+
Requires-Dist: torchvision >=0.15.2
|
|
52
|
+
Requires-Dist: yolov5 >=7.0.12
|
|
53
|
+
|
|
54
|
+
# MegaDetector
|
|
55
|
+
|
|
56
|
+
This package is a pip-installable version of the support/inference code for [MegaDetector](https://github.com/agentmorris/MegaDetector), an object detection model that helps conservation biologists spend less time doing boring things with camera trap images.
|
|
57
|
+
|
|
58
|
+
If you want to learn more about what MegaDetector is all about, head over to the [MegaDetector repo](https://github.com/agentmorris/MegaDetector).
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## Reasons you probably aren't looking for this package
|
|
62
|
+
|
|
63
|
+
### If you are an ecologist...
|
|
64
|
+
|
|
65
|
+
If you are an ecologist looking to use MegaDetector to help you get through your camera trap images, you probably don't want this package. We recommend starting with our "[Getting started with MegaDetector](https://github.com/agentmorris/MegaDetector/blob/main/collaborations.md)" page, then digging in to the [MegaDetector User Guide](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md), which will walk you through the process of using MegaDetector. That journey will <i>not</i> involve this package.
|
|
66
|
+
|
|
67
|
+
### If you are a computer-vision-y type...
|
|
68
|
+
|
|
69
|
+
If you are a computer-vision-y person looking to run or fine-tune MegaDetector programmatically, you still probably don't want this package. MegaDetector is just a fine-tuned version of [YOLOv5](https://github.com/ultralytics/yolov5), and the [ultralytics](https://github.com/ultralytics/ultralytics/) package (from the developers of YOLOv5) has a zillion bells and whistles for both inference and fine-tuning that this package doesn't.
|
|
70
|
+
|
|
71
|
+
## Reasons you might want to use this package
|
|
72
|
+
|
|
73
|
+
If you want to programatically interact with the postprocessing tools from the MegaDetector repo, or programmatically run MegaDetector in a way that produces [Timelapse](https://saul.cpsc.ucalgary.ca/timelapse)-friendly output (i.e., output in the standard [MegaDetector output format](https://github.com/agentmorris/MegaDetector/tree/main/api/batch_processing#megadetector-batch-output-format)), this package might be for you.
|
|
74
|
+
|
|
75
|
+
Although even if that describes you, you <i>still</i> might be better off cloning the MegaDetector repo. Pip-installability requires that some dependencies be newer than what was available at the time MDv5 was trained, so results are <i>very slightly</i> different than results produced in the "official" environment. These differences <i>probably</i> don't matter much, but they have not been formally characterized.
|
|
76
|
+
|
|
77
|
+
## If I haven't talked you out of using this package...
|
|
78
|
+
|
|
79
|
+
To install:
|
|
80
|
+
|
|
81
|
+
`pip install megadetector`
|
|
82
|
+
|
|
83
|
+
MegaDetector model weights aren't downloaded at pip-install time, but they will be (optionally) automatically downloaded the first time you run the model.
|
|
84
|
+
|
|
85
|
+
### Examples of things you can do with this package
|
|
86
|
+
|
|
87
|
+
#### Run MegaDetector on one image and count the number of detections
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
from md_utils import url_utils
|
|
91
|
+
from md_visualization import visualization_utils as vis_utils
|
|
92
|
+
from detection import run_detector
|
|
93
|
+
|
|
94
|
+
# This is the image at the bottom of this page, it has one animal in it
|
|
95
|
+
image_url = 'https://github.com/agentmorris/MegaDetector/raw/main/images/orinoquia-thumb-web.jpg'
|
|
96
|
+
temporary_filename = url_utils.download_url(image_url)
|
|
97
|
+
|
|
98
|
+
image = vis_utils.load_image(temporary_filename)
|
|
99
|
+
|
|
100
|
+
# This will automatically download MDv5a to the system temp folder;
|
|
101
|
+
# you can also specify a filename explicitly, or set the $MDV5A
|
|
102
|
+
# environment variable to point to the model file.
|
|
103
|
+
model = run_detector.load_detector('MDV5A')
|
|
104
|
+
|
|
105
|
+
result = model.generate_detections_one_image(image)
|
|
106
|
+
|
|
107
|
+
detections_above_threshold = [d for d in result['detections'] if d['conf'] > 0.2]
|
|
108
|
+
print('Found {} detection above threshold'.format(len(detections_above_threshold)))
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Run MegaDetector on a folder of images
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
from detection.run_detector_batch import load_and_run_detector_batch,write_results_to_file
|
|
115
|
+
from md_utils import path_utils
|
|
116
|
+
import os
|
|
117
|
+
|
|
118
|
+
# Pick a folder to run MD on recursively, and an output file
|
|
119
|
+
image_folder = os.path.expanduser('~/megadetector_test_images')
|
|
120
|
+
output_file = os.path.expanduser('~/megadetector_output_test.json')
|
|
121
|
+
|
|
122
|
+
# Recursively find images
|
|
123
|
+
image_file_names = path_utils.find_images(image_folder,recursive=True)
|
|
124
|
+
|
|
125
|
+
# This will automatically download MDv5a to the system temp folder;
|
|
126
|
+
# you can also specify a filename explicitly, or set the $MDV5A
|
|
127
|
+
# environment variable to point to the model file.
|
|
128
|
+
results = load_and_run_detector_batch('MDV5A', image_file_names)
|
|
129
|
+
|
|
130
|
+
# Write results as relative filenames, this is what Timelapse
|
|
131
|
+
# and other downstream tools expect.
|
|
132
|
+
write_results_to_file(results,output_file,relative_path_base=image_folder)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Contact
|
|
136
|
+
|
|
137
|
+
Contact <a href="cameratraps@lila.science">cameratraps@lila.science</a> with questions.
|
|
138
|
+
|
|
139
|
+
## Gratuitous animal picture
|
|
140
|
+
|
|
141
|
+
<img src="https://github.com/agentmorris/MegaDetector/raw/main/images/orinoquia-thumb-web_detections.jpg"><br/>Image credit University of Minnesota, from the [Orinoquía Camera Traps](http://lila.science/datasets/orinoquia-camera-traps/) data set.
|
|
@@ -22,7 +22,7 @@ api/batch_processing/postprocessing/compare_batch_results.py,sha256=EbaReSTVW3da
|
|
|
22
22
|
api/batch_processing/postprocessing/convert_output_format.py,sha256=jjRvXrM2tOb5HTtxb7XAcNsyphGhURfcZNCtNfCEA6g,12847
|
|
23
23
|
api/batch_processing/postprocessing/load_api_results.py,sha256=oLgUbQg_i3THmlMVKP9_F3yBeqVK_i_9H6b_8e9z64Y,7421
|
|
24
24
|
api/batch_processing/postprocessing/md_to_coco_starter_code.py,sha256=jnQpvMn2DQVoSh7ftQBHidYDrzFAv5XkO6psqTx0WFM,6747
|
|
25
|
-
api/batch_processing/postprocessing/md_to_labelme.py,sha256=
|
|
25
|
+
api/batch_processing/postprocessing/md_to_labelme.py,sha256=R5GznGW5U4IGzyWvo8FkpwmE-tGuCE4WLF2VI6Ve_e8,5202
|
|
26
26
|
api/batch_processing/postprocessing/merge_detections.py,sha256=B4QnqW9nvcEJpXzAK20TVB0t6L8c7PR5OjPy8FX-5Z8,15930
|
|
27
27
|
api/batch_processing/postprocessing/postprocess_batch_results.py,sha256=rnDhNj0R8E-1voECTVVwDyJ5TLEclc7Yuai-e7TSNv0,65782
|
|
28
28
|
api/batch_processing/postprocessing/separate_detections_into_folders.py,sha256=llaXxuOfeKehBa2rRwtvspJrWF-Z9HzqvTH1eS_dSgI,29546
|
|
@@ -47,7 +47,7 @@ classification/identify_mislabeled_candidates.py,sha256=pHB9U_7LFBeLyY1AngIAtbrn
|
|
|
47
47
|
classification/json_to_azcopy_list.py,sha256=o57wLHJPDrP9OPSY-3x81WI3mmcH1DyIOUh3VQmMwxg,1670
|
|
48
48
|
classification/json_validator.py,sha256=ZizcEPpW1J26p-oGyfvcffBy2voNRKCNXKF8NtxIt5A,26618
|
|
49
49
|
classification/map_classification_categories.py,sha256=2B4K-TdE77VNw8XG1h8X7CuUvw0JSIrALdy6a1FvkXw,10738
|
|
50
|
-
classification/merge_classification_detection_output.py,sha256=
|
|
50
|
+
classification/merge_classification_detection_output.py,sha256=2FDTauvkbMZ3putJH837Ux67HTGsCAnGCOXhnnqjt6g,20123
|
|
51
51
|
classification/prepare_classification_script.py,sha256=6BRxiEPSIl3nTVrZHE5qqUGDe_AxAEqnUg7sxMZSFMg,6141
|
|
52
52
|
classification/prepare_classification_script_mc.py,sha256=IMCsLyGL70cViVTH0eow0sYDM9E81AsBGrctNveXP10,7440
|
|
53
53
|
classification/run_classifier.py,sha256=eBpkZzP7TtrnwOIlc99fTpe1QocmDuERaIw9mXqwAWI,9363
|
|
@@ -81,7 +81,7 @@ data_management/importers/auckland_doc_test_to_json.py,sha256=09MS1_8ZLytlRC5MAc
|
|
|
81
81
|
data_management/importers/auckland_doc_to_json.py,sha256=Gcon1XAeNwDfubqCXBUI6BgMLMmchgyv8u9OUxF7mwI,5954
|
|
82
82
|
data_management/importers/awc_to_json.py,sha256=7L0Q1bRwnCtEvdvOizVah3MDfFtmnYMHKxBeWMDgelI,5298
|
|
83
83
|
data_management/importers/bellevue_to_json.py,sha256=RLEiZ-k7wrkIXfS4CpEfnHiilPwOmE6A9hfu7faXiY8,7900
|
|
84
|
-
data_management/importers/cacophony-thermal-importer.py,sha256=
|
|
84
|
+
data_management/importers/cacophony-thermal-importer.py,sha256=0Y21Hx8Y4dMvpUpbKKMDYb0r-AqFD2k8N0Bf9q75geY,28621
|
|
85
85
|
data_management/importers/carrizo_shrubfree_2018.py,sha256=giJuSMeTSerjvLjh8l_VzNwe_BCZNt92OdX8yNmRBUU,7811
|
|
86
86
|
data_management/importers/carrizo_trail_cam_2017.py,sha256=ChDV7sU2Dqx9x4-ZuId74HBijsPvUP5cEkQ5bu8AQIU,8814
|
|
87
87
|
data_management/importers/cct_field_adjustments.py,sha256=_T5pSy-7tKUml8lGFR8oW5T9fyUQvvt1aqZ3-0w_26s,1343
|
|
@@ -124,10 +124,10 @@ data_management/lila/generate_lila_per_image_labels.py,sha256=2dIQaVYTnyb5X_zfqQ
|
|
|
124
124
|
data_management/lila/get_lila_annotation_counts.py,sha256=YgLNLsdlCYFaY2hmdeD_fjBXflWskP1-oL5Z3Ew3kKo,5326
|
|
125
125
|
data_management/lila/get_lila_image_counts.py,sha256=r5p2wPL5vuKKO8DWia3Tll-EZZWFNUvax6ljaYtrKsk,3625
|
|
126
126
|
data_management/lila/lila_common.py,sha256=olg_eR6Ul2kUQ7tIsndzVIJpils5oXNANYSGBmS455E,8667
|
|
127
|
-
detection/process_video.py,sha256=
|
|
128
|
-
detection/pytorch_detector.py,sha256=
|
|
129
|
-
detection/run_detector.py,sha256=
|
|
130
|
-
detection/run_detector_batch.py,sha256=
|
|
127
|
+
detection/process_video.py,sha256=b2xcQThAdlgirumxynHULYLviCr_q5sCDfdkKEqVFyU,22089
|
|
128
|
+
detection/pytorch_detector.py,sha256=nI2xctI6FSdbWjSFHYlMT0LTH6CCATOe9DF-I8MLEpc,11505
|
|
129
|
+
detection/run_detector.py,sha256=LBveNOLE3AWSTcQ1MUbbWXaQIutr9e2vtz6RG2SjlWQ,23821
|
|
130
|
+
detection/run_detector_batch.py,sha256=vgwoj7gRUpeiwqkqWBDr5xTK8GIgXMBKwcB3dk5dqhw,40750
|
|
131
131
|
detection/run_inference_with_yolov5_val.py,sha256=yxMFxQQDvkydWVpM0ecopDXtPi89gaqMX0TKjyxNyjI,22118
|
|
132
132
|
detection/run_tiled_inference.py,sha256=cs1IehE2DXj8Nr3CbnYMXqwcFM1vUBT1Rm5We5nlcSM,28785
|
|
133
133
|
detection/tf_detector.py,sha256=xOO8kzd-Um2X_sAZyop524LM53nipv5pNx8YueGTJrc,6760
|
|
@@ -142,11 +142,11 @@ md_utils/path_utils.py,sha256=fdX-BnjDx811eFtEFrgn5VyIA4chPFdbc_z6OfUExXc,12364
|
|
|
142
142
|
md_utils/process_utils.py,sha256=_LMebsTQX2PFxERj0-LoC-XCua23RPw3heu-ckp0Tjo,3049
|
|
143
143
|
md_utils/sas_blob_utils.py,sha256=GpjHn33N2b-XeBAtU3xhGbTIYcBs4YrXHtbQDmlGFvY,16955
|
|
144
144
|
md_utils/string_utils.py,sha256=tFTC9TarPFGa7_UkKF0_t6Q2naH9IEsDVM2DOxwkFTQ,1277
|
|
145
|
-
md_utils/url_utils.py,sha256=
|
|
145
|
+
md_utils/url_utils.py,sha256=aFN7_WvzMJqYHL9t-SGCP2A0-mlYu1-P0HkZwgzUsKg,4598
|
|
146
146
|
md_utils/write_html_image_list.py,sha256=myXMdOwUERZWp9p2RPu8TcStCsu2X7aJNtcomlhoeqA,7573
|
|
147
147
|
md_visualization/plot_utils.py,sha256=Kb2tMAQICwBdDSgaOIZsZCGVs5MvYyDGjjI41S4okWc,10586
|
|
148
148
|
md_visualization/render_images_with_thumbnails.py,sha256=XJcL5qxu5pe2LQ4MqnD-O6dM_cPxGGNoqk5U_rZzFUQ,10391
|
|
149
|
-
md_visualization/visualization_utils.py,sha256=
|
|
149
|
+
md_visualization/visualization_utils.py,sha256=uHwimaXPy1TGqGOlJS5mzwzk2NNhE-y3PNrnfZUC4r0,30449
|
|
150
150
|
md_visualization/visualize_db.py,sha256=PelSZuL_E8olrsDXfHfH_61Iv3NvH2bxIak1VRHkqI4,18049
|
|
151
151
|
md_visualization/visualize_detector_output.py,sha256=JkZGhi_CrazgKzYOOtGT3fnGu1C5BgR__lXWGzaTVWQ,9897
|
|
152
152
|
md_visualization/visualize_incoming_annotations.py,sha256=kvssw9F3YtQyLpxRPtl7fGKLIrXuRqG4NA92zwu8a7s,6418
|
|
@@ -161,8 +161,8 @@ taxonomy_mapping/species_lookup.py,sha256=1QmQidwKnswjvdy0A2SgUn7D8-aQ-947jfc2i_
|
|
|
161
161
|
taxonomy_mapping/taxonomy_csv_checker.py,sha256=BdAkMCF9MgXMqDa9PKmjWqhymFf00csr2uA4jWFb86o,4691
|
|
162
162
|
taxonomy_mapping/taxonomy_graph.py,sha256=ZDm2enGanBlm8KXWvCndqmeerOp9LREaetSl-Lxy07s,12361
|
|
163
163
|
taxonomy_mapping/validate_lila_category_mappings.py,sha256=CApYVWIZ8TTJ3vvQTgfjIvWDGHpPo-Zn9jqJFaw3DNw,2314
|
|
164
|
-
megadetector-5.0.
|
|
165
|
-
megadetector-5.0.
|
|
166
|
-
megadetector-5.0.
|
|
167
|
-
megadetector-5.0.
|
|
168
|
-
megadetector-5.0.
|
|
164
|
+
megadetector-5.0.4.dist-info/LICENSE,sha256=RMa3qq-7Cyk7DdtqRj_bP1oInGFgjyHn9-PZ3PcrqIs,1100
|
|
165
|
+
megadetector-5.0.4.dist-info/METADATA,sha256=QkhiDNY4IJCYysfOealvw-0kcweBsEhsCdnpULuS0jQ,7560
|
|
166
|
+
megadetector-5.0.4.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
167
|
+
megadetector-5.0.4.dist-info/top_level.txt,sha256=-mFGpqnmviVz0Vyr2GxZ_kTo_PBPNoK6h4JtqIMjZGQ,88
|
|
168
|
+
megadetector-5.0.4.dist-info/RECORD,,
|
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: megadetector
|
|
3
|
-
Version: 5.0.2
|
|
4
|
-
Summary: MegaDetector is an AI model that helps conservation folks spend less time doing boring things with camera trap images.
|
|
5
|
-
Author-email: Your friendly neighborhood MegaDetector team <cameratraps@lila.science>
|
|
6
|
-
Maintainer-email: Your friendly neighborhood MegaDetector team <cameratraps@lila.science>
|
|
7
|
-
License: MIT License
|
|
8
|
-
|
|
9
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
-
in the Software without restriction, including without limitation the rights
|
|
12
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
-
furnished to do so, subject to the following conditions:
|
|
15
|
-
|
|
16
|
-
The above copyright notice and this permission notice shall be included in all
|
|
17
|
-
copies or substantial portions of the Software.
|
|
18
|
-
|
|
19
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
-
SOFTWARE.
|
|
26
|
-
|
|
27
|
-
Project-URL: Homepage, https://github.com/agentmorris/MegaDetector
|
|
28
|
-
Project-URL: Bug Reports, https://github.com/agentmorris/MegaDetector/issues
|
|
29
|
-
Project-URL: Source, https://github.com/agentmorris/MegaDetector
|
|
30
|
-
Keywords: camera traps,conservation,wildlife,ai
|
|
31
|
-
Classifier: Development Status :: 3 - Alpha
|
|
32
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
-
Classifier: Programming Language :: Python :: 3
|
|
34
|
-
Requires-Python: >=3.9
|
|
35
|
-
Description-Content-Type: text/markdown
|
|
36
|
-
License-File: LICENSE
|
|
37
|
-
Requires-Dist: Pillow
|
|
38
|
-
Requires-Dist: tqdm
|
|
39
|
-
Requires-Dist: jsonpickle
|
|
40
|
-
Requires-Dist: humanfriendly
|
|
41
|
-
Requires-Dist: numpy
|
|
42
|
-
Requires-Dist: matplotlib
|
|
43
|
-
Requires-Dist: opencv-python
|
|
44
|
-
Requires-Dist: requests
|
|
45
|
-
Requires-Dist: pyqtree
|
|
46
|
-
Requires-Dist: scikit-learn
|
|
47
|
-
Requires-Dist: pandas
|
|
48
|
-
Requires-Dist: seaborn
|
|
49
|
-
Requires-Dist: PyYAML
|
|
50
|
-
Requires-Dist: torch
|
|
51
|
-
Requires-Dist: torchvision
|
|
52
|
-
Requires-Dist: yolov5
|
|
53
|
-
|
|
54
|
-
# MegaDetector
|
|
55
|
-
|
|
56
|
-
...helping conservation biologists spend less time doing boring things with camera trap images.
|
|
57
|
-
|
|
58
|
-
## Table of contents
|
|
59
|
-
|
|
60
|
-
1. [Repo overview](#repo-overview)
|
|
61
|
-
2. [What's MegaDetector all about?](#whats-megadetector-all-about)
|
|
62
|
-
3. [How do I get started with MegaDetector?](#how-do-i-get-started-with-megadetector)
|
|
63
|
-
4. [Who is using MegaDetector?](#who-is-using-megadetector)
|
|
64
|
-
5. [Repo contents](#repo-contents)
|
|
65
|
-
6. [Contact](#contact)
|
|
66
|
-
7. [Gratuitous camera trap picture](#gratuitous-camera-trap-picture)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
## Repo overview
|
|
70
|
-
|
|
71
|
-
This repo contains the tools for training and running [MegaDetector](megadetector.md), an object detection model that does a pretty good job finding animals, people, and vehicles (and therefore is pretty good at finding empty images) in camera trap images in a variety of terrestrial ecosystems.
|
|
72
|
-
|
|
73
|
-
The core functionality provided is:
|
|
74
|
-
|
|
75
|
-
- Training and running [MegaDetector](megadetector.md).
|
|
76
|
-
- Training and running some [species classifiers](classification) that are used in conjunction with MegaDetector.
|
|
77
|
-
- Tools to [convert](data_management) frequently-used camera trap metadata formats into a common format.
|
|
78
|
-
- A [batch processing API](https://github.com/agentmorris/MegaDetector/tree/main/api/batch_processing) that runs MegaDetector on large image collections, to accelerate population surveys.
|
|
79
|
-
- A [real-time API](https://github.com/agentmorris/MegaDetector/tree/main/api/synchronous) that runs MegaDetector (and some species classifiers) synchronously, primarily to support biosecurity applications.
|
|
80
|
-
|
|
81
|
-
MegaDetector was initially developed by the [Microsoft AI for Earth program](https://www.microsoft.com/en-us/ai/ai-for-earth); this repo is derived from the [microsoft/cameratraps](https://github.com/microsoft/cameratraps) repo and maintained by the original MegaDetector developers (who are no longer at Microsoft, but are absolutely fantastically eternally grateful to Microsoft for the investment and commitment that made MegaDetector happen).
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
## What's MegaDetector all about?
|
|
85
|
-
|
|
86
|
-
[MegaDetector](megadetector.md) is an object detection model that identifies animals, people, and vehicles in camera trap images (which also makes it useful for eliminating blank images). This model is trained on several hundred thousand bounding boxes from a variety of ecosystems. Lots more information – including download links and instructions for running the model – is available in the [MegaDetector User Guide](megadetector.md).
|
|
87
|
-
|
|
88
|
-
This repo does not host the data used to train MegaDetector, but we work with our collaborators to make data and annotations available whenever possible on [lila.science](http://lila.science). See the [MegaDetector training data](megadetector.md#can-you-share-the-training-data) section to learn more about the data used to train MegaDetector.
|
|
89
|
-
|
|
90
|
-
Here's a “teaser” image of what MegaDetector output looks like:
|
|
91
|
-
|
|
92
|
-
<br/>Image credit University of Washington.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
## How do I get started with MegaDetector?
|
|
96
|
-
|
|
97
|
-
If you're just considering the use of AI in your workflow, and you aren't even sure yet whether MegaDetector would be useful to you, we recommend reading the "[getting started with MegaDetector](collaborations.md)" page.
|
|
98
|
-
|
|
99
|
-
If you're already familiar with MegaDetector and you're ready to run it on your data (and you have some familiarity with running Python code), see the [MegaDetector User Guide](megadetector.md) for instructions on downloading and running MegaDetector.
|
|
100
|
-
|
|
101
|
-
MegaDetector is just one of many tools that aims to make conservation biologists more efficient with AI. If you want to learn about other ways to use AI to accelerate camera trap workflows, check out our of the field, affectionately titled “[Everything I know about machine learning and camera traps](https://agentmorris.github.io/camera-trap-ml-survey/)”.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
## Who is using MegaDetector?
|
|
105
|
-
|
|
106
|
-
We work with ecologists all over the world to help them spend less time annotating images and more time thinking about conservation. You can read a little more about how this works on our [getting started with MegaDetector](collaborations.md) page.
|
|
107
|
-
|
|
108
|
-
Here are a few of the organizations that have used MegaDetector... we're only listing organizations who (a) we know about and (b) have given us permission to refer to them here (or have posted publicly about their use of MegaDetector), so if you're using MegaDetector or other tools from this repo and would like to be added to this list, <a href="mailto:cameratraps@lila.science">email us</a>!
|
|
109
|
-
|
|
110
|
-
* [Arizona Department of Environmental Quality](http://azdeq.gov/)
|
|
111
|
-
* [Blackbird Environmental](https://blackbirdenv.com/)
|
|
112
|
-
* [Camelot](https://camelotproject.org/)
|
|
113
|
-
* [Canadian Parks and Wilderness Society (CPAWS) Northern Alberta Chapter](https://cpawsnab.org/)
|
|
114
|
-
* [Conservation X Labs](https://conservationxlabs.com/)
|
|
115
|
-
* [Czech University of Life Sciences Prague](https://www.czu.cz/en)
|
|
116
|
-
* [Dudek Camera Trap AI Image Toolkit (AIT)](https://dudek.com/services/wildlife-camera-trap-ai-image-processing-and-management/)
|
|
117
|
-
* [EcoLogic Consultants Ltd.](https://www.consult-ecologic.com/)
|
|
118
|
-
* [Estación Biológica de Doñana](http://www.ebd.csic.es/inicio)
|
|
119
|
-
* [Idaho Department of Fish and Game](https://idfg.idaho.gov/)
|
|
120
|
-
* [Island Conservation](https://www.islandconservation.org/)
|
|
121
|
-
* [Myall Lakes Dingo Project](https://carnivorecoexistence.info/myall-lakes-dingo-project/)
|
|
122
|
-
* [Norwegian Institute for Nature Research](https://www.nina.no/english/Home)
|
|
123
|
-
* [Point No Point Treaty Council](https://pnptc.org/)
|
|
124
|
-
* [Ramat Hanadiv Nature Park](https://www.ramat-hanadiv.org.il/en/)
|
|
125
|
-
* [SPEA (Portuguese Society for the Study of Birds)](https://spea.pt/en/)
|
|
126
|
-
* [Sky Island Alliance](https://skyislandalliance.org/)
|
|
127
|
-
* [Synthetaic](https://www.synthetaic.com/)
|
|
128
|
-
* [Taronga Conservation Society](https://taronga.org.au/)
|
|
129
|
-
* [The Nature Conservancy in Wyoming](https://www.nature.org/en-us/about-us/where-we-work/united-states/wyoming/)
|
|
130
|
-
* [TrapTagger](https://wildeyeconservation.org/trap-tagger-about/)
|
|
131
|
-
* [University of California Davis Natural Reserves](https://naturalreserves.ucdavis.edu/)
|
|
132
|
-
* [Upper Yellowstone Watershed Group](https://www.upperyellowstone.org/)
|
|
133
|
-
* [Zamba Cloud](https://www.zambacloud.com/)
|
|
134
|
-
* [Parc national du Mont-Tremblant](https://www.sepaq.com/pq/mot/index.dot?language_id=1)
|
|
135
|
-
|
|
136
|
-
* [Applied Conservation Macro Ecology Lab](http://www.acmelab.ca/), University of Victoria
|
|
137
|
-
* [Banff National Park Resource Conservation](https://www.pc.gc.ca/en/pn-np/ab/banff/nature/conservation), Parks Canada
|
|
138
|
-
* [Blumstein Lab](https://blumsteinlab.eeb.ucla.edu/), UCLA
|
|
139
|
-
* [Borderlands Research Institute](https://bri.sulross.edu/), Sul Ross State University
|
|
140
|
-
* [Capitol Reef National Park](https://www.nps.gov/care/index.htm) / Utah Valley University
|
|
141
|
-
* [Center for Biodiversity and Conservation](https://www.amnh.org/research/center-for-biodiversity-conservation), American Museum of Natural History
|
|
142
|
-
* [Centre for Ecosystem Science](https://www.unsw.edu.au/research/), UNSW Sydney
|
|
143
|
-
* [Cross-Cultural Ecology Lab](https://crossculturalecology.net/), Macquarie University
|
|
144
|
-
* [DC Cat Count](https://hub.dccatcount.org/), led by the Humane Rescue Alliance
|
|
145
|
-
* [Department of Fish and Wildlife Sciences](https://www.uidaho.edu/cnr/departments/fish-and-wildlife-sciences), University of Idaho
|
|
146
|
-
* [Department of Wildlife Ecology and Conservation](https://wec.ifas.ufl.edu/), University of Florida
|
|
147
|
-
* [Ecology and Conservation of Amazonian Vertebrates Research Group](https://www.researchgate.net/lab/Fernanda-Michalski-Lab-4), Federal University of Amapá
|
|
148
|
-
* [Gola Forest Programma](https://www.rspb.org.uk/our-work/conservation/projects/scientific-support-for-the-gola-forest-programme/), Royal Society for the Protection of Birds (RSPB)
|
|
149
|
-
* [Graeme Shannon's Research Group](https://wildliferesearch.co.uk/group-1), Bangor University
|
|
150
|
-
* [Hamaarag](https://hamaarag.org.il/), The Steinhardt Museum of Natural History, Tel Aviv University
|
|
151
|
-
* [Institut des Science de la Forêt Tempérée](https://isfort.uqo.ca/) (ISFORT), Université du Québec en Outaouais
|
|
152
|
-
* [Lab of Dr. Bilal Habib](https://bhlab.in/about), the Wildlife Institute of India
|
|
153
|
-
* [Mammal Spatial Ecology and Conservation Lab](https://labs.wsu.edu/dthornton/), Washington State University
|
|
154
|
-
* [McLoughlin Lab in Population Ecology](http://mcloughlinlab.ca/lab/), University of Saskatchewan
|
|
155
|
-
* [National Wildlife Refuge System, Southwest Region](https://www.fws.gov/about/region/southwest), U.S. Fish & Wildlife Service
|
|
156
|
-
* [Northern Great Plains Program](https://nationalzoo.si.edu/news/restoring-americas-prairie), Smithsonian
|
|
157
|
-
* [Polar Ecology Group](https://polarecologygroup.wordpress.com), University of Gdansk
|
|
158
|
-
* [Quantitative Ecology Lab](https://depts.washington.edu/sefsqel/), University of Washington
|
|
159
|
-
* [Santa Monica Mountains Recreation Area](https://www.nps.gov/samo/index.htm), National Park Service
|
|
160
|
-
* [Seattle Urban Carnivore Project](https://www.zoo.org/seattlecarnivores), Woodland Park Zoo
|
|
161
|
-
* [Serra dos Órgãos National Park](https://www.icmbio.gov.br/parnaserradosorgaos/), ICMBio
|
|
162
|
-
* [Snapshot USA](https://emammal.si.edu/snapshot-usa), Smithsonian
|
|
163
|
-
* [Wildlife Coexistence Lab](https://wildlife.forestry.ubc.ca/), University of British Columbia
|
|
164
|
-
* [Wildlife Research](https://www.dfw.state.or.us/wildlife/research/index.asp), Oregon Department of Fish and Wildlife
|
|
165
|
-
* [Wildlife Division](https://www.michigan.gov/dnr/about/contact/wildlife), Michigan Department of Natural Resources
|
|
166
|
-
|
|
167
|
-
* Department of Ecology, TU Berlin
|
|
168
|
-
* Ghost Cat Analytics
|
|
169
|
-
* Protected Areas Unit, Canadian Wildlife Service
|
|
170
|
-
|
|
171
|
-
* [School of Natural Sciences](https://www.utas.edu.au/natural-sciences), University of Tasmania ([story](https://www.utas.edu.au/about/news-and-stories/articles/2022/1204-innovative-camera-network-keeps-close-eye-on-tassie-wildlife))
|
|
172
|
-
* [Kenai National Wildlife Refuge](https://www.fws.gov/refuge/kenai), U.S. Fish & Wildlife Service ([story](https://www.peninsulaclarion.com/sports/refuge-notebook-new-technology-increases-efficiency-of-refuge-cameras/))
|
|
173
|
-
|
|
174
|
-
* [Australian Wildlife Conservancy](https://www.australianwildlife.org/) (blog posts [1](https://www.australianwildlife.org/cutting-edge-technology-delivering-efficiency-gains-in-conservation/), [2](https://www.australianwildlife.org/efficiency-gains-at-the-cutting-edge-of-technology/))
|
|
175
|
-
* [Bavarian Forest National Park](https://www.nationalpark-bayerischer-wald.bayern.de/english/index.htm) ([story](https://customers.microsoft.com/en-au/story/1667539539271247797-nationalparkbayerischerwald-azure-en))
|
|
176
|
-
* [Felidae Conservation Fund](https://felidaefund.org/) ([WildePod platform](https://wildepod.org/)) ([blog post](https://abhaykashyap.com/blog/ai-powered-camera-trap-image-annotation-system/))
|
|
177
|
-
* [Alberta Biodiversity Monitoring Institute (ABMI)](https://www.abmi.ca/home.html) ([WildTrax platform](https://www.wildtrax.ca/)) (blog posts [1](https://wildcams.ca/blog/the-abmi-visits-the-zoo/),[2](http://blog.abmi.ca/2023/06/14/making-wildtrax-its-not-a-kind-of-magic-behind-the-screen/))
|
|
178
|
-
* [Shan Shui Conservation Center](http://en.shanshui.org/) ([blog post](https://mp.weixin.qq.com/s/iOIQF3ckj0-rEG4yJgerYw?fbclid=IwAR0alwiWbe3udIcFvqqwm7y5qgr9hZpjr871FZIa-ErGUukZ7yJ3ZhgCevs)) ([translated blog post](https://mp-weixin-qq-com.translate.goog/s/iOIQF3ckj0-rEG4yJgerYw?fbclid=IwAR0alwiWbe3udIcFvqqwm7y5qgr9hZpjr871FZIa-ErGUukZ7yJ3ZhgCevs&_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp))
|
|
179
|
-
* [Irvine Ranch Conservancy](http://www.irconservancy.org/) ([story](https://www.ocregister.com/2022/03/30/ai-software-is-helping-researchers-focus-on-learning-about-ocs-wild-animals/))
|
|
180
|
-
* [Wildlife Protection Solutions](https://wildlifeprotectionsolutions.org/) ([story](https://customers.microsoft.com/en-us/story/1384184517929343083-wildlife-protection-solutions-nonprofit-ai-for-earth), [story](https://www.enterpriseai.news/2023/02/20/ai-helps-wildlife-protection-solutions-safeguard-endangered-species/))
|
|
181
|
-
* [Q42](https://www.q42.nl/en) ([blog post](https://engineering.q42.nl/ai-bear-repeller/))
|
|
182
|
-
* [Agouti](https://agouti.eu/) ([report](https://efsa.onlinelibrary.wiley.com/doi/pdf/10.2903/sp.efsa.2023.EN-8217))
|
|
183
|
-
* [Trapper](https://trapper-project.readthedocs.io/en/latest/overview.html) ([tutorial](https://trapper-project.readthedocs.io/en/latest/tutorial.html))
|
|
184
|
-
|
|
185
|
-
* [Road Ecology Center](https://roadecology.ucdavis.edu/), University of California, Davis ([Wildlife Observer Network platform](https://wildlifeobserver.net/))
|
|
186
|
-
* [The Nature Conservancy in California](https://www.nature.org/en-us/about-us/where-we-work/united-states/california/) ([Animl platform](https://github.com/tnc-ca-geo/animl-frontend))
|
|
187
|
-
* [San Diego Zoo Wildlife Alliance](https://science.sandiegozoo.org/) ([Animl R package](https://github.com/conservationtechlab/animl))
|
|
188
|
-
|
|
189
|
-
Also see:
|
|
190
|
-
|
|
191
|
-
* The [list of MD-related GUIs, platforms, and GitHub repos](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md#is-there-a-gui) on the MegaDetector User Guide
|
|
192
|
-
|
|
193
|
-
* [Peter's map of EcoAssist users](https://github.com/PetervanLunteren/EcoAssist#users) (who are also MegaDetector users!)
|
|
194
|
-
|
|
195
|
-
* The list of papers tagged "MegaDetector" on our [list of papers about ML and camera traps](https://agentmorris.github.io/camera-trap-ml-survey/#camera-trap-ml-papers)
|
|
196
|
-
|
|
197
|
-
## Repo contents
|
|
198
|
-
|
|
199
|
-
This repo is organized into the following folders...
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
### api
|
|
203
|
-
|
|
204
|
-
Code for hosting our models as an API, either for synchronous operation (i.e., for real-time inference) or as a batch process (for large biodiversity surveys). Common operations one might do after running MegaDetector – e.g. [generating preview pages to summarize your results](https://github.com/agentmorris/MegaDetector/blob/main/api/batch_processing/postprocessing/postprocess_batch_results.py), [separating images into different folders based on AI results](https://github.com/agentmorris/MegaDetector/blob/main/api/batch_processing/postprocessing/separate_detections_into_folders.py), or [converting results to a different format](https://github.com/agentmorris/MegaDetector/blob/main/api/batch_processing/postprocessing/convert_output_format.py) – also live in this folder, within the [api/batch_processing/postprocessing](https://github.com/agentmorris/MegaDetector/tree/main/api/batch_processing/postprocessing) folder.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
### archive
|
|
208
|
-
|
|
209
|
-
Old code that we didn't <i>quite</i> want to delete, but is basically obsolete.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
### classification
|
|
213
|
-
|
|
214
|
-
Experimental code for training species classifiers on new data sets, generally trained on MegaDetector crops. Currently the main pipeline described in this folder relies on a large database of labeled images that is not publicly available; therefore, this folder is not yet set up to facilitate training of your own classifiers. However, it is useful for <i>users</i> of the classifiers that we train, and contains some useful starting points if you are going to take a "DIY" approach to training classifiers on cropped images.
|
|
215
|
-
|
|
216
|
-
All that said, here's another "teaser image" of what you get at the end of training and running a classifier:
|
|
217
|
-
|
|
218
|
-
<img src="images/warthog_classifications.jpg" width="700"><br/>Image credit University of Minnesota, from the Snapshot Safari program.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
### data_management
|
|
222
|
-
|
|
223
|
-
Code for:
|
|
224
|
-
|
|
225
|
-
* Converting frequently-used metadata formats to [COCO Camera Traps](https://github.com/agentmorris/MegaDetector/blob/main/data_management/README.md#coco-cameratraps-format) format
|
|
226
|
-
* Converting the output of AI models (especially [YOLOv5](https://github.com/agentmorris/MegaDetector/blob/main/api/batch_processing/postprocessing/convert_output_format.py)) to the format used for AI results throughout this repo
|
|
227
|
-
* Creating, visualizing, and editing COCO Camera Traps .json databases
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
### detection
|
|
231
|
-
|
|
232
|
-
Code for training, running, and evaluating MegaDetector.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
### envs
|
|
236
|
-
|
|
237
|
-
Environment files... specifically .yml files for mamba/conda environments (these are what we recommend in our [MegaDetector User Guide](megadetector.md)), and a requirements.txt for the pip-inclined.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
### images
|
|
241
|
-
|
|
242
|
-
Media used in documentation.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
### md_utils
|
|
246
|
-
|
|
247
|
-
Small utility functions for string manipulation, filename manipulation, downloading files from URLs, etc. Mostly adapted from the [ai4eutils](https://github.com/microsoft/ai4eutils) repo.
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
### md_visualization
|
|
251
|
-
|
|
252
|
-
Shared tools for visualizing images with ground truth and/or predicted annotations.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
### sandbox
|
|
256
|
-
|
|
257
|
-
Random things that don't fit in any other directory, but aren't quite deprecated. Mostly postprocessing scripts that were built for a single use case but could potentially be useful in the future.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
### taxonomy_mapping
|
|
261
|
-
|
|
262
|
-
Code to facilitate mapping data-set-specific category names (e.g. "lion", which means very different things in Idaho vs. South Africa) to a standard taxonomy.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
### test_images
|
|
266
|
-
|
|
267
|
-
A handful of images from [LILA](https://lila.science) that facilitate testing and debugging.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
## Contact
|
|
271
|
-
|
|
272
|
-
For questions about this repo, contact [cameratraps@lila.science](mailto:cameratraps@lila.science).
|
|
273
|
-
|
|
274
|
-
You can also chat with us and the broader camera trap AI community on the [AI for Conservation forum at WILDLABS](https://wildlabs.net/groups/ai-conservation) or the [AI for Conservation Slack group](https://aiforconservation.slack.com).
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
## Gratuitous camera trap picture
|
|
278
|
-
|
|
279
|
-
<br/>Image credit USDA, from the [NACTI](http://lila.science/datasets/nacti) data set.
|
|
280
|
-
|
|
281
|
-
You will find lots more gratuitous camera trap pictures sprinkled about this repo. It's like a scavenger hunt.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
## License
|
|
285
|
-
|
|
286
|
-
This repository is licensed with the [MIT license](https://opensource.org/license/mit/).
|
|
287
|
-
|
|
288
|
-
Code written on or before April 28, 2023 is [copyright Microsoft](https://github.com/Microsoft/dotnet/blob/main/LICENSE).
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
## Contributing
|
|
292
|
-
|
|
293
|
-
This project welcomes contributions, as pull requests, issues, or suggestions by [email](mailto:cameratraps@lila.science). We have a [list](https://github.com/agentmorris/MegaDetector/issues/84) of issues that we're hoping to address, many of which would be good starting points for new contributors. We also depend on other open-source tools that help users run MegaDetector (e.g. [EcoAssist](https://github.com/PetervanLunteren/EcoAssist) and [CamTrap Detector](https://github.com/bencevans/camtrap-detector)) and work with MegaDetector results (e.g. [Timelapse](https://github.com/saulgreenberg/Timelapse)); if you are looking to get involved in GUI development, reach out to the developers of those tools as well!
|
|
294
|
-
|
|
295
|
-
If you are interesting in getting involved in the conservation technology space, and MegaDetector just happens to be the first page you landed on, and none of our open issues are getting you fired up, don't fret! Head over to the [WILDLABS discussion forums](https://wildlabs.net/discussions) and let the community know you're a developer looking to get involved. Someone needs your help!
|
|
File without changes
|
|
File without changes
|
|
File without changes
|