megadetector 10.0.2__py3-none-any.whl → 10.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.
- megadetector/data_management/animl_to_md.py +158 -0
- megadetector/data_management/zamba_to_md.py +188 -0
- megadetector/detection/process_video.py +165 -946
- megadetector/detection/pytorch_detector.py +575 -276
- megadetector/detection/run_detector_batch.py +629 -202
- megadetector/detection/run_md_and_speciesnet.py +1319 -0
- megadetector/detection/video_utils.py +243 -107
- megadetector/postprocessing/classification_postprocessing.py +12 -1
- megadetector/postprocessing/combine_batch_outputs.py +2 -0
- megadetector/postprocessing/compare_batch_results.py +21 -2
- megadetector/postprocessing/merge_detections.py +16 -12
- megadetector/postprocessing/separate_detections_into_folders.py +1 -1
- megadetector/postprocessing/subset_json_detector_output.py +1 -3
- megadetector/postprocessing/validate_batch_results.py +25 -2
- megadetector/tests/__init__.py +0 -0
- megadetector/tests/test_nms_synthetic.py +335 -0
- megadetector/utils/ct_utils.py +69 -5
- megadetector/utils/extract_frames_from_video.py +303 -0
- megadetector/utils/md_tests.py +583 -524
- megadetector/utils/path_utils.py +4 -15
- megadetector/utils/wi_utils.py +20 -4
- megadetector/visualization/visualization_utils.py +1 -1
- megadetector/visualization/visualize_db.py +8 -22
- megadetector/visualization/visualize_detector_output.py +7 -5
- megadetector/visualization/visualize_video_output.py +607 -0
- {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/METADATA +134 -135
- {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/RECORD +30 -23
- {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/licenses/LICENSE +0 -0
- {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/top_level.txt +0 -0
- {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/WHEEL +0 -0
megadetector/utils/path_utils.py
CHANGED
|
@@ -36,6 +36,7 @@ from tqdm import tqdm
|
|
|
36
36
|
from megadetector.utils.ct_utils import is_iterable
|
|
37
37
|
from megadetector.utils.ct_utils import make_test_folder
|
|
38
38
|
from megadetector.utils.ct_utils import sort_dictionary_by_value
|
|
39
|
+
from megadetector.utils.ct_utils import environment_is_wsl
|
|
39
40
|
|
|
40
41
|
# Should all be lower-case
|
|
41
42
|
IMG_EXTENSIONS = ('.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff', '.bmp')
|
|
@@ -622,21 +623,7 @@ def is_executable(filename):
|
|
|
622
623
|
return which(filename) is not None
|
|
623
624
|
|
|
624
625
|
|
|
625
|
-
#%%
|
|
626
|
-
|
|
627
|
-
def environment_is_wsl():
|
|
628
|
-
"""
|
|
629
|
-
Determines whether we're running in WSL.
|
|
630
|
-
|
|
631
|
-
Returns:
|
|
632
|
-
True if we're running in WSL.
|
|
633
|
-
"""
|
|
634
|
-
|
|
635
|
-
if sys.platform not in ('linux','posix'):
|
|
636
|
-
return False
|
|
637
|
-
platform_string = ' '.join(platform.uname()).lower()
|
|
638
|
-
return 'microsoft' in platform_string and 'wsl' in platform_string
|
|
639
|
-
|
|
626
|
+
#%% WSL utilities
|
|
640
627
|
|
|
641
628
|
def wsl_path_to_windows_path(filename, failure_behavior='none'):
|
|
642
629
|
r"""
|
|
@@ -731,6 +718,8 @@ def windows_path_to_wsl_path(filename, failure_behavior='none'):
|
|
|
731
718
|
# ...def window_path_to_wsl_path(...)
|
|
732
719
|
|
|
733
720
|
|
|
721
|
+
#%% Platform-independent file openers
|
|
722
|
+
|
|
734
723
|
def open_file_in_chrome(filename):
|
|
735
724
|
"""
|
|
736
725
|
Open a file in chrome, regardless of file type. I typically use this to open
|
megadetector/utils/wi_utils.py
CHANGED
|
@@ -1869,22 +1869,30 @@ country_code_to_country = None
|
|
|
1869
1869
|
|
|
1870
1870
|
#%% Functions related to geofencing and taxonomy mapping
|
|
1871
1871
|
|
|
1872
|
-
def taxonomy_info_to_taxonomy_string(taxonomy_info):
|
|
1872
|
+
def taxonomy_info_to_taxonomy_string(taxonomy_info, include_taxon_id_and_common_name=False):
|
|
1873
1873
|
"""
|
|
1874
|
-
Convert a taxonomy record in dict format to a semicolon-delimited string
|
|
1874
|
+
Convert a taxonomy record in dict format to a five- or seven-token semicolon-delimited string
|
|
1875
1875
|
|
|
1876
1876
|
Args:
|
|
1877
1877
|
taxonomy_info (dict): dict in the format stored in, e.g., taxonomy_string_to_taxonomy_info
|
|
1878
|
+
include_taxon_id_and_common_name (bool, optional): by default, this function returns a
|
|
1879
|
+
five-token string of latin names; if this argument is True, it includes the leading
|
|
1880
|
+
(GUID) and trailing (common name) tokens
|
|
1878
1881
|
|
|
1879
1882
|
Returns:
|
|
1880
1883
|
str: string in the format used as keys in, e.g., taxonomy_string_to_taxonomy_info
|
|
1881
1884
|
"""
|
|
1882
|
-
|
|
1885
|
+
s = taxonomy_info['class'] + ';' + \
|
|
1883
1886
|
taxonomy_info['order'] + ';' + \
|
|
1884
1887
|
taxonomy_info['family'] + ';' + \
|
|
1885
1888
|
taxonomy_info['genus'] + ';' + \
|
|
1886
1889
|
taxonomy_info['species']
|
|
1887
1890
|
|
|
1891
|
+
if include_taxon_id_and_common_name:
|
|
1892
|
+
s = taxonomy_info['taxon_id'] + ';' + s + ';' + taxonomy_info['common_name']
|
|
1893
|
+
|
|
1894
|
+
return s
|
|
1895
|
+
|
|
1888
1896
|
|
|
1889
1897
|
def initialize_taxonomy_info(taxonomy_file,force_init=False,encoding='cp1252'):
|
|
1890
1898
|
"""
|
|
@@ -2504,7 +2512,7 @@ if False:
|
|
|
2504
2512
|
initialize_geofencing(geofencing_file, country_code_file, force_init=True)
|
|
2505
2513
|
initialize_taxonomy_info(taxonomy_file, force_init=True, encoding=encoding)
|
|
2506
2514
|
|
|
2507
|
-
from megadetector.utils.path_utils import open_file; open_file(geofencing_file)
|
|
2515
|
+
# from megadetector.utils.path_utils import open_file; open_file(geofencing_file)
|
|
2508
2516
|
|
|
2509
2517
|
|
|
2510
2518
|
#%% Generate a block list
|
|
@@ -2530,6 +2538,14 @@ if False:
|
|
|
2530
2538
|
print(rows)
|
|
2531
2539
|
|
|
2532
2540
|
|
|
2541
|
+
#%% Look up taxonomy info for a common name
|
|
2542
|
+
|
|
2543
|
+
common_name = 'domestic horse'
|
|
2544
|
+
info = common_name_to_taxonomy_info[common_name]
|
|
2545
|
+
s = taxonomy_info_to_taxonomy_string(info,include_taxon_id_and_common_name=True)
|
|
2546
|
+
print(s)
|
|
2547
|
+
|
|
2548
|
+
|
|
2533
2549
|
#%% Generate a block-except list
|
|
2534
2550
|
|
|
2535
2551
|
block_except_list = 'ALB,AND,ARM,AUT,AZE,BEL,BGR,BIH,BLR,CHE,CYP,CZE,DEU,DNK,ESP,EST,FIN,FRA,GBR,GEO,GRC,HRV,HUN,IRL,IRN,IRQ,ISL,ISR,ITA,KAZ,LIE,LTU,LUX,LVA,MDA,MKD,MLT,MNE,NLD,NOR,POL,PRT,ROU,RUS,SMR,SRB,SVK,SVN,SWE,TUR,UKR,UZB'
|
|
@@ -552,7 +552,7 @@ def render_detection_bounding_boxes(detections,
|
|
|
552
552
|
custom_strings (list of str, optional): optional set of strings to append to detection labels, should
|
|
553
553
|
have the same length as [detections]. Appended before any classification labels.
|
|
554
554
|
box_sort_order (str, optional): sorting scheme for detection boxes, can be None, "confidence", or
|
|
555
|
-
"reverse_confidence".
|
|
555
|
+
"reverse_confidence". "confidence" puts the highest-confidence boxes on top.
|
|
556
556
|
verbose (bool, optional): enable additional debug output
|
|
557
557
|
"""
|
|
558
558
|
|
|
@@ -321,7 +321,7 @@ def visualize_db(db_path, output_dir, image_base_dir, options=None):
|
|
|
321
321
|
box_classes = []
|
|
322
322
|
box_score_strings = []
|
|
323
323
|
|
|
324
|
-
# All the class labels we've seen for this image (with
|
|
324
|
+
# All the class labels we've seen for this image (with or without bboxes)
|
|
325
325
|
image_categories = set()
|
|
326
326
|
|
|
327
327
|
extra_annotation_field_string = ''
|
|
@@ -368,6 +368,7 @@ def visualize_db(db_path, output_dir, image_base_dir, options=None):
|
|
|
368
368
|
category_name = category_name.replace('"','')
|
|
369
369
|
category_name = '<a href="https://www.google.com/search?tbm=isch&q={}">{}</a>'.format(
|
|
370
370
|
category_name,category_name)
|
|
371
|
+
|
|
371
372
|
image_categories.add(category_name)
|
|
372
373
|
|
|
373
374
|
assert not ('bbox' in anno and 'bbox_relative' in anno), \
|
|
@@ -522,7 +523,7 @@ def visualize_db(db_path, output_dir, image_base_dir, options=None):
|
|
|
522
523
|
|
|
523
524
|
return True
|
|
524
525
|
|
|
525
|
-
# ...def render_image_info
|
|
526
|
+
# ...def render_image_info(...)
|
|
526
527
|
|
|
527
528
|
print('Rendering images')
|
|
528
529
|
start_time = time.time()
|
|
@@ -589,7 +590,7 @@ def visualize_db(db_path, output_dir, image_base_dir, options=None):
|
|
|
589
590
|
|
|
590
591
|
return html_output_file,image_db
|
|
591
592
|
|
|
592
|
-
# def visualize_db(...)
|
|
593
|
+
# ...def visualize_db(...)
|
|
593
594
|
|
|
594
595
|
|
|
595
596
|
#%% Command-line driver
|
|
@@ -603,8 +604,10 @@ def _args_to_object(args, obj):
|
|
|
603
604
|
if not n.startswith('_'):
|
|
604
605
|
setattr(obj, n, v)
|
|
605
606
|
|
|
606
|
-
|
|
607
|
-
|
|
607
|
+
def main():
|
|
608
|
+
"""
|
|
609
|
+
Command-line driver for visualize_db
|
|
610
|
+
"""
|
|
608
611
|
|
|
609
612
|
parser = argparse.ArgumentParser()
|
|
610
613
|
parser.add_argument('db_path', action='store', type=str,
|
|
@@ -642,20 +645,3 @@ def main(): # noqa
|
|
|
642
645
|
|
|
643
646
|
if __name__ == '__main__':
|
|
644
647
|
main()
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
#%% Interactive driver
|
|
648
|
-
|
|
649
|
-
if False:
|
|
650
|
-
|
|
651
|
-
#%%
|
|
652
|
-
|
|
653
|
-
db_path = r'e:\wildlife_data\missouri_camera_traps\missouri_camera_traps_set1.json'
|
|
654
|
-
output_dir = r'e:\wildlife_data\missouri_camera_traps\preview'
|
|
655
|
-
image_base_dir = r'e:\wildlife_data\missouri_camera_traps'
|
|
656
|
-
|
|
657
|
-
options = DbVizOptions()
|
|
658
|
-
options.num_to_visualize = 100
|
|
659
|
-
|
|
660
|
-
html_output_file, db = visualize_db(db_path,output_dir,image_base_dir,options)
|
|
661
|
-
# os.startfile(html_output_file)
|
|
@@ -24,10 +24,13 @@ from megadetector.detection.run_detector import get_typical_confidence_threshold
|
|
|
24
24
|
from megadetector.utils.ct_utils import get_max_conf
|
|
25
25
|
from megadetector.utils import write_html_image_list
|
|
26
26
|
from megadetector.utils.path_utils import path_is_abs
|
|
27
|
+
from megadetector.utils.path_utils import open_file
|
|
27
28
|
from megadetector.utils.wi_utils import load_md_or_speciesnet_file
|
|
28
29
|
from megadetector.visualization import visualization_utils as vis_utils
|
|
29
30
|
from megadetector.visualization.visualization_utils import blur_detections
|
|
30
31
|
|
|
32
|
+
default_box_sort_order = 'confidence'
|
|
33
|
+
|
|
31
34
|
|
|
32
35
|
#%% Constants
|
|
33
36
|
|
|
@@ -49,7 +52,7 @@ def _render_image(entry,
|
|
|
49
52
|
out_dir,
|
|
50
53
|
images_dir,
|
|
51
54
|
output_image_width,
|
|
52
|
-
box_sort_order=
|
|
55
|
+
box_sort_order=default_box_sort_order,
|
|
53
56
|
category_names_to_blur=None):
|
|
54
57
|
"""
|
|
55
58
|
Internal function for rendering a single image.
|
|
@@ -153,7 +156,7 @@ def visualize_detector_output(detector_output_path,
|
|
|
153
156
|
parallelize_rendering=False,
|
|
154
157
|
parallelize_rendering_n_cores=10,
|
|
155
158
|
parallelize_rendering_with_threads=True,
|
|
156
|
-
box_sort_order=
|
|
159
|
+
box_sort_order=default_box_sort_order,
|
|
157
160
|
category_names_to_blur=None):
|
|
158
161
|
"""
|
|
159
162
|
Draws bounding boxes on images given the output of a detector.
|
|
@@ -397,7 +400,7 @@ def main(): # noqa
|
|
|
397
400
|
'--category_names_to_blur', default=None, type=str,
|
|
398
401
|
help='Comma-separated list of category names to blur (or a single category name, typically "person")')
|
|
399
402
|
parser.add_argument(
|
|
400
|
-
'--classification_confidence', type=float, default=0.
|
|
403
|
+
'--classification_confidence', type=float, default=0.3,
|
|
401
404
|
help='If classification results are present, render results above this threshold')
|
|
402
405
|
|
|
403
406
|
if len(sys.argv[1:]) == 0:
|
|
@@ -424,8 +427,7 @@ def main(): # noqa
|
|
|
424
427
|
html_output_file=args.html_output_file,
|
|
425
428
|
category_names_to_blur=category_names_to_blur)
|
|
426
429
|
|
|
427
|
-
if args.html_output_file is not None and args.open_html_output_file:
|
|
428
|
-
from megadetector.utils.path_utils import open_file
|
|
430
|
+
if (args.html_output_file is not None) and args.open_html_output_file:
|
|
429
431
|
open_file(args.html_output_file)
|
|
430
432
|
|
|
431
433
|
if __name__ == '__main__':
|