megadetector 10.0.9__py3-none-any.whl → 10.0.11__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 (84) hide show
  1. megadetector/data_management/animl_to_md.py +5 -2
  2. megadetector/data_management/cct_json_utils.py +4 -2
  3. megadetector/data_management/cct_to_md.py +5 -4
  4. megadetector/data_management/cct_to_wi.py +5 -1
  5. megadetector/data_management/coco_to_yolo.py +3 -2
  6. megadetector/data_management/databases/combine_coco_camera_traps_files.py +4 -4
  7. megadetector/data_management/databases/integrity_check_json_db.py +2 -2
  8. megadetector/data_management/databases/subset_json_db.py +0 -3
  9. megadetector/data_management/generate_crops_from_cct.py +6 -4
  10. megadetector/data_management/get_image_sizes.py +5 -35
  11. megadetector/data_management/labelme_to_coco.py +10 -6
  12. megadetector/data_management/labelme_to_yolo.py +19 -28
  13. megadetector/data_management/lila/create_lila_test_set.py +22 -2
  14. megadetector/data_management/lila/generate_lila_per_image_labels.py +7 -5
  15. megadetector/data_management/lila/lila_common.py +2 -2
  16. megadetector/data_management/lila/test_lila_metadata_urls.py +0 -1
  17. megadetector/data_management/ocr_tools.py +6 -10
  18. megadetector/data_management/read_exif.py +69 -13
  19. megadetector/data_management/remap_coco_categories.py +1 -1
  20. megadetector/data_management/remove_exif.py +10 -5
  21. megadetector/data_management/rename_images.py +20 -13
  22. megadetector/data_management/resize_coco_dataset.py +10 -4
  23. megadetector/data_management/speciesnet_to_md.py +3 -3
  24. megadetector/data_management/yolo_output_to_md_output.py +3 -1
  25. megadetector/data_management/yolo_to_coco.py +28 -19
  26. megadetector/detection/change_detection.py +26 -18
  27. megadetector/detection/process_video.py +1 -1
  28. megadetector/detection/pytorch_detector.py +5 -5
  29. megadetector/detection/run_detector.py +34 -10
  30. megadetector/detection/run_detector_batch.py +60 -42
  31. megadetector/detection/run_inference_with_yolov5_val.py +3 -1
  32. megadetector/detection/run_md_and_speciesnet.py +282 -110
  33. megadetector/detection/run_tiled_inference.py +7 -7
  34. megadetector/detection/tf_detector.py +4 -6
  35. megadetector/detection/video_utils.py +9 -6
  36. megadetector/postprocessing/add_max_conf.py +4 -4
  37. megadetector/postprocessing/categorize_detections_by_size.py +3 -2
  38. megadetector/postprocessing/classification_postprocessing.py +19 -21
  39. megadetector/postprocessing/combine_batch_outputs.py +3 -2
  40. megadetector/postprocessing/compare_batch_results.py +49 -27
  41. megadetector/postprocessing/convert_output_format.py +8 -6
  42. megadetector/postprocessing/create_crop_folder.py +13 -4
  43. megadetector/postprocessing/generate_csv_report.py +22 -8
  44. megadetector/postprocessing/load_api_results.py +8 -4
  45. megadetector/postprocessing/md_to_coco.py +2 -3
  46. megadetector/postprocessing/md_to_labelme.py +12 -8
  47. megadetector/postprocessing/md_to_wi.py +2 -1
  48. megadetector/postprocessing/merge_detections.py +4 -6
  49. megadetector/postprocessing/postprocess_batch_results.py +4 -3
  50. megadetector/postprocessing/remap_detection_categories.py +6 -3
  51. megadetector/postprocessing/render_detection_confusion_matrix.py +18 -10
  52. megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +1 -1
  53. megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +5 -3
  54. megadetector/postprocessing/separate_detections_into_folders.py +10 -4
  55. megadetector/postprocessing/subset_json_detector_output.py +1 -1
  56. megadetector/postprocessing/top_folders_to_bottom.py +22 -7
  57. megadetector/postprocessing/validate_batch_results.py +1 -1
  58. megadetector/taxonomy_mapping/map_new_lila_datasets.py +59 -3
  59. megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +1 -1
  60. megadetector/taxonomy_mapping/preview_lila_taxonomy.py +26 -17
  61. megadetector/taxonomy_mapping/species_lookup.py +51 -2
  62. megadetector/utils/ct_utils.py +9 -4
  63. megadetector/utils/directory_listing.py +3 -0
  64. megadetector/utils/extract_frames_from_video.py +4 -0
  65. megadetector/utils/gpu_test.py +6 -6
  66. megadetector/utils/md_tests.py +21 -21
  67. megadetector/utils/path_utils.py +171 -36
  68. megadetector/utils/split_locations_into_train_val.py +0 -4
  69. megadetector/utils/string_utils.py +21 -0
  70. megadetector/utils/url_utils.py +5 -3
  71. megadetector/utils/wi_platform_utils.py +168 -24
  72. megadetector/utils/wi_taxonomy_utils.py +38 -8
  73. megadetector/utils/write_html_image_list.py +1 -2
  74. megadetector/visualization/plot_utils.py +31 -19
  75. megadetector/visualization/render_images_with_thumbnails.py +3 -0
  76. megadetector/visualization/visualization_utils.py +18 -7
  77. megadetector/visualization/visualize_db.py +9 -26
  78. megadetector/visualization/visualize_detector_output.py +1 -0
  79. megadetector/visualization/visualize_video_output.py +14 -2
  80. {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/METADATA +1 -1
  81. {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/RECORD +84 -84
  82. {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/WHEEL +0 -0
  83. {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/licenses/LICENSE +0 -0
  84. {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/top_level.txt +0 -0
@@ -13,8 +13,7 @@ check out run_detector_batch.py**.
13
13
  That said, this script (run_detector.py) is a good way to test our detector on a handful of images
14
14
  and get super-satisfying, graphical results.
15
15
 
16
- If you would like to *not* use the GPU on the machine, set the environment
17
- variable CUDA_VISIBLE_DEVICES to "-1".
16
+ If you would like to *not* use the GPU, set the environment variable CUDA_VISIBLE_DEVICES to "-1".
18
17
 
19
18
  This script will only consider detections with > 0.005 confidence at all times.
20
19
  The threshold you provide is only for rendering the results. If you need to
@@ -79,6 +78,10 @@ DEFAULT_DETECTOR_LABEL_MAP = {
79
78
  # models other than MegaDetector.
80
79
  USE_MODEL_NATIVE_CLASSES = False
81
80
 
81
+ # Detection threshold to recommend to callers when all other mechanisms for choosing
82
+ # a model-specific threshold fail
83
+ fallback_detection_threshold = 0.2
84
+
82
85
  # Maps a variety of strings that might occur in filenames to canonical version numbers.
83
86
  #
84
87
  # Order matters here.
@@ -215,7 +218,8 @@ known_models = {
215
218
  {
216
219
  'url':model_url_base + 'md_v1000.0.0-redwood.pt',
217
220
  'normalized_typical_inference_speed':1.0,
218
- 'md5':'74474b3aec9cf1a990da38b37ddf9197'
221
+ 'md5':'74474b3aec9cf1a990da38b37ddf9197',
222
+ 'typical_detection_threshold':0.3
219
223
  },
220
224
  'v1000.0.0-spruce':
221
225
  {
@@ -515,19 +519,34 @@ def get_typical_confidence_threshold_from_results(results):
515
519
  with open(results,'r') as f:
516
520
  results = json.load(f)
517
521
 
522
+ default_threshold = None
523
+
524
+ # Best case: the .json file tells us the default threshold
518
525
  if 'detector_metadata' in results['info'] and \
519
526
  'typical_detection_threshold' in results['info']['detector_metadata']:
520
527
  default_threshold = results['info']['detector_metadata']['typical_detection_threshold']
528
+ # Worst case: we don't even know what detector this is
521
529
  elif ('detector' not in results['info']) or (results['info']['detector'] is None):
522
530
  print('Warning: detector version not available in results file, using MDv5 defaults')
523
531
  detector_metadata = get_detector_metadata_from_version_string('v5a.0.0')
524
532
  default_threshold = detector_metadata['typical_detection_threshold']
533
+ # We know what detector this is, but it doesn't have a default threshold
534
+ # in the .json file
525
535
  else:
526
536
  print('Warning: detector metadata not available in results file, inferring from MD version')
527
- detector_filename = results['info']['detector']
528
- detector_version = get_detector_version_from_filename(detector_filename)
529
- detector_metadata = get_detector_metadata_from_version_string(detector_version)
530
- default_threshold = detector_metadata['typical_detection_threshold']
537
+ try:
538
+ detector_filename = results['info']['detector']
539
+ detector_version = get_detector_version_from_filename(detector_filename)
540
+ detector_metadata = get_detector_metadata_from_version_string(detector_version)
541
+ if 'typical_detection_threshold' in detector_metadata:
542
+ default_threshold = detector_metadata['typical_detection_threshold']
543
+ except Exception:
544
+ pass
545
+
546
+ if default_threshold is None:
547
+ print('Could not determine threshold, using fallback threshold of {}'.format(
548
+ fallback_detection_threshold))
549
+ default_threshold = fallback_detection_threshold
531
550
 
532
551
  return default_threshold
533
552
 
@@ -546,7 +565,7 @@ def is_gpu_available(model_file):
546
565
  """
547
566
 
548
567
  if model_file.endswith('.pb'):
549
- import tensorflow.compat.v1 as tf
568
+ import tensorflow.compat.v1 as tf # type: ignore
550
569
  gpu_available = tf.test.is_gpu_available()
551
570
  print('TensorFlow version:', tf.__version__)
552
571
  print('tf.test.is_gpu_available:', gpu_available)
@@ -741,8 +760,9 @@ def load_and_run_detector(model_file,
741
760
  fn = '{}{}{}'.format(name, DETECTION_FILENAME_INSERT, '.jpg')
742
761
  if fn in output_filename_collision_counts:
743
762
  n_collisions = output_filename_collision_counts[fn]
763
+ fn_original = fn
744
764
  fn = '{:0>4d}'.format(n_collisions) + '_' + fn
745
- output_filename_collision_counts[fn] += 1
765
+ output_filename_collision_counts[fn_original] += 1
746
766
  else:
747
767
  output_filename_collision_counts[fn] = 0
748
768
  fn = os.path.join(output_dir, fn)
@@ -847,7 +867,11 @@ def _validate_zip_file(file_path, file_description='file'):
847
867
  """
848
868
  try:
849
869
  with zipfile.ZipFile(file_path, 'r') as zipf:
850
- zipf.testzip()
870
+ corrupt_file = zipf.testzip()
871
+ if corrupt_file is not None:
872
+ print('{} {} contains at least one corrupt file: {}'.format(
873
+ file_description.capitalize(), file_path, corrupt_file))
874
+ return False
851
875
  return True
852
876
  except (zipfile.BadZipFile, zipfile.LargeZipFile) as e:
853
877
  print('{} {} appears to be corrupted (bad zip): {}'.format(
@@ -94,10 +94,10 @@ max_queue_size = 10
94
94
  # How often should we print progress when using the image queue?
95
95
  n_queue_print = 1000
96
96
 
97
- # Only used if --include_exif_data or --include_image_timestamp are supplied
98
- exif_options = read_exif.ReadExifOptions()
99
- exif_options.processing_library = 'pil'
100
- exif_options.byte_handling = 'convert_to_string'
97
+ # Only used if --include_exif_tags or --include_image_timestamp are supplied
98
+ exif_options_base = read_exif.ReadExifOptions()
99
+ exif_options_base.processing_library = 'pil'
100
+ exif_options_base.byte_handling = 'convert_to_string'
101
101
 
102
102
  # Only relevant when we're running our test harness; because bugs in batch
103
103
  # inference are dependent on batch grouping, we randomize batch grouping
@@ -208,7 +208,7 @@ def _consumer_func(q,
208
208
  image_size=None,
209
209
  include_image_size=False,
210
210
  include_image_timestamp=False,
211
- include_exif_data=False,
211
+ include_exif_tags=None,
212
212
  augment=False,
213
213
  detector_options=None,
214
214
  preprocess_on_image_queue=default_preprocess_on_image_queue,
@@ -232,7 +232,7 @@ def _consumer_func(q,
232
232
  image_size (int, optional): image size to use for inference
233
233
  include_image_size (bool, optional): include image dimensions in output
234
234
  include_image_timestamp (bool, optional): include image timestamps in output
235
- include_exif_data (bool, optional): include EXIF data in output
235
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
236
236
  augment (bool, optional): enable image augmentation
237
237
  detector_options (dict, optional): key/value pairs that are interpreted differently
238
238
  by different detectors
@@ -334,7 +334,7 @@ def _consumer_func(q,
334
334
  image_size=image_size,
335
335
  include_image_size=include_image_size,
336
336
  include_image_timestamp=include_image_timestamp,
337
- include_exif_data=include_exif_data,
337
+ include_exif_tags=include_exif_tags,
338
338
  augment=augment)
339
339
  results.extend(batch_results)
340
340
 
@@ -411,7 +411,7 @@ def _consumer_func(q,
411
411
  image_size=image_size,
412
412
  include_image_size=include_image_size,
413
413
  include_image_timestamp=include_image_timestamp,
414
- include_exif_data=include_exif_data,
414
+ include_exif_tags=include_exif_tags,
415
415
  augment=augment)
416
416
  results.extend(batch_results)
417
417
 
@@ -431,7 +431,7 @@ def _consumer_func(q,
431
431
  image_size=image_size,
432
432
  include_image_size=include_image_size,
433
433
  include_image_timestamp=include_image_timestamp,
434
- include_exif_data=include_exif_data,
434
+ include_exif_tags=include_exif_tags,
435
435
  augment=augment)
436
436
  results.append(result)
437
437
  n_images_processed += 1
@@ -464,7 +464,7 @@ def _run_detector_with_image_queue(image_files,
464
464
  image_size=None,
465
465
  include_image_size=False,
466
466
  include_image_timestamp=False,
467
- include_exif_data=False,
467
+ include_exif_tags=None,
468
468
  augment=False,
469
469
  detector_options=None,
470
470
  loader_workers=default_loaders,
@@ -487,7 +487,7 @@ def _run_detector_with_image_queue(image_files,
487
487
  doing
488
488
  include_image_size (bool, optional): should we include image size in the output for each image?
489
489
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
490
- include_exif_data (bool, optional): should we include EXIF data in the output for each image?
490
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
491
491
  augment (bool, optional): enable image augmentation
492
492
  detector_options (dict, optional): key/value pairs that are interpreted differently
493
493
  by different detectors
@@ -562,7 +562,7 @@ def _run_detector_with_image_queue(image_files,
562
562
  image_size,
563
563
  include_image_size,
564
564
  include_image_timestamp,
565
- include_exif_data,
565
+ include_exif_tags,
566
566
  augment,
567
567
  detector_options,
568
568
  preprocess_on_image_queue,
@@ -579,7 +579,7 @@ def _run_detector_with_image_queue(image_files,
579
579
  image_size,
580
580
  include_image_size,
581
581
  include_image_timestamp,
582
- include_exif_data,
582
+ include_exif_tags,
583
583
  augment,
584
584
  detector_options,
585
585
  preprocess_on_image_queue,
@@ -598,7 +598,7 @@ def _run_detector_with_image_queue(image_files,
598
598
  image_size,
599
599
  include_image_size,
600
600
  include_image_timestamp,
601
- include_exif_data,
601
+ include_exif_tags,
602
602
  augment,
603
603
  detector_options,
604
604
  preprocess_on_image_queue,
@@ -680,7 +680,7 @@ def _process_batch(image_items_batch,
680
680
  image_size=None,
681
681
  include_image_size=False,
682
682
  include_image_timestamp=False,
683
- include_exif_data=False,
683
+ include_exif_tags=None,
684
684
  augment=False):
685
685
  """
686
686
  Process a batch of images using generate_detections_one_batch(). Does not necessarily return
@@ -695,7 +695,7 @@ def _process_batch(image_items_batch,
695
695
  image_size (int, optional): image size override
696
696
  include_image_size (bool, optional): include image dimensions in results
697
697
  include_image_timestamp (bool, optional): include image timestamps in results
698
- include_exif_data (bool, optional): include EXIF data in results
698
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
699
699
  augment (bool, optional): whether to use image augmentation
700
700
 
701
701
  Returns:
@@ -762,12 +762,13 @@ def _process_batch(image_items_batch,
762
762
  image_result['detections'] = \
763
763
  [det for det in image_result['detections'] if det['conf'] >= confidence_threshold]
764
764
 
765
- if include_image_size or include_image_timestamp or include_exif_data:
765
+ if include_image_size or include_image_timestamp or (include_exif_tags is not None):
766
766
 
767
767
  image = valid_images[i_valid_image]
768
768
 
769
769
  # If this was preprocessed by the producer thread, pull out the PIL version
770
770
  if isinstance(image,dict):
771
+
771
772
  image = image['img_original_pil']
772
773
 
773
774
  if include_image_size:
@@ -779,9 +780,12 @@ def _process_batch(image_items_batch,
779
780
 
780
781
  image_result['datetime'] = get_image_datetime(image)
781
782
 
782
- if include_exif_data:
783
+ if include_exif_tags is not None:
783
784
 
784
- image_result['exif_metadata'] = read_exif.read_pil_exif(image,exif_options)
785
+ exif_options = copy.copy(exif_options_base)
786
+ exif_options.tags_to_include = include_exif_tags
787
+ image_result['exif_metadata'] = read_exif.read_pil_exif(
788
+ image,exif_options)
785
789
 
786
790
  # ...if we need to store metadata
787
791
 
@@ -834,7 +838,7 @@ def _process_images(im_files,
834
838
  checkpoint_queue=None,
835
839
  include_image_size=False,
836
840
  include_image_timestamp=False,
837
- include_exif_data=False,
841
+ include_exif_tags=None,
838
842
  augment=False,
839
843
  detector_options=None,
840
844
  loader_workers=default_loaders,
@@ -856,7 +860,7 @@ def _process_images(im_files,
856
860
  checkpoint_queue (Queue, optional): internal parameter used to pass image queues around
857
861
  include_image_size (bool, optional): should we include image size in the output for each image?
858
862
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
859
- include_exif_data (bool, optional): should we include EXIF data in the output for each image?
863
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
860
864
  augment (bool, optional): enable image augmentation
861
865
  detector_options (dict, optional): key/value pairs that are interpreted differently
862
866
  by different detectors
@@ -883,18 +887,19 @@ def _process_images(im_files,
883
887
 
884
888
  if use_image_queue:
885
889
 
886
- _run_detector_with_image_queue(im_files,
890
+ results = _run_detector_with_image_queue(im_files,
887
891
  detector,
888
892
  confidence_threshold,
889
893
  quiet=quiet,
890
894
  image_size=image_size,
891
895
  include_image_size=include_image_size,
892
896
  include_image_timestamp=include_image_timestamp,
893
- include_exif_data=include_exif_data,
897
+ include_exif_tags=include_exif_tags,
894
898
  augment=augment,
895
899
  detector_options=detector_options,
896
900
  loader_workers=loader_workers,
897
901
  preprocess_on_image_queue=preprocess_on_image_queue)
902
+ return results
898
903
 
899
904
  else:
900
905
 
@@ -907,7 +912,7 @@ def _process_images(im_files,
907
912
  image_size=image_size,
908
913
  include_image_size=include_image_size,
909
914
  include_image_timestamp=include_image_timestamp,
910
- include_exif_data=include_exif_data,
915
+ include_exif_tags=include_exif_tags,
911
916
  augment=augment)
912
917
 
913
918
  if checkpoint_queue is not None:
@@ -929,7 +934,7 @@ def _process_image(im_file,
929
934
  image_size=None,
930
935
  include_image_size=False,
931
936
  include_image_timestamp=False,
932
- include_exif_data=False,
937
+ include_exif_tags=False,
933
938
  augment=False):
934
939
  """
935
940
  Runs a detector (typically MegaDetector) on a single image file.
@@ -947,7 +952,7 @@ def _process_image(im_file,
947
952
  doing
948
953
  include_image_size (bool, optional): should we include image size in the output for each image?
949
954
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
950
- include_exif_data (bool, optional): should we include EXIF data in the output for each image?
955
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
951
956
  augment (bool, optional): enable image augmentation
952
957
 
953
958
  Returns:
@@ -1000,7 +1005,9 @@ def _process_image(im_file,
1000
1005
  if include_image_timestamp:
1001
1006
  result['datetime'] = get_image_datetime(image)
1002
1007
 
1003
- if include_exif_data:
1008
+ if include_exif_tags is not None:
1009
+ exif_options = copy.copy(exif_options_base)
1010
+ exif_options.tags_to_include = include_exif_tags
1004
1011
  result['exif_metadata'] = read_exif.read_pil_exif(image,exif_options)
1005
1012
 
1006
1013
  return result
@@ -1055,7 +1062,7 @@ def load_and_run_detector_batch(model_file,
1055
1062
  class_mapping_filename=None,
1056
1063
  include_image_size=False,
1057
1064
  include_image_timestamp=False,
1058
- include_exif_data=False,
1065
+ include_exif_tags=None,
1059
1066
  augment=False,
1060
1067
  force_model_download=False,
1061
1068
  detector_options=None,
@@ -1088,7 +1095,7 @@ def load_and_run_detector_batch(model_file,
1088
1095
  file or YOLOv5 dataset.yaml file
1089
1096
  include_image_size (bool, optional): should we include image size in the output for each image?
1090
1097
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
1091
- include_exif_data (bool, optional): should we include EXIF data in the output for each image?
1098
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
1092
1099
  augment (bool, optional): enable image augmentation
1093
1100
  force_model_download (bool, optional): force downloading the model file if
1094
1101
  a named model (e.g. "MDV5A") is supplied, even if the local file already
@@ -1207,7 +1214,7 @@ def load_and_run_detector_batch(model_file,
1207
1214
  image_size=image_size,
1208
1215
  include_image_size=include_image_size,
1209
1216
  include_image_timestamp=include_image_timestamp,
1210
- include_exif_data=include_exif_data,
1217
+ include_exif_tags=include_exif_tags,
1211
1218
  augment=augment,
1212
1219
  detector_options=detector_options,
1213
1220
  loader_workers=loader_workers,
@@ -1269,7 +1276,7 @@ def load_and_run_detector_batch(model_file,
1269
1276
  image_size=image_size,
1270
1277
  include_image_size=include_image_size,
1271
1278
  include_image_timestamp=include_image_timestamp,
1272
- include_exif_data=include_exif_data,
1279
+ include_exif_tags=include_exif_tags,
1273
1280
  augment=augment)
1274
1281
 
1275
1282
  results.extend(batch_results)
@@ -1295,7 +1302,7 @@ def load_and_run_detector_batch(model_file,
1295
1302
  image_size=image_size,
1296
1303
  include_image_size=include_image_size,
1297
1304
  include_image_timestamp=include_image_timestamp,
1298
- include_exif_data=include_exif_data,
1305
+ include_exif_tags=include_exif_tags,
1299
1306
  augment=augment)
1300
1307
  results.append(result)
1301
1308
 
@@ -1354,7 +1361,7 @@ def load_and_run_detector_batch(model_file,
1354
1361
  checkpoint_queue=checkpoint_queue,
1355
1362
  include_image_size=include_image_size,
1356
1363
  include_image_timestamp=include_image_timestamp,
1357
- include_exif_data=include_exif_data,
1364
+ include_exif_tags=include_exif_tags,
1358
1365
  augment=augment,
1359
1366
  detector_options=detector_options),
1360
1367
  image_chunks)
@@ -1374,7 +1381,7 @@ def load_and_run_detector_batch(model_file,
1374
1381
  image_size=image_size,
1375
1382
  include_image_size=include_image_size,
1376
1383
  include_image_timestamp=include_image_timestamp,
1377
- include_exif_data=include_exif_data,
1384
+ include_exif_tags=include_exif_tags,
1378
1385
  augment=augment,
1379
1386
  detector_options=detector_options),
1380
1387
  image_chunks)
@@ -1495,7 +1502,7 @@ def get_image_datetime(image):
1495
1502
  returns None if EXIF datetime is not available.
1496
1503
  """
1497
1504
 
1498
- exif_tags = read_exif.read_pil_exif(image,exif_options)
1505
+ exif_tags = read_exif.read_pil_exif(image,exif_options_base)
1499
1506
 
1500
1507
  try:
1501
1508
  datetime_str = exif_tags['DateTimeOriginal']
@@ -1654,7 +1661,7 @@ if False:
1654
1661
  class_mapping_filename = None
1655
1662
  include_image_size = True
1656
1663
  include_image_timestamp = True
1657
- include_exif_data = True
1664
+ include_exif_tags = None
1658
1665
  overwrite_handling = None
1659
1666
 
1660
1667
  # Generate a command line
@@ -1689,8 +1696,8 @@ if False:
1689
1696
  cmd += ' --include_image_size'
1690
1697
  if include_image_timestamp:
1691
1698
  cmd += ' --include_image_timestamp'
1692
- if include_exif_data:
1693
- cmd += ' --include_exif_data'
1699
+ if include_exif_tags is not None:
1700
+ cmd += ' --include_exif_tags "{}"'.format(include_exif_tags)
1694
1701
  if overwrite_handling is not None:
1695
1702
  cmd += ' --overwrite_handling {}'.format(overwrite_handling)
1696
1703
 
@@ -1837,9 +1844,10 @@ def main(): # noqa
1837
1844
  help='Include image datetime (if available) in output file'
1838
1845
  )
1839
1846
  parser.add_argument(
1840
- '--include_exif_data',
1841
- action='store_true',
1842
- help='Include available EXIF data in output file'
1847
+ '--include_exif_tags',
1848
+ type=str,
1849
+ default=None,
1850
+ help='Command-separated list of EXIF tags to include in output, or "all" to include all tags'
1843
1851
  )
1844
1852
  parser.add_argument(
1845
1853
  '--overwrite_handling',
@@ -1878,6 +1886,12 @@ def main(): # noqa
1878
1886
  action='store_true',
1879
1887
  help=argparse.SUPPRESS)
1880
1888
 
1889
+ # This argument is deprecated in favor use --include_exif_tags
1890
+ parser.add_argument(
1891
+ '--include_exif_data',
1892
+ action='store_true',
1893
+ help=argparse.SUPPRESS)
1894
+
1881
1895
  if len(sys.argv[1:]) == 0:
1882
1896
  parser.print_help()
1883
1897
  parser.exit()
@@ -1888,6 +1902,10 @@ def main(): # noqa
1888
1902
  if args.use_threads_for_queue:
1889
1903
  use_threads_for_queue = True
1890
1904
 
1905
+ # Support the legacy --include_exif_data flag
1906
+ if args.include_exif_data and (args.include_exif_tags is None):
1907
+ args.include_exif_tags = 'all'
1908
+
1891
1909
  detector_options = parse_kvp_list(args.detector_options)
1892
1910
 
1893
1911
  # If the specified detector file is really the name of a known model, find
@@ -2094,7 +2112,7 @@ def main(): # noqa
2094
2112
  class_mapping_filename=args.class_mapping_filename,
2095
2113
  include_image_size=args.include_image_size,
2096
2114
  include_image_timestamp=args.include_image_timestamp,
2097
- include_exif_data=args.include_exif_data,
2115
+ include_exif_tags=args.include_exif_tags,
2098
2116
  augment=args.augment,
2099
2117
  # Don't download the model *again*
2100
2118
  force_model_download=False,
@@ -351,7 +351,9 @@ def run_inference_with_yolo_val(options):
351
351
  else:
352
352
  raise ValueError('Unknown output handling method {}'.format(options.overwrite_handling))
353
353
 
354
- os.makedirs(os.path.dirname(options.output_file),exist_ok=True)
354
+ output_dir = os.path.dirname(options.output_file)
355
+ if len(output_dir) > 0:
356
+ os.makedirs(output_dir, exist_ok=True)
355
357
 
356
358
  if options.input_folder is not None:
357
359
  options.input_folder = options.input_folder.replace('\\','/')