megadetector 5.0.26__py3-none-any.whl → 5.0.28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of megadetector might be problematic. Click here for more details.
- megadetector/data_management/mewc_to_md.py +1 -1
- megadetector/data_management/read_exif.py +2 -0
- megadetector/detection/process_video.py +1 -1
- megadetector/detection/pytorch_detector.py +4 -4
- megadetector/detection/run_detector.py +10 -3
- megadetector/detection/run_detector_batch.py +4 -3
- megadetector/detection/run_tiled_inference.py +65 -13
- megadetector/detection/video_utils.py +2 -2
- megadetector/postprocessing/classification_postprocessing.py +517 -20
- megadetector/postprocessing/create_crop_folder.py +1 -1
- megadetector/postprocessing/generate_csv_report.py +499 -0
- megadetector/postprocessing/load_api_results.py +4 -4
- megadetector/postprocessing/postprocess_batch_results.py +6 -4
- megadetector/taxonomy_mapping/preview_lila_taxonomy.py +0 -3
- megadetector/taxonomy_mapping/taxonomy_graph.py +1 -1
- megadetector/utils/ct_utils.py +3 -2
- megadetector/utils/path_utils.py +75 -29
- megadetector/utils/split_locations_into_train_val.py +16 -3
- megadetector/utils/wi_utils.py +68 -410
- megadetector/visualization/visualization_utils.py +25 -9
- megadetector/visualization/visualize_detector_output.py +50 -28
- {megadetector-5.0.26.dist-info → megadetector-5.0.28.dist-info}/METADATA +132 -132
- {megadetector-5.0.26.dist-info → megadetector-5.0.28.dist-info}/RECORD +26 -25
- {megadetector-5.0.26.dist-info → megadetector-5.0.28.dist-info}/WHEEL +1 -1
- {megadetector-5.0.26.dist-info → megadetector-5.0.28.dist-info}/licenses/LICENSE +0 -0
- {megadetector-5.0.26.dist-info → megadetector-5.0.28.dist-info}/top_level.txt +0 -0
|
@@ -10,7 +10,6 @@ detector output result file (.json), optionally writing an HTML index file.
|
|
|
10
10
|
#%% Imports
|
|
11
11
|
|
|
12
12
|
import argparse
|
|
13
|
-
import json
|
|
14
13
|
import os
|
|
15
14
|
import random
|
|
16
15
|
import sys
|
|
@@ -21,11 +20,13 @@ from functools import partial
|
|
|
21
20
|
from tqdm import tqdm
|
|
22
21
|
|
|
23
22
|
from megadetector.data_management.annotations.annotation_constants import detector_bbox_category_id_to_name
|
|
24
|
-
from megadetector.
|
|
25
|
-
from megadetector.visualization.visualization_utils import blur_detections
|
|
23
|
+
from megadetector.detection.run_detector import get_typical_confidence_threshold_from_results
|
|
26
24
|
from megadetector.utils.ct_utils import get_max_conf
|
|
27
25
|
from megadetector.utils import write_html_image_list
|
|
28
|
-
from megadetector.
|
|
26
|
+
from megadetector.utils.path_utils import path_is_abs
|
|
27
|
+
from megadetector.utils.wi_utils import load_md_or_speciesnet_file
|
|
28
|
+
from megadetector.visualization import visualization_utils as vis_utils
|
|
29
|
+
from megadetector.visualization.visualization_utils import blur_detections
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
#%% Constants
|
|
@@ -73,9 +74,16 @@ def _render_image(entry,
|
|
|
73
74
|
rendering_result['skipped_image'] = True
|
|
74
75
|
return rendering_result
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
if images_dir is None:
|
|
78
|
+
image_filename_in_abs = image_id
|
|
79
|
+
assert path_is_abs(image_filename_in_abs), \
|
|
80
|
+
'Absolute paths are required when no image base dir is supplied'
|
|
81
|
+
else:
|
|
82
|
+
assert not path_is_abs(image_id), \
|
|
83
|
+
'Relative paths are required when an image base dir is supplied'
|
|
84
|
+
image_filename_in_abs = os.path.join(images_dir, image_id)
|
|
77
85
|
if not os.path.exists(image_filename_in_abs):
|
|
78
|
-
print(f'Image {image_id} not found
|
|
86
|
+
print(f'Image {image_id} not found')
|
|
79
87
|
rendering_result['missing_image'] = True
|
|
80
88
|
return rendering_result
|
|
81
89
|
|
|
@@ -125,12 +133,14 @@ def _render_image(entry,
|
|
|
125
133
|
|
|
126
134
|
return rendering_result
|
|
127
135
|
|
|
136
|
+
# ...def _render_image(...)
|
|
137
|
+
|
|
128
138
|
|
|
129
139
|
#%% Main function
|
|
130
140
|
|
|
131
141
|
def visualize_detector_output(detector_output_path,
|
|
132
142
|
out_dir,
|
|
133
|
-
images_dir,
|
|
143
|
+
images_dir=None,
|
|
134
144
|
confidence_threshold=0.15,
|
|
135
145
|
sample=-1,
|
|
136
146
|
output_image_width=700,
|
|
@@ -153,20 +163,24 @@ def visualize_detector_output(detector_output_path,
|
|
|
153
163
|
detector_output_path (str): path to detector output .json file
|
|
154
164
|
out_dir (str): path to directory for saving annotated images
|
|
155
165
|
images_dir (str): folder where the images live; filenames in
|
|
156
|
-
[detector_output_path] should be relative to [image_dir]
|
|
166
|
+
[detector_output_path] should be relative to [image_dir]. Can be None if paths are
|
|
167
|
+
absolute.
|
|
157
168
|
confidence_threshold (float, optional): threshold above which detections will be rendered
|
|
158
169
|
sample (int, optional): maximum number of images to render, -1 for all
|
|
159
170
|
output_image_width (int, optional): width in pixels to resize images for display,
|
|
160
171
|
preserving aspect ration; set to -1 to use original image width
|
|
161
172
|
random_seed (int, optional): seed to use for choosing images when sample != -1
|
|
162
|
-
render_detections_only (bool): only render images with above-threshold detections
|
|
173
|
+
render_detections_only (bool): only render images with above-threshold detections. Empty
|
|
174
|
+
images are discarded after sampling, so if you want to see, e.g., 1000 non-empty images,
|
|
175
|
+
you can set [render_detections_only], but you need to sample more than 1000 images.
|
|
163
176
|
classification_confidence_threshold (float, optional): only show classifications
|
|
164
177
|
above this threshold; does not impact whether images are rendered, only whether
|
|
165
178
|
classification labels (not detection categories) are displayed
|
|
166
179
|
html_output_file (str, optional): output path for an HTML index file (not written
|
|
167
180
|
if None)
|
|
168
181
|
html_output_options (dict, optional): HTML formatting options; see write_html_image_list
|
|
169
|
-
for details
|
|
182
|
+
for details. The most common option you may want to supply here is
|
|
183
|
+
'maxFiguresPerHtmlFile'.
|
|
170
184
|
preserve_path_structure (bool, optional): if False (default), writes images to unique
|
|
171
185
|
names in a flat structure in the output folder; if True, preserves relative paths
|
|
172
186
|
within the output folder
|
|
@@ -188,25 +202,24 @@ def visualize_detector_output(detector_output_path,
|
|
|
188
202
|
assert os.path.exists(detector_output_path), \
|
|
189
203
|
'Detector output file does not exist at {}'.format(detector_output_path)
|
|
190
204
|
|
|
191
|
-
|
|
192
|
-
|
|
205
|
+
if images_dir is not None:
|
|
206
|
+
assert os.path.isdir(images_dir), \
|
|
207
|
+
'Image folder {} is not available'.format(images_dir)
|
|
193
208
|
|
|
194
209
|
os.makedirs(out_dir, exist_ok=True)
|
|
195
210
|
|
|
196
211
|
|
|
197
212
|
##%% Load detector output
|
|
198
213
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
assert 'images' in detector_output, (
|
|
202
|
-
'Detector output file should be a json with an "images" field.')
|
|
214
|
+
detector_output = load_md_or_speciesnet_file(detector_output_path)
|
|
215
|
+
|
|
203
216
|
images = detector_output['images']
|
|
204
217
|
|
|
205
218
|
if confidence_threshold is None:
|
|
206
219
|
confidence_threshold = get_typical_confidence_threshold_from_results(detector_output)
|
|
207
220
|
|
|
208
|
-
assert confidence_threshold >= 0 and confidence_threshold <= 1,
|
|
209
|
-
f'Confidence threshold {confidence_threshold} is invalid, must be in (0, 1).'
|
|
221
|
+
assert confidence_threshold >= 0 and confidence_threshold <= 1, \
|
|
222
|
+
f'Confidence threshold {confidence_threshold} is invalid, must be in (0, 1).'
|
|
210
223
|
|
|
211
224
|
if 'detection_categories' in detector_output:
|
|
212
225
|
detector_label_map = detector_output['detection_categories']
|
|
@@ -303,9 +316,12 @@ def visualize_detector_output(detector_output_path,
|
|
|
303
316
|
html_dir = os.path.dirname(html_output_file)
|
|
304
317
|
|
|
305
318
|
html_image_info = []
|
|
306
|
-
|
|
319
|
+
|
|
307
320
|
for r in rendering_results:
|
|
308
321
|
d = {}
|
|
322
|
+
if r['annotated_image_path'] is None:
|
|
323
|
+
assert r['failed_image'] or r['missing_image'] or r['skipped_image']
|
|
324
|
+
continue
|
|
309
325
|
annotated_image_path_relative = os.path.relpath(r['annotated_image_path'],html_dir)
|
|
310
326
|
d['filename'] = annotated_image_path_relative
|
|
311
327
|
d['textStyle'] = \
|
|
@@ -319,6 +335,8 @@ def visualize_detector_output(detector_output_path,
|
|
|
319
335
|
|
|
320
336
|
return annotated_image_paths
|
|
321
337
|
|
|
338
|
+
# ...def visualize_detector_output(...)
|
|
339
|
+
|
|
322
340
|
|
|
323
341
|
#%% Command-line driver
|
|
324
342
|
|
|
@@ -336,42 +354,45 @@ def main():
|
|
|
336
354
|
help='Path to directory where the annotated images will be saved. '
|
|
337
355
|
'The directory will be created if it does not exist.')
|
|
338
356
|
parser.add_argument(
|
|
339
|
-
'
|
|
357
|
+
'--confidence', type=float, default=0.15,
|
|
340
358
|
help='Value between 0 and 1, indicating the confidence threshold '
|
|
341
359
|
'above which to visualize bounding boxes')
|
|
342
360
|
parser.add_argument(
|
|
343
|
-
'
|
|
361
|
+
'--images_dir', type=str, default=None,
|
|
344
362
|
help='Path to a local directory where images are stored. This '
|
|
345
363
|
'serves as the root directory for image paths in '
|
|
346
|
-
'detector_output_path.')
|
|
364
|
+
'detector_output_path. Omit if image paths are absolute.')
|
|
347
365
|
parser.add_argument(
|
|
348
|
-
'
|
|
366
|
+
'--sample', type=int, default=-1,
|
|
349
367
|
help='Number of images to be annotated and rendered. Set to -1 '
|
|
350
368
|
'(default) to annotate all images in the detector output file. '
|
|
351
369
|
'There may be fewer images if some are not found in images_dir.')
|
|
352
370
|
parser.add_argument(
|
|
353
|
-
'
|
|
371
|
+
'--output_image_width', type=int, default=700,
|
|
354
372
|
help='Integer, desired width in pixels of the output annotated images. '
|
|
355
373
|
'Use -1 to not resize. Default: 700.')
|
|
356
374
|
parser.add_argument(
|
|
357
|
-
'
|
|
375
|
+
'--random_seed', type=int, default=None,
|
|
358
376
|
help='Integer, for deterministic order of image sampling')
|
|
359
377
|
parser.add_argument(
|
|
360
|
-
'
|
|
378
|
+
'--html_output_file', type=str, default=None,
|
|
361
379
|
help='Filename to which we should write an HTML image index (off by default)')
|
|
362
380
|
parser.add_argument(
|
|
363
381
|
'--open_html_output_file', action='store_true',
|
|
364
382
|
help='Open the .html output file when done')
|
|
365
383
|
parser.add_argument(
|
|
366
|
-
'
|
|
384
|
+
'--detections_only', action='store_true',
|
|
367
385
|
help='Only render images with above-threshold detections (by default, '
|
|
368
386
|
'both empty and non-empty images are rendered).')
|
|
369
387
|
parser.add_argument(
|
|
370
|
-
'
|
|
388
|
+
'--preserve_path_structure', action='store_true',
|
|
371
389
|
help='Preserve relative image paths (otherwise flattens and assigns unique file names)')
|
|
372
390
|
parser.add_argument(
|
|
373
391
|
'--category_names_to_blur', default=None, type=str,
|
|
374
392
|
help='Comma-separated list of category names to blur (or a single category name, typically "person")')
|
|
393
|
+
parser.add_argument(
|
|
394
|
+
'--classification_confidence', type=float, default=0.1,
|
|
395
|
+
help='If classification results are present, render results above this threshold')
|
|
375
396
|
|
|
376
397
|
if len(sys.argv[1:]) == 0:
|
|
377
398
|
parser.print_help()
|
|
@@ -392,6 +413,7 @@ def main():
|
|
|
392
413
|
output_image_width=args.output_image_width,
|
|
393
414
|
random_seed=args.random_seed,
|
|
394
415
|
render_detections_only=args.detections_only,
|
|
416
|
+
classification_confidence_threshold=args.classification_confidence,
|
|
395
417
|
preserve_path_structure=args.preserve_path_structure,
|
|
396
418
|
html_output_file=args.html_output_file,
|
|
397
419
|
category_names_to_blur=category_names_to_blur)
|
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: megadetector
|
|
3
|
-
Version: 5.0.
|
|
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: Documentation, https://megadetector.readthedocs.io
|
|
29
|
-
Project-URL: Bug Reports, https://github.com/agentmorris/MegaDetector/issues
|
|
30
|
-
Project-URL: Source, https://github.com/agentmorris/MegaDetector
|
|
31
|
-
Keywords: camera traps,conservation,wildlife,ai,megadetector
|
|
32
|
-
Classifier: Programming Language :: Python :: 3
|
|
33
|
-
Requires-Python: <3.14,>=3.9
|
|
34
|
-
Description-Content-Type: text/markdown
|
|
35
|
-
License-File: LICENSE
|
|
36
|
-
Requires-Dist: mkl==2024.0; sys_platform != "darwin"
|
|
37
|
-
Requires-Dist: numpy
|
|
38
|
-
Requires-Dist: Pillow>=9.5
|
|
39
|
-
Requires-Dist: tqdm>=4.64.0
|
|
40
|
-
Requires-Dist: jsonpickle>=3.0.2
|
|
41
|
-
Requires-Dist: humanfriendly>=10.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: scikit-learn>=1.3.1
|
|
47
|
-
Requires-Dist: pandas>=2.1.1
|
|
48
|
-
Requires-Dist: python-dateutil
|
|
49
|
-
Requires-Dist: send2trash
|
|
50
|
-
Requires-Dist: dill
|
|
51
|
-
Requires-Dist: ultralytics-yolov5==0.1.1
|
|
52
|
-
Requires-Dist: yolov9pip==0.0.4
|
|
53
|
-
Requires-Dist: python-dateutil
|
|
54
|
-
Dynamic: license-file
|
|
55
|
-
|
|
56
|
-
# MegaDetector
|
|
57
|
-
|
|
58
|
-
This package is a pip-installable version of the support/inference code for [MegaDetector](https://github.com/agentmorris/MegaDetector/?tab=readme-ov-file#megadetector), an object detection model that helps conservation biologists spend less time doing boring things with camera trap images. Complete documentation for this Python package is available at [megadetector.readthedocs.io](https://megadetector.readthedocs.io).
|
|
59
|
-
|
|
60
|
-
If you aren't looking for the Python package specifically, and you just want to learn more about what MegaDetector is all about, head over to the [MegaDetector repo](https://github.com/agentmorris/MegaDetector/?tab=readme-ov-file#megadetector).
|
|
61
|
-
|
|
62
|
-
If you don't want to run MegaDetector, and you just want to use the utilities in this package - postprocessing, manipulating large volumes of camera trap images, etc. - you may want to check out the [megadetector-utils](https://pypi.org/project/megadetector-utils/) package, which is identical to this one, but excludes all of the PyTorch/YOLO dependencies, and is thus approximately one zillion times smaller.
|
|
63
|
-
|
|
64
|
-
## Installation
|
|
65
|
-
|
|
66
|
-
Install with:
|
|
67
|
-
|
|
68
|
-
`pip install megadetector`
|
|
69
|
-
|
|
70
|
-
MegaDetector model weights aren't downloaded at the time you install the package, but they will be (optionally) automatically downloaded the first time you run the model.
|
|
71
|
-
|
|
72
|
-
## Package reference
|
|
73
|
-
|
|
74
|
-
See [megadetector.readthedocs.io](https://megadetector.readthedocs.io).
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
## Examples of things you can do with this package
|
|
78
|
-
|
|
79
|
-
### Run MegaDetector on one image and count the number of detections
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
from megadetector.utils import url_utils
|
|
83
|
-
from megadetector.visualization import visualization_utils as vis_utils
|
|
84
|
-
from megadetector.detection import run_detector
|
|
85
|
-
|
|
86
|
-
# This is the image at the bottom of this page, it has one animal in it
|
|
87
|
-
image_url = 'https://github.com/agentmorris/MegaDetector/raw/main/images/orinoquia-thumb-web.jpg'
|
|
88
|
-
temporary_filename = url_utils.download_url(image_url)
|
|
89
|
-
|
|
90
|
-
image = vis_utils.load_image(temporary_filename)
|
|
91
|
-
|
|
92
|
-
# This will automatically download MDv5a; you can also specify a filename.
|
|
93
|
-
model = run_detector.load_detector('MDV5A')
|
|
94
|
-
|
|
95
|
-
result = model.generate_detections_one_image(image)
|
|
96
|
-
|
|
97
|
-
detections_above_threshold = [d for d in result['detections'] if d['conf'] > 0.2]
|
|
98
|
-
print('Found {} detections above threshold'.format(len(detections_above_threshold)))
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Run MegaDetector on a folder of images
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
from megadetector.detection.run_detector_batch import \
|
|
105
|
-
load_and_run_detector_batch, write_results_to_file
|
|
106
|
-
from megadetector.utils import path_utils
|
|
107
|
-
import os
|
|
108
|
-
|
|
109
|
-
# Pick a folder to run MD on recursively, and an output file
|
|
110
|
-
image_folder = os.path.expanduser('~/megadetector_test_images')
|
|
111
|
-
output_file = os.path.expanduser('~/megadetector_output_test.json')
|
|
112
|
-
|
|
113
|
-
# Recursively find images
|
|
114
|
-
image_file_names = path_utils.find_images(image_folder,recursive=True)
|
|
115
|
-
|
|
116
|
-
# This will automatically download MDv5a; you can also specify a filename.
|
|
117
|
-
results = load_and_run_detector_batch('MDV5A', image_file_names)
|
|
118
|
-
|
|
119
|
-
# Write results to a format that Timelapse and other downstream tools like.
|
|
120
|
-
write_results_to_file(results,
|
|
121
|
-
output_file,
|
|
122
|
-
relative_path_base=image_folder,
|
|
123
|
-
detector_file=detector_filename)
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Contact
|
|
127
|
-
|
|
128
|
-
Contact <a href="cameratraps@lila.science">cameratraps@lila.science</a> with questions.
|
|
129
|
-
|
|
130
|
-
## Gratuitous animal picture
|
|
131
|
-
|
|
132
|
-
<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.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: megadetector
|
|
3
|
+
Version: 5.0.28
|
|
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: Documentation, https://megadetector.readthedocs.io
|
|
29
|
+
Project-URL: Bug Reports, https://github.com/agentmorris/MegaDetector/issues
|
|
30
|
+
Project-URL: Source, https://github.com/agentmorris/MegaDetector
|
|
31
|
+
Keywords: camera traps,conservation,wildlife,ai,megadetector
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Requires-Python: <3.14,>=3.9
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
License-File: LICENSE
|
|
36
|
+
Requires-Dist: mkl==2024.0; sys_platform != "darwin"
|
|
37
|
+
Requires-Dist: numpy>=1.26.4
|
|
38
|
+
Requires-Dist: Pillow>=9.5
|
|
39
|
+
Requires-Dist: tqdm>=4.64.0
|
|
40
|
+
Requires-Dist: jsonpickle>=3.0.2
|
|
41
|
+
Requires-Dist: humanfriendly>=10.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: scikit-learn>=1.3.1
|
|
47
|
+
Requires-Dist: pandas>=2.1.1
|
|
48
|
+
Requires-Dist: python-dateutil
|
|
49
|
+
Requires-Dist: send2trash
|
|
50
|
+
Requires-Dist: dill
|
|
51
|
+
Requires-Dist: ultralytics-yolov5==0.1.1
|
|
52
|
+
Requires-Dist: yolov9pip==0.0.4
|
|
53
|
+
Requires-Dist: python-dateutil
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# MegaDetector
|
|
57
|
+
|
|
58
|
+
This package is a pip-installable version of the support/inference code for [MegaDetector](https://github.com/agentmorris/MegaDetector/?tab=readme-ov-file#megadetector), an object detection model that helps conservation biologists spend less time doing boring things with camera trap images. Complete documentation for this Python package is available at [megadetector.readthedocs.io](https://megadetector.readthedocs.io).
|
|
59
|
+
|
|
60
|
+
If you aren't looking for the Python package specifically, and you just want to learn more about what MegaDetector is all about, head over to the [MegaDetector repo](https://github.com/agentmorris/MegaDetector/?tab=readme-ov-file#megadetector).
|
|
61
|
+
|
|
62
|
+
If you don't want to run MegaDetector, and you just want to use the utilities in this package - postprocessing, manipulating large volumes of camera trap images, etc. - you may want to check out the [megadetector-utils](https://pypi.org/project/megadetector-utils/) package, which is identical to this one, but excludes all of the PyTorch/YOLO dependencies, and is thus approximately one zillion times smaller.
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
Install with:
|
|
67
|
+
|
|
68
|
+
`pip install megadetector`
|
|
69
|
+
|
|
70
|
+
MegaDetector model weights aren't downloaded at the time you install the package, but they will be (optionally) automatically downloaded the first time you run the model.
|
|
71
|
+
|
|
72
|
+
## Package reference
|
|
73
|
+
|
|
74
|
+
See [megadetector.readthedocs.io](https://megadetector.readthedocs.io).
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
## Examples of things you can do with this package
|
|
78
|
+
|
|
79
|
+
### Run MegaDetector on one image and count the number of detections
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
from megadetector.utils import url_utils
|
|
83
|
+
from megadetector.visualization import visualization_utils as vis_utils
|
|
84
|
+
from megadetector.detection import run_detector
|
|
85
|
+
|
|
86
|
+
# This is the image at the bottom of this page, it has one animal in it
|
|
87
|
+
image_url = 'https://github.com/agentmorris/MegaDetector/raw/main/images/orinoquia-thumb-web.jpg'
|
|
88
|
+
temporary_filename = url_utils.download_url(image_url)
|
|
89
|
+
|
|
90
|
+
image = vis_utils.load_image(temporary_filename)
|
|
91
|
+
|
|
92
|
+
# This will automatically download MDv5a; you can also specify a filename.
|
|
93
|
+
model = run_detector.load_detector('MDV5A')
|
|
94
|
+
|
|
95
|
+
result = model.generate_detections_one_image(image)
|
|
96
|
+
|
|
97
|
+
detections_above_threshold = [d for d in result['detections'] if d['conf'] > 0.2]
|
|
98
|
+
print('Found {} detections above threshold'.format(len(detections_above_threshold)))
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Run MegaDetector on a folder of images
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
from megadetector.detection.run_detector_batch import \
|
|
105
|
+
load_and_run_detector_batch, write_results_to_file
|
|
106
|
+
from megadetector.utils import path_utils
|
|
107
|
+
import os
|
|
108
|
+
|
|
109
|
+
# Pick a folder to run MD on recursively, and an output file
|
|
110
|
+
image_folder = os.path.expanduser('~/megadetector_test_images')
|
|
111
|
+
output_file = os.path.expanduser('~/megadetector_output_test.json')
|
|
112
|
+
|
|
113
|
+
# Recursively find images
|
|
114
|
+
image_file_names = path_utils.find_images(image_folder,recursive=True)
|
|
115
|
+
|
|
116
|
+
# This will automatically download MDv5a; you can also specify a filename.
|
|
117
|
+
results = load_and_run_detector_batch('MDV5A', image_file_names)
|
|
118
|
+
|
|
119
|
+
# Write results to a format that Timelapse and other downstream tools like.
|
|
120
|
+
write_results_to_file(results,
|
|
121
|
+
output_file,
|
|
122
|
+
relative_path_base=image_folder,
|
|
123
|
+
detector_file=detector_filename)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Contact
|
|
127
|
+
|
|
128
|
+
Contact <a href="cameratraps@lila.science">cameratraps@lila.science</a> with questions.
|
|
129
|
+
|
|
130
|
+
## Gratuitous animal picture
|
|
131
|
+
|
|
132
|
+
<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.
|
|
@@ -62,9 +62,9 @@ megadetector/data_management/generate_crops_from_cct.py,sha256=Esq2Vlvp1AQvD8bmt
|
|
|
62
62
|
megadetector/data_management/get_image_sizes.py,sha256=2b6arj4gvoN-9f61lC3t1zAFFwYFxfb2iL83Tstoiik,6602
|
|
63
63
|
megadetector/data_management/labelme_to_coco.py,sha256=8RUXALXbLpmS7UYUet4BAe9JVSDW7ojwDDpxYs072ZI,21231
|
|
64
64
|
megadetector/data_management/labelme_to_yolo.py,sha256=dRePSOwU_jiCr0EakDQCz1Ct-ZHDxDglUk4HbM1LfWc,10034
|
|
65
|
-
megadetector/data_management/mewc_to_md.py,sha256=
|
|
65
|
+
megadetector/data_management/mewc_to_md.py,sha256=wZ25oDQ3spdI4a-8uii8F1UFX7JvBatIi1JLGLYPsHE,13399
|
|
66
66
|
megadetector/data_management/ocr_tools.py,sha256=T9ClY3B-blnK3-UF1vpVdageknYsykm_6FAfqn0kliU,32529
|
|
67
|
-
megadetector/data_management/read_exif.py,sha256=
|
|
67
|
+
megadetector/data_management/read_exif.py,sha256=aQKkhZ70vs-WT-7mIbujxN44WyuQFP47utZ7azsWQM4,30595
|
|
68
68
|
megadetector/data_management/remap_coco_categories.py,sha256=xbU3JW6o25YL8vV83KsOzK6_u1gGGbWDo1G0eOj4ncE,5123
|
|
69
69
|
megadetector/data_management/remove_exif.py,sha256=vIWnJfw1i9JgyQKUDGEzzqkHro4ndykIPFWhtkm6RAU,2502
|
|
70
70
|
megadetector/data_management/rename_images.py,sha256=ikIj_b5DY1rgaAn9n_IbwsnugAolczFNivh4xzfLPy8,6915
|
|
@@ -138,29 +138,30 @@ megadetector/data_management/lila/get_lila_image_counts.py,sha256=UxXS5RDnSA_Wbx
|
|
|
138
138
|
megadetector/data_management/lila/lila_common.py,sha256=74ecaGItH4AtCYeY1WSejLIcylhJPCJ1y97gYYL34PM,11080
|
|
139
139
|
megadetector/data_management/lila/test_lila_metadata_urls.py,sha256=TPNkULZM3zeOLucD-KSGwD8tHsmGY1uHbCBV2_vPpY0,5080
|
|
140
140
|
megadetector/detection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
141
|
-
megadetector/detection/process_video.py,sha256=
|
|
142
|
-
megadetector/detection/pytorch_detector.py,sha256=
|
|
143
|
-
megadetector/detection/run_detector.py,sha256=
|
|
144
|
-
megadetector/detection/run_detector_batch.py,sha256=
|
|
141
|
+
megadetector/detection/process_video.py,sha256=oUF8tzqGmAwUwFKJKnEHQ1hOOtfnn018vWesRUndMGA,54471
|
|
142
|
+
megadetector/detection/pytorch_detector.py,sha256=_ENSlQSE04wvj3J8Bx8W95PCl-vPkuAeBJ29si-LD50,45334
|
|
143
|
+
megadetector/detection/run_detector.py,sha256=zNq90YtuFVcx6zQa4AOO2vK5m1HnSS-H0qxo8kJlLH4,39431
|
|
144
|
+
megadetector/detection/run_detector_batch.py,sha256=hXsib0h_IeA9AF1tkAHiwov8TyUK_1OMUWiVvPiO1lU,73129
|
|
145
145
|
megadetector/detection/run_inference_with_yolov5_val.py,sha256=Ofu9B4yOmWso-S6JYalK0f_CvsG5tr2gkW_-rDskMD0,55291
|
|
146
|
-
megadetector/detection/run_tiled_inference.py,sha256=
|
|
146
|
+
megadetector/detection/run_tiled_inference.py,sha256=LbBatyumn_0CFv8yaglEvyzaaiSSHyA8s5X0vDbd2gQ,40469
|
|
147
147
|
megadetector/detection/tf_detector.py,sha256=t9O6J7r1wHOkKbrwchducdJrAHSw38DDA7rF7_0urn0,8522
|
|
148
|
-
megadetector/detection/video_utils.py,sha256=
|
|
148
|
+
megadetector/detection/video_utils.py,sha256=UY5MP4PXkoVMTGIAgQqXw9tu-9KWv52KI6OMywO3_a4,43821
|
|
149
149
|
megadetector/postprocessing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
150
150
|
megadetector/postprocessing/add_max_conf.py,sha256=qTE1_0RwGAy6jLDkHrIo2pS84yNbUV11s4IZuAYGdIU,1514
|
|
151
151
|
megadetector/postprocessing/categorize_detections_by_size.py,sha256=YdapcvjA6Dz2dPa2AFf1Dwyl7C-OmmP4G4OjhTOuaF4,5797
|
|
152
|
-
megadetector/postprocessing/classification_postprocessing.py,sha256=
|
|
152
|
+
megadetector/postprocessing/classification_postprocessing.py,sha256=aTSTqFBACR8kjxE-tEQwcpDH8XogzIUj479gcIDgY18,61069
|
|
153
153
|
megadetector/postprocessing/combine_batch_outputs.py,sha256=va6v1ZZzbQlq16S3gEqHKI5RbBuwRQ6ZoLAdDbIWYOQ,8416
|
|
154
154
|
megadetector/postprocessing/compare_batch_results.py,sha256=dtRbutrJQNb0e9VO5bOQXMpPTj-rYJqrqrE3AaM6-NU,85613
|
|
155
155
|
megadetector/postprocessing/convert_output_format.py,sha256=HwThfK76UPEAGa3KQbJ_tMKIrUvJ3JhKoQVWJt9dPBk,15447
|
|
156
|
-
megadetector/postprocessing/create_crop_folder.py,sha256=
|
|
156
|
+
megadetector/postprocessing/create_crop_folder.py,sha256=mnoPDl5_hBVYpzUZeH0IpD3ZY_yHJyROOJi275DHMKg,16146
|
|
157
157
|
megadetector/postprocessing/detector_calibration.py,sha256=rzAsiUJhw8Y4RxSK1SMnsdjI3MYkFA9NP5vJ7CNsX0I,21820
|
|
158
|
-
megadetector/postprocessing/
|
|
158
|
+
megadetector/postprocessing/generate_csv_report.py,sha256=A2j5FD7PDBVEh2foVEBCdSWzi5KDHoUDE0iwvhEw2Fg,19858
|
|
159
|
+
megadetector/postprocessing/load_api_results.py,sha256=oV9QlqHYhsVUuZJqABWhK9M23q5SGfk2eQjw3JKhaBQ,7046
|
|
159
160
|
megadetector/postprocessing/md_to_coco.py,sha256=VfAXHSFZsMfzu1ppetZGDEG9ennJouIuUmFHuJdNtQY,15967
|
|
160
161
|
megadetector/postprocessing/md_to_labelme.py,sha256=DDCsQpxZXQxWjPlsg1DM5yE33Fc_c8KatuDgt66Q8rQ,11696
|
|
161
162
|
megadetector/postprocessing/md_to_wi.py,sha256=Yq-WdbWPcwkGkF5Iw7c6Ua6Ky723jYwJWY8Kl_KfgRE,1271
|
|
162
163
|
megadetector/postprocessing/merge_detections.py,sha256=GfoDtDUdOyv9M4p8tTzUuaEPsgnmHu1pgnPsvSUfOq0,17778
|
|
163
|
-
megadetector/postprocessing/postprocess_batch_results.py,sha256=
|
|
164
|
+
megadetector/postprocessing/postprocess_batch_results.py,sha256=BusnOgrFCVv2p6NUd2k-uhiQKWHGXwhtVupUo4TgycE,85582
|
|
164
165
|
megadetector/postprocessing/remap_detection_categories.py,sha256=d9IYTa0i_KbbrarJc_mczABmdwypscl5-KpK8Hx_z8o,6640
|
|
165
166
|
megadetector/postprocessing/render_detection_confusion_matrix.py,sha256=_wsk4W0PbNiqmFuHy-EA0Z07B1tQLMsdCTPatnHAdZw,27382
|
|
166
167
|
megadetector/postprocessing/separate_detections_into_folders.py,sha256=ua7mBe1Vg4-_JC6ZBhqPfv6uMBqfpIR4o_cmZo-2obY,33836
|
|
@@ -174,35 +175,35 @@ megadetector/taxonomy_mapping/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
|
174
175
|
megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py,sha256=6D_YHTeWTs6O8S9ABog2t9-wfQSh9dW2k9XTqXUZKfo,17927
|
|
175
176
|
megadetector/taxonomy_mapping/map_new_lila_datasets.py,sha256=q6GZ3uUhFaLaGrVPvViZcyzbZJARR3Q557oGV8h0D9Y,4245
|
|
176
177
|
megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py,sha256=kemgxFTriz92Z4fJL0FSimmhhLtC3nBZuZ-Cy9cl1kM,4812
|
|
177
|
-
megadetector/taxonomy_mapping/preview_lila_taxonomy.py,sha256=
|
|
178
|
+
megadetector/taxonomy_mapping/preview_lila_taxonomy.py,sha256=d1m5U0ov6Zdf0Y5SiidqVfqHpMjmWPpliVD5bwMMvQ8,17698
|
|
178
179
|
megadetector/taxonomy_mapping/retrieve_sample_image.py,sha256=4cfWsLRwS_EwAmQr2p5tA_W6glBK71tSjPfaHxUZQWs,1979
|
|
179
180
|
megadetector/taxonomy_mapping/simple_image_download.py,sha256=wLhyMSocX_JhDGA6yLbEfpysz8MMI8YFJWaxyA-GZ9c,6932
|
|
180
181
|
megadetector/taxonomy_mapping/species_lookup.py,sha256=Z7nVoyh7bi8dHT0cJ7U6lEyi2xJOQra_rlv-DREZ_-U,29811
|
|
181
182
|
megadetector/taxonomy_mapping/taxonomy_csv_checker.py,sha256=A_zPwzY-ERz6xawxgk2Tpfsycl-1sDcjUiuaXXBppi8,4850
|
|
182
|
-
megadetector/taxonomy_mapping/taxonomy_graph.py,sha256=
|
|
183
|
+
megadetector/taxonomy_mapping/taxonomy_graph.py,sha256=fexDfHIqW9mJJ34JPbeW0FWQ56_6lUu1RRoe2B5rQjg,12262
|
|
183
184
|
megadetector/taxonomy_mapping/validate_lila_category_mappings.py,sha256=1qyZr23bvZSVUYLQnO1XAtIZ4jdpARA5dxt8euKVyOA,2527
|
|
184
185
|
megadetector/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
185
186
|
megadetector/utils/azure_utils.py,sha256=0BdnkG2hW-X0yFpsJqmBhOd2wysz_LvhuyImPJMVPJs,6271
|
|
186
|
-
megadetector/utils/ct_utils.py,sha256=
|
|
187
|
+
megadetector/utils/ct_utils.py,sha256=cR1qbP_h-xh7020nuGrB55TvIytERHQrR6xuSXIkQJQ,27399
|
|
187
188
|
megadetector/utils/directory_listing.py,sha256=42t8lDz8V3vPkGTGUd-UnSw2xKpqfpvb4BT-6xVAUmY,9689
|
|
188
189
|
megadetector/utils/gpu_test.py,sha256=1NxvyJrD4mq_uuCysT0q9pSJyR-gpdQogB6O8TP4E2Q,3665
|
|
189
190
|
megadetector/utils/md_tests.py,sha256=bMloXfts_sxG4vTEZq5pmUJ8-WLnsoU8mYkdz732YrE,75028
|
|
190
|
-
megadetector/utils/path_utils.py,sha256=
|
|
191
|
+
megadetector/utils/path_utils.py,sha256=nl74fQfhoofE8Qpmb20mkP9xZYFIkNBgV88XvhnIMV0,53155
|
|
191
192
|
megadetector/utils/process_utils.py,sha256=K7-ZW_bJbMgeDBLDhYHMV84urM8H7L6IddQS5z3UgBw,5824
|
|
192
193
|
megadetector/utils/sas_blob_utils.py,sha256=k76EcMmJc_otrEHcfV2fxAC6fNhxU88FxM3ddSYrsKU,16917
|
|
193
|
-
megadetector/utils/split_locations_into_train_val.py,sha256=
|
|
194
|
+
megadetector/utils/split_locations_into_train_val.py,sha256=ldTWD5s8Q14nCGedvL70FAf7W8xZ9cBtTxIWFeI7ehM,10711
|
|
194
195
|
megadetector/utils/string_utils.py,sha256=ZQapJodzvTDyQhjZgMoMl3-9bqnKAUlORpws8Db9AkA,2050
|
|
195
196
|
megadetector/utils/url_utils.py,sha256=yybWwJ-vl2A6Fci66i-xt_dl3Uqh72Ylnb8XOT2Grog,14835
|
|
196
|
-
megadetector/utils/wi_utils.py,sha256=
|
|
197
|
+
megadetector/utils/wi_utils.py,sha256=OmYSTSCiWIuEnDHcQimPPrsHWPCEL9sMGQn6G8B8XTc,100877
|
|
197
198
|
megadetector/utils/write_html_image_list.py,sha256=MhVAAv6th9Q2fldtE8hp_hHWFgJ_pcKJEk3YiK6dWY4,9415
|
|
198
199
|
megadetector/visualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
199
200
|
megadetector/visualization/plot_utils.py,sha256=lOfU3uPrcuHZagV_1SN8erT8PujIepocgw6KZ17Ej6c,10671
|
|
200
201
|
megadetector/visualization/render_images_with_thumbnails.py,sha256=kgJYW8BsqRO4C7T3sqItdBuSkZ64I1vOtIWAsVG4XBI,10589
|
|
201
|
-
megadetector/visualization/visualization_utils.py,sha256=
|
|
202
|
+
megadetector/visualization/visualization_utils.py,sha256=5PLL8Wa_TKmrItPH6z_n-b8h5EHn84qxce0VM3paG2k,76276
|
|
202
203
|
megadetector/visualization/visualize_db.py,sha256=h1NSK_4ZR_NlwBn2JrYyCOv9C7_iqmLWWOk4T6YkyXw,25280
|
|
203
|
-
megadetector/visualization/visualize_detector_output.py,sha256=
|
|
204
|
-
megadetector-5.0.
|
|
205
|
-
megadetector-5.0.
|
|
206
|
-
megadetector-5.0.
|
|
207
|
-
megadetector-5.0.
|
|
208
|
-
megadetector-5.0.
|
|
204
|
+
megadetector/visualization/visualize_detector_output.py,sha256=1zjess07B7FevT7lThNqotdNrMPKdUnPmEu1zyMxci0,20278
|
|
205
|
+
megadetector-5.0.28.dist-info/licenses/LICENSE,sha256=RMa3qq-7Cyk7DdtqRj_bP1oInGFgjyHn9-PZ3PcrqIs,1100
|
|
206
|
+
megadetector-5.0.28.dist-info/METADATA,sha256=9uFX27-meAxvB_zHprROT4U7qhss6MDFYvobGdGjPr8,6449
|
|
207
|
+
megadetector-5.0.28.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
|
|
208
|
+
megadetector-5.0.28.dist-info/top_level.txt,sha256=wf9DXa8EwiOSZ4G5IPjakSxBPxTDjhYYnqWRfR-zS4M,13
|
|
209
|
+
megadetector-5.0.28.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|