megadetector 10.0.8__py3-none-any.whl → 10.0.10__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.

@@ -210,6 +210,8 @@ def read_pil_exif(im,options=None):
210
210
  if exif_info is None:
211
211
  return exif_tags
212
212
 
213
+ # Read all standard EXIF tags; if necessary, we'll filter later to a restricted
214
+ # list of tags.
213
215
  for k, v in exif_info.items():
214
216
  assert isinstance(k,str) or isinstance(k,int), \
215
217
  'Invalid EXIF key {}'.format(str(k))
@@ -221,6 +223,7 @@ def read_pil_exif(im,options=None):
221
223
 
222
224
  exif_ifd_tags = _get_exif_ifd(exif_info)
223
225
 
226
+ # Read tags that are only available via offset
224
227
  for k in exif_ifd_tags.keys():
225
228
  v = exif_ifd_tags[k]
226
229
  if k in exif_tags:
@@ -266,7 +269,7 @@ def read_pil_exif(im,options=None):
266
269
 
267
270
  # Convert to strings, e.g. 'GPSTimeStamp'
268
271
  gps_info = {}
269
- for int_tag,v in enumerate(gps_info_raw.keys()):
272
+ for int_tag,v in gps_info_raw.items():
270
273
  assert isinstance(int_tag,int)
271
274
  if int_tag in ExifTags.GPSTAGS:
272
275
  gps_info[ExifTags.GPSTAGS[int_tag]] = v
@@ -276,11 +279,15 @@ def read_pil_exif(im,options=None):
276
279
  exif_tags['GPSInfo'] = gps_info
277
280
 
278
281
  except Exception as e:
282
+
279
283
  if options.verbose:
280
284
  print('Warning: error reading GPS info: {}'.format(str(e)))
281
285
 
282
286
  # ...if we think there might be GPS tags in this image
283
287
 
288
+ # Filter tags if necessary
289
+ exif_tags = _filter_tags(exif_tags,options)
290
+
284
291
  return exif_tags
285
292
 
286
293
  # ...read_pil_exif()
@@ -337,10 +344,16 @@ def _filter_tags(tags,options):
337
344
  if options.tags_to_include is None and options.tags_to_exclude is None:
338
345
  return tags
339
346
  if options.tags_to_include is not None:
347
+ if isinstance(options.tags_to_include,str):
348
+ if options.tags_to_include == 'all':
349
+ return tags
340
350
  assert options.tags_to_exclude is None, "tags_to_include and tags_to_exclude are incompatible"
351
+ tags_to_include = options.tags_to_include.split(',')
352
+ # Case-insensitive matching
353
+ tags_to_include = [s.lower() for s in tags_to_include]
341
354
  tags_to_return = {}
342
355
  for tag_name in tags.keys():
343
- if tag_name in options.tags_to_include:
356
+ if str(tag_name).lower() in tags_to_include:
344
357
  tags_to_return[tag_name] = tags[tag_name]
345
358
  return tags_to_return
346
359
  if options.tags_to_exclude is not None:
@@ -859,6 +859,9 @@ class PTDetector:
859
859
  except AttributeError:
860
860
  pass
861
861
 
862
+ # AddaxAI depends on this printout, don't remove it
863
+ print('PTDetector using device {}'.format(str(self.device).lower()))
864
+
862
865
  try:
