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.
- megadetector/data_management/animl_to_md.py +5 -2
- megadetector/data_management/cct_json_utils.py +4 -2
- megadetector/data_management/cct_to_md.py +5 -4
- megadetector/data_management/cct_to_wi.py +5 -1
- megadetector/data_management/coco_to_yolo.py +3 -2
- megadetector/data_management/databases/combine_coco_camera_traps_files.py +4 -4
- megadetector/data_management/databases/integrity_check_json_db.py +2 -2
- megadetector/data_management/databases/subset_json_db.py +0 -3
- megadetector/data_management/generate_crops_from_cct.py +6 -4
- megadetector/data_management/get_image_sizes.py +5 -35
- megadetector/data_management/labelme_to_coco.py +10 -6
- megadetector/data_management/labelme_to_yolo.py +19 -28
- megadetector/data_management/lila/create_lila_test_set.py +22 -2
- megadetector/data_management/lila/generate_lila_per_image_labels.py +7 -5
- megadetector/data_management/lila/lila_common.py +2 -2
- megadetector/data_management/lila/test_lila_metadata_urls.py +0 -1
- megadetector/data_management/ocr_tools.py +6 -10
- megadetector/data_management/read_exif.py +69 -13
- megadetector/data_management/remap_coco_categories.py +1 -1
- megadetector/data_management/remove_exif.py +10 -5
- megadetector/data_management/rename_images.py +20 -13
- megadetector/data_management/resize_coco_dataset.py +10 -4
- megadetector/data_management/speciesnet_to_md.py +3 -3
- megadetector/data_management/yolo_output_to_md_output.py +3 -1
- megadetector/data_management/yolo_to_coco.py +28 -19
- megadetector/detection/change_detection.py +26 -18
- megadetector/detection/process_video.py +1 -1
- megadetector/detection/pytorch_detector.py +5 -5
- megadetector/detection/run_detector.py +34 -10
- megadetector/detection/run_detector_batch.py +60 -42
- megadetector/detection/run_inference_with_yolov5_val.py +3 -1
- megadetector/detection/run_md_and_speciesnet.py +282 -110
- megadetector/detection/run_tiled_inference.py +7 -7
- megadetector/detection/tf_detector.py +4 -6
- megadetector/detection/video_utils.py +9 -6
- megadetector/postprocessing/add_max_conf.py +4 -4
- megadetector/postprocessing/categorize_detections_by_size.py +3 -2
- megadetector/postprocessing/classification_postprocessing.py +19 -21
- megadetector/postprocessing/combine_batch_outputs.py +3 -2
- megadetector/postprocessing/compare_batch_results.py +49 -27
- megadetector/postprocessing/convert_output_format.py +8 -6
- megadetector/postprocessing/create_crop_folder.py +13 -4
- megadetector/postprocessing/generate_csv_report.py +22 -8
- megadetector/postprocessing/load_api_results.py +8 -4
- megadetector/postprocessing/md_to_coco.py +2 -3
- megadetector/postprocessing/md_to_labelme.py +12 -8
- megadetector/postprocessing/md_to_wi.py +2 -1
- megadetector/postprocessing/merge_detections.py +4 -6
- megadetector/postprocessing/postprocess_batch_results.py +4 -3
- megadetector/postprocessing/remap_detection_categories.py +6 -3
- megadetector/postprocessing/render_detection_confusion_matrix.py +18 -10
- megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +1 -1
- megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +5 -3
- megadetector/postprocessing/separate_detections_into_folders.py +10 -4
- megadetector/postprocessing/subset_json_detector_output.py +1 -1
- megadetector/postprocessing/top_folders_to_bottom.py +22 -7
- megadetector/postprocessing/validate_batch_results.py +1 -1
- megadetector/taxonomy_mapping/map_new_lila_datasets.py +59 -3
- megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +1 -1
- megadetector/taxonomy_mapping/preview_lila_taxonomy.py +26 -17
- megadetector/taxonomy_mapping/species_lookup.py +51 -2
- megadetector/utils/ct_utils.py +9 -4
- megadetector/utils/directory_listing.py +3 -0
- megadetector/utils/extract_frames_from_video.py +4 -0
- megadetector/utils/gpu_test.py +6 -6
- megadetector/utils/md_tests.py +21 -21
- megadetector/utils/path_utils.py +171 -36
- megadetector/utils/split_locations_into_train_val.py +0 -4
- megadetector/utils/string_utils.py +21 -0
- megadetector/utils/url_utils.py +5 -3
- megadetector/utils/wi_platform_utils.py +168 -24
- megadetector/utils/wi_taxonomy_utils.py +38 -8
- megadetector/utils/write_html_image_list.py +1 -2
- megadetector/visualization/plot_utils.py +31 -19
- megadetector/visualization/render_images_with_thumbnails.py +3 -0
- megadetector/visualization/visualization_utils.py +18 -7
- megadetector/visualization/visualize_db.py +9 -26
- megadetector/visualization/visualize_detector_output.py +1 -0
- megadetector/visualization/visualize_video_output.py +14 -2
- {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/METADATA +1 -1
- {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/RECORD +84 -84
- {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/WHEEL +0 -0
- {megadetector-10.0.9.dist-info → megadetector-10.0.11.dist-info}/licenses/LICENSE +0 -0
- {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
|
|
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
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
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[
|
|
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 --
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
783
|
+
if include_exif_tags is not None:
|
|
783
784
|
|
|
784
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
1693
|
-
cmd += ' --
|
|
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
|
-
'--
|
|
1841
|
-
|
|
1842
|
-
|
|
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
|
-
|
|
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.
|
|
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('\\','/')
|