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.

@@ -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, that requires a
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 md_to_labelme(results_file,image_base,confidence_threshold,overwrite=False):
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
- output_dict['md_info'] = md_results['info']
62
- output_dict['version'] = '5.3.0a0'
63
- output_dict['flags'] = {}
64
- output_dict['shapes'] = []
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
- help='Confidence threshold')
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',
@@ -85,7 +85,7 @@ from typing import Any
85
85
  import pandas as pd
86
86
  from tqdm import tqdm
87
87
 
88
- from ct_utils import truncate_float
88
+ from md_utils.ct_utils import truncate_float
89
89
 
90
90
 
91
91
  #%% Support functions
@@ -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 minumum confidence
487
+ # Discard tags below the minimum confidence
488
488
  if tag['confidence'] >= confidence_threshold:
489
489
  valid_tags.append(tag)
490
490
  else:
@@ -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.
@@ -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
- checkpoint = torch.load(model_pt_path, map_location=device)
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 to TensorFlow (.pb) or PyTorch (.pt) detector model file')
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'
@@ -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 vesions 9 and 10, and for a bit, I'd like to
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=wnBgScq9JbOG3HxHK94SxhRmBZsmQDNG4vKz5YgN2h8,4214
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=pU6cT02bCoj3QdLwtOTBKBWlUtxCF973tqc7Zo6gBjA,20114
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=ZcIXHMcZFBUMTnTTbaCrRwnmIjCNcHkb_53cCqYvnqo,28621
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=DU8jub3JSyviz5vaaOoCmQ_REwiWk7fbv47QeO0belM,22082
128
- detection/pytorch_detector.py,sha256=qiuiLoPFhNuNxUIv9OPn2oTVzBgbWEm-EHpOkO0nZnw,10649
129
- detection/run_detector.py,sha256=ARkG5IDGe8K7ZcwzLGYk5AkRVPM7DclepohPAK8LIwE,20689
130
- detection/run_detector_batch.py,sha256=db_qURKGDLc5R51zPlKR3wP8H6mxim8dZvuH0vvkkmk,40384
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=uNd_OMCpSio3dcyIvd5lrpaqugngsvKsnIVyiQBenzI,4416
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=ofj-0zLra6l71XNRiA6nc9SczVrQgvpE3m98ZnmqRpo,30448
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.2.dist-info/LICENSE,sha256=RMa3qq-7Cyk7DdtqRj_bP1oInGFgjyHn9-PZ3PcrqIs,1100
165
- megadetector-5.0.2.dist-info/METADATA,sha256=Kb-ASkQsJRtb65vmNhbJ8H4CPLS2l1SGDLEWkS9wCPk,21350
166
- megadetector-5.0.2.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
167
- megadetector-5.0.2.dist-info/top_level.txt,sha256=-mFGpqnmviVz0Vyr2GxZ_kTo_PBPNoK6h4JtqIMjZGQ,88
168
- megadetector-5.0.2.dist-info/RECORD,,
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 &ndash; including download links and instructions for running the model &ndash; 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 &ldquo;teaser&rdquo; image of what MegaDetector output looks like:
91
-
92
- ![Red bounding box on fox](images/detector_example.jpg)<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 &ldquo;[Everything I know about machine learning and camera traps](https://agentmorris.github.io/camera-trap-ml-survey/)&rdquo;.
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 &ndash; 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) &ndash; 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
- ![Bird flying above water](images/nacti.jpg)<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!