863
866
  self.model = PTDetector._load_model(model_path,
864
867
  device=self.device,
@@ -596,8 +596,7 @@ def load_detector(model_file,
596
596
  model_file = try_download_known_detector(model_file,
597
597
  force_download=force_model_download)
598
598
 
599
- if verbose:
600
- print('GPU available: {}'.format(is_gpu_available(model_file)))
599
+ print('GPU available: {}'.format(is_gpu_available(model_file)))
601
600
 
602
601
  start_time = time.time()
603
602
 
@@ -94,20 +94,29 @@ 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
- # TODO: it's a little sloppy that these are module-level globals, but in practice it
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
+
102
+ # Only relevant when we're running our test harness; because bugs in batch
103
+ # inference are dependent on batch grouping, we randomize batch grouping
104
+ # during testing to maximize the probability that latent bugs come up
105
+ # eventually.
106
+ randomize_batch_order_during_testing = True
107
+
108
+ # TODO: it's a little sloppy that the following are module-level globals, but in practice it
98
109
  # doesn't really matter, so I'm not in a big rush to move these to options until I do
99
110
  # a larger cleanup of all the long argument lists in this module.
100
- #
111
+
101
112
  # Should the consumer loop run on its own process, or here in the main process?
102
113
  run_separate_consumer_process = False
103
- use_threads_for_queue = False
104
- verbose = False
105
114
 
106
- exif_options = read_exif.ReadExifOptions()
107
- exif_options.processing_library = 'pil'
108
- exif_options.byte_handling = 'convert_to_string'
115
+ # Should we use threads (rather than processes) for the data loading workers?
116
+ use_threads_for_queue = False
109
117
 
110
- randomize_batch_order_during_testing = True
118
+ # Enable additional debug output
119
+ verbose = False
111
120
 
112
121
 
113
122
  #%% Support functions for multiprocessing
@@ -199,7 +208,7 @@ def _consumer_func(q,
199
208
  image_size=None,
200
209
  include_image_size=False,
201
210
  include_image_timestamp=False,
202
- include_exif_data=False,
211
+ include_exif_tags=None,
203
212
  augment=False,
204
213
  detector_options=None,
205
214
  preprocess_on_image_queue=default_preprocess_on_image_queue,
@@ -223,7 +232,7 @@ def _consumer_func(q,
223
232
  image_size (int, optional): image size to use for inference
224
233
  include_image_size (bool, optional): include image dimensions in output
225
234
  include_image_timestamp (bool, optional): include image timestamps in output
226
- 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
227
236
  augment (bool, optional): enable image augmentation
228
237
  detector_options (dict, optional): key/value pairs that are interpreted differently
229
238
  by different detectors
@@ -325,7 +334,7 @@ def _consumer_func(q,
325
334
  image_size=image_size,
326
335
  include_image_size=include_image_size,
327
336
  include_image_timestamp=include_image_timestamp,
328
- include_exif_data=include_exif_data,
337
+ include_exif_tags=include_exif_tags,
329
338
  augment=augment)
330
339
  results.extend(batch_results)
331
340
 
@@ -402,7 +411,7 @@ def _consumer_func(q,
402
411
  image_size=image_size,
403
412
  include_image_size=include_image_size,
404
413
  include_image_timestamp=include_image_timestamp,
405
- include_exif_data=include_exif_data,
414
+ include_exif_tags=include_exif_tags,
406
415
  augment=augment)
407
416
  results.extend(batch_results)
408
417
 
@@ -422,7 +431,7 @@ def _consumer_func(q,
422
431
  image_size=image_size,
423
432
  include_image_size=include_image_size,
424
433
  include_image_timestamp=include_image_timestamp,
425
- include_exif_data=include_exif_data,
434
+ include_exif_tags=include_exif_tags,
426
435
  augment=augment)
427
436
  results.append(result)
428
437
  n_images_processed += 1
@@ -455,7 +464,7 @@ def _run_detector_with_image_queue(image_files,
455
464
  image_size=None,
456
465
  include_image_size=False,
457
466
  include_image_timestamp=False,
458
- include_exif_data=False,
467
+ include_exif_tags=None,
459
468
  augment=False,
460
469
  detector_options=None,
461
470
  loader_workers=default_loaders,
@@ -478,7 +487,7 @@ def _run_detector_with_image_queue(image_files,
478
487
  doing
479
488
  include_image_size (bool, optional): should we include image size in the output for each image?
480
489
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
481
- 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
482
491
  augment (bool, optional): enable image augmentation
483
492
  detector_options (dict, optional): key/value pairs that are interpreted differently
484
493
  by different detectors
@@ -553,7 +562,7 @@ def _run_detector_with_image_queue(image_files,
553
562
  image_size,
554
563
  include_image_size,
555
564
  include_image_timestamp,
556
- include_exif_data,
565
+ include_exif_tags,
557
566
  augment,
558
567
  detector_options,
559
568
  preprocess_on_image_queue,
@@ -570,7 +579,7 @@ def _run_detector_with_image_queue(image_files,
570
579
  image_size,
571
580
  include_image_size,
572
581
  include_image_timestamp,
573
- include_exif_data,
582
+ include_exif_tags,
574
583
  augment,
575
584
  detector_options,
576
585
  preprocess_on_image_queue,
@@ -589,7 +598,7 @@ def _run_detector_with_image_queue(image_files,
589
598
  image_size,
590
599
  include_image_size,
591
600
  include_image_timestamp,
592
- include_exif_data,
601
+ include_exif_tags,
593
602
  augment,
594
603
  detector_options,
595
604
  preprocess_on_image_queue,
@@ -671,7 +680,7 @@ def _process_batch(image_items_batch,
671
680
  image_size=None,
672
681
  include_image_size=False,
673
682
  include_image_timestamp=False,
674
- include_exif_data=False,
683
+ include_exif_tags=None,
675
684
  augment=False):
676
685
  """
677
686
  Process a batch of images using generate_detections_one_batch(). Does not necessarily return
@@ -686,7 +695,7 @@ def _process_batch(image_items_batch,
686
695
  image_size (int, optional): image size override
687
696
  include_image_size (bool, optional): include image dimensions in results
688
697
  include_image_timestamp (bool, optional): include image timestamps in results
689
- 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
690
699
  augment (bool, optional): whether to use image augmentation
691
700
 
692
701
  Returns:
@@ -736,7 +745,9 @@ def _process_batch(image_items_batch,
736
745
  try:
737
746
 
738
747
  batch_detections = \
739
- detector.generate_detections_one_batch(valid_images, valid_image_filenames, verbose=verbose)
748
+ detector.generate_detections_one_batch(valid_images,
749
+ valid_image_filenames,
750
+ verbose=verbose)
740
751
 
741
752
  assert len(batch_detections) == len(valid_images)
742
753
 
@@ -751,12 +762,13 @@ def _process_batch(image_items_batch,
751
762
  image_result['detections'] = \
752
763
  [det for det in image_result['detections'] if det['conf'] >= confidence_threshold]
753
764
 
754
- 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):
755
766
 
756
767
  image = valid_images[i_valid_image]
757
768
 
758
769
  # If this was preprocessed by the producer thread, pull out the PIL version
759
770
  if isinstance(image,dict):
771
+
760
772
  image = image['img_original_pil']
761
773
 
762
774
  if include_image_size:
@@ -768,9 +780,12 @@ def _process_batch(image_items_batch,
768
780
 
769
781
  image_result['datetime'] = get_image_datetime(image)
770
782
 
771
- if include_exif_data:
783
+ if include_exif_tags is not None:
772
784
 
773
- 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)
774
789
 
775
790
  # ...if we need to store metadata
776
791
 
@@ -823,7 +838,7 @@ def _process_images(im_files,
823
838
  checkpoint_queue=None,
824
839
  include_image_size=False,
825
840
  include_image_timestamp=False,
826
- include_exif_data=False,
841
+ include_exif_tags=None,
827
842
  augment=False,
828
843
  detector_options=None,
829
844
  loader_workers=default_loaders,
@@ -845,7 +860,7 @@ def _process_images(im_files,
845
860
  checkpoint_queue (Queue, optional): internal parameter used to pass image queues around
846
861
  include_image_size (bool, optional): should we include image size in the output for each image?
847
862
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
848
- 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
849
864
  augment (bool, optional): enable image augmentation
850
865
  detector_options (dict, optional): key/value pairs that are interpreted differently
851
866
  by different detectors
@@ -879,7 +894,7 @@ def _process_images(im_files,
879
894
  image_size=image_size,
880
895
  include_image_size=include_image_size,
881
896
  include_image_timestamp=include_image_timestamp,
882
- include_exif_data=include_exif_data,
897
+ include_exif_tags=include_exif_tags,
883
898
  augment=augment,
884
899
  detector_options=detector_options,
885
900
  loader_workers=loader_workers,
@@ -896,7 +911,7 @@ def _process_images(im_files,
896
911
  image_size=image_size,
897
912
  include_image_size=include_image_size,
898
913
  include_image_timestamp=include_image_timestamp,
899
- include_exif_data=include_exif_data,
914
+ include_exif_tags=include_exif_tags,
900
915
  augment=augment)
901
916
 
902
917
  if checkpoint_queue is not None:
@@ -918,7 +933,7 @@ def _process_image(im_file,
918
933
  image_size=None,
919
934
  include_image_size=False,
920
935
  include_image_timestamp=False,
921
- include_exif_data=False,
936
+ include_exif_tags=False,
922
937
  augment=False):
923
938
  """
924
939
  Runs a detector (typically MegaDetector) on a single image file.
@@ -936,7 +951,7 @@ def _process_image(im_file,
936
951
  doing
937
952
  include_image_size (bool, optional): should we include image size in the output for each image?
938
953
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
939
- include_exif_data (bool, optional): should we include EXIF data in the output for each image?
954
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
940
955
  augment (bool, optional): enable image augmentation
941
956
 
942
957
  Returns:
@@ -989,7 +1004,9 @@ def _process_image(im_file,
989
1004
  if include_image_timestamp:
990
1005
  result['datetime'] = get_image_datetime(image)
991
1006
 
992
- if include_exif_data:
1007
+ if include_exif_tags is not None:
1008
+ exif_options = copy.copy(exif_options_base)
1009
+ exif_options.tags_to_include = include_exif_tags
993
1010
  result['exif_metadata'] = read_exif.read_pil_exif(image,exif_options)
994
1011
 
995
1012
  return result
@@ -1044,13 +1061,14 @@ def load_and_run_detector_batch(model_file,
1044
1061
  class_mapping_filename=None,
1045
1062
  include_image_size=False,
1046
1063
  include_image_timestamp=False,
1047
- include_exif_data=False,
1064
+ include_exif_tags=None,
1048
1065
  augment=False,
1049
1066
  force_model_download=False,
1050
1067
  detector_options=None,
1051
1068
  loader_workers=default_loaders,
1052
1069
  preprocess_on_image_queue=default_preprocess_on_image_queue,
1053
- batch_size=1):
1070
+ batch_size=1,
1071
+ verbose_output=False):
1054
1072
  """
1055
1073
  Load a model file and run it on a list of images.
1056
1074
 
@@ -1076,7 +1094,7 @@ def load_and_run_detector_batch(model_file,
1076
1094
  file or YOLOv5 dataset.yaml file
1077
1095
  include_image_size (bool, optional): should we include image size in the output for each image?
1078
1096
  include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
1079
- include_exif_data (bool, optional): should we include EXIF data in the output for each image?
1097
+ include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
1080
1098
  augment (bool, optional): enable image augmentation
1081
1099
  force_model_download (bool, optional): force downloading the model file if
1082
1100
  a named model (e.g. "MDV5A") is supplied, even if the local file already
@@ -1087,6 +1105,7 @@ def load_and_run_detector_batch(model_file,
1087
1105
  preprocess_on_image_queue (bool, optional): if the image queue is enabled, should it handle
1088
1106
  image loading and preprocessing (True), or just image loading (False)?
1089
1107
  batch_size (int, optional): batch size for GPU processing, automatically set to 1 for CPU processing
1108
+ verbose_output (bool, optional): enable additional debug output
1090
1109
 
1091
1110
  Returns:
1092
1111
  results: list of dicts; each dict represents detections on one image
@@ -1109,6 +1128,11 @@ def load_and_run_detector_batch(model_file,
1109
1128
  if class_mapping_filename is not None:
1110
1129
  _load_custom_class_mapping(class_mapping_filename)
1111
1130
 
1131
+ global verbose
1132
+ if verbose_output:
1133
+ print('Enabling verbose output')
1134
+ verbose = True
1135
+
1112
1136
  # Handle the case where image_file_names is not yet actually a list
1113
1137
  if isinstance(image_file_names,str):
1114
1138
 
@@ -1189,7 +1213,7 @@ def load_and_run_detector_batch(model_file,
1189
1213
  image_size=image_size,
1190
1214
  include_image_size=include_image_size,
1191
1215
  include_image_timestamp=include_image_timestamp,
1192
- include_exif_data=include_exif_data,
1216
+ include_exif_tags=include_exif_tags,
1193
1217
  augment=augment,
1194
1218
  detector_options=detector_options,
1195
1219
  loader_workers=loader_workers,
@@ -1251,7 +1275,7 @@ def load_and_run_detector_batch(model_file,
1251
1275
  image_size=image_size,
1252
1276
  include_image_size=include_image_size,
1253
1277
  include_image_timestamp=include_image_timestamp,
1254
- include_exif_data=include_exif_data,
1278
+ include_exif_tags=include_exif_tags,
1255
1279
  augment=augment)
1256
1280
 
1257
1281
  results.extend(batch_results)
@@ -1277,7 +1301,7 @@ def load_and_run_detector_batch(model_file,
1277
1301
  image_size=image_size,
1278
1302
  include_image_size=include_image_size,
1279
1303
  include_image_timestamp=include_image_timestamp,
1280
- include_exif_data=include_exif_data,
1304
+ include_exif_tags=include_exif_tags,
1281
1305
  augment=augment)
1282
1306
  results.append(result)
1283
1307
 
@@ -1336,7 +1360,7 @@ def load_and_run_detector_batch(model_file,
1336
1360
  checkpoint_queue=checkpoint_queue,
1337
1361
  include_image_size=include_image_size,
1338
1362
  include_image_timestamp=include_image_timestamp,
1339
- include_exif_data=include_exif_data,
1363
+ include_exif_tags=include_exif_tags,
1340
1364
  augment=augment,
1341
1365
  detector_options=detector_options),
1342
1366
  image_chunks)
@@ -1356,7 +1380,7 @@ def load_and_run_detector_batch(model_file,
1356
1380
  image_size=image_size,
1357
1381
  include_image_size=include_image_size,
1358
1382
  include_image_timestamp=include_image_timestamp,
1359
- include_exif_data=include_exif_data,
1383
+ include_exif_tags=include_exif_tags,
1360
1384
  augment=augment,
1361
1385
  detector_options=detector_options),
1362
1386
  image_chunks)
@@ -1477,7 +1501,7 @@ def get_image_datetime(image):
1477
1501
  returns None if EXIF datetime is not available.
1478
1502
  """
1479
1503
 
1480
- exif_tags = read_exif.read_pil_exif(image,exif_options)
1504
+ exif_tags = read_exif.read_pil_exif(image,exif_options_base)
1481
1505
 
1482
1506
  try:
1483
1507
  datetime_str = exif_tags['DateTimeOriginal']
@@ -1636,7 +1660,7 @@ if False:
1636
1660
  class_mapping_filename = None
1637
1661
  include_image_size = True
1638
1662
  include_image_timestamp = True
1639
- include_exif_data = True
1663
+ include_exif_tags = None
1640
1664
  overwrite_handling = None
1641
1665
 
1642
1666
  # Generate a command line
@@ -1671,8 +1695,8 @@ if False:
1671
1695
  cmd += ' --include_image_size'
1672
1696
  if include_image_timestamp:
1673
1697
  cmd += ' --include_image_timestamp'
1674
- if include_exif_data:
1675
- cmd += ' --include_exif_data'
1698
+ if include_exif_tags is not None:
1699
+ cmd += ' --include_exif_tags "{}"'.format(include_exif_tags)
1676
1700
  if overwrite_handling is not None:
1677
1701
  cmd += ' --overwrite_handling {}'.format(overwrite_handling)
1678
1702
 
@@ -1819,9 +1843,10 @@ def main(): # noqa
1819
1843
  help='Include image datetime (if available) in output file'
1820
1844
  )
1821
1845
  parser.add_argument(
1822
- '--include_exif_data',
1823
- action='store_true',
1824
- help='Include available EXIF data in output file'
1846
+ '--include_exif_tags',
1847
+ type=str,
1848
+ default=None,
1849
+ help='Command-separated list of EXIF tags to include in output, or "all" to include all tags'
1825
1850
  )
1826
1851
  parser.add_argument(
1827
1852
  '--overwrite_handling',
@@ -1860,20 +1885,26 @@ def main(): # noqa
1860
1885
  action='store_true',
1861
1886
  help=argparse.SUPPRESS)
1862
1887
 
1888
+ # This argument is deprecated in favor use --include_exif_tags
1889
+ parser.add_argument(
1890
+ '--include_exif_data',
1891
+ action='store_true',
1892
+ help=argparse.SUPPRESS)
1893
+
1863
1894
  if len(sys.argv[1:]) == 0:
1864
1895
  parser.print_help()
1865
1896
  parser.exit()
1866
1897
 
1867
1898
  args = parser.parse_args()
1868
1899
 
1869
- global verbose
1870
1900
  global use_threads_for_queue
1871
-
1872
- if args.verbose:
1873
- verbose = True
1874
1901
  if args.use_threads_for_queue:
1875
1902
  use_threads_for_queue = True
1876
1903
 
1904
+ # Support the legacy --include_exif_data flag
1905
+ if args.include_exif_data and (args.include_exif_tags is None):
1906
+ args.include_exif_tags = 'all'
1907
+
1877
1908
  detector_options = parse_kvp_list(args.detector_options)
1878
1909
 
1879
1910
  # If the specified detector file is really the name of a known model, find
@@ -2080,14 +2111,15 @@ def main(): # noqa
2080
2111
  class_mapping_filename=args.class_mapping_filename,
2081
2112
  include_image_size=args.include_image_size,
2082
2113
  include_image_timestamp=args.include_image_timestamp,
2083
- include_exif_data=args.include_exif_data,
2114
+ include_exif_tags=args.include_exif_tags,
2084
2115
  augment=args.augment,
2085
2116
  # Don't download the model *again*
2086
2117
  force_model_download=False,
2087
2118
  detector_options=detector_options,
2088
2119
  loader_workers=args.loader_workers,
2089
2120
  preprocess_on_image_queue=args.preprocess_on_image_queue,
2090
- batch_size=args.batch_size)
2121
+ batch_size=args.batch_size,
2122
+ verbose_output=args.verbose)
2091
2123
 
2092
2124
  elapsed = time.time() - start_time
2093
2125
  images_per_second = len(results) / elapsed