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.

Files changed (30) hide show
  1. megadetector/data_management/animl_to_md.py +158 -0
  2. megadetector/data_management/zamba_to_md.py +188 -0
  3. megadetector/detection/process_video.py +165 -946
  4. megadetector/detection/pytorch_detector.py +575 -276
  5. megadetector/detection/run_detector_batch.py +629 -202
  6. megadetector/detection/run_md_and_speciesnet.py +1319 -0
  7. megadetector/detection/video_utils.py +243 -107
  8. megadetector/postprocessing/classification_postprocessing.py +12 -1
  9. megadetector/postprocessing/combine_batch_outputs.py +2 -0
  10. megadetector/postprocessing/compare_batch_results.py +21 -2
  11. megadetector/postprocessing/merge_detections.py +16 -12
  12. megadetector/postprocessing/separate_detections_into_folders.py +1 -1
  13. megadetector/postprocessing/subset_json_detector_output.py +1 -3
  14. megadetector/postprocessing/validate_batch_results.py +25 -2
  15. megadetector/tests/__init__.py +0 -0
  16. megadetector/tests/test_nms_synthetic.py +335 -0
  17. megadetector/utils/ct_utils.py +69 -5
  18. megadetector/utils/extract_frames_from_video.py +303 -0
  19. megadetector/utils/md_tests.py +583 -524
  20. megadetector/utils/path_utils.py +4 -15
  21. megadetector/utils/wi_utils.py +20 -4
  22. megadetector/visualization/visualization_utils.py +1 -1
  23. megadetector/visualization/visualize_db.py +8 -22
  24. megadetector/visualization/visualize_detector_output.py +7 -5
  25. megadetector/visualization/visualize_video_output.py +607 -0
  26. {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/METADATA +134 -135
  27. {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/RECORD +30 -23
  28. {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/licenses/LICENSE +0 -0
  29. {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/top_level.txt +0 -0
  30. {megadetector-10.0.2.dist-info → megadetector-10.0.4.dist-info}/WHEEL +0 -0
@@ -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
- #%% Platform-independent way to open files in their associated application
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
@@ -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
- return taxonomy_info['class'] + ';' + \
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 out without bboxes)
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
- def main(): # noqa
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=None,
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=None,
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.1,
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__':