megadetector 5.0.5__py3-none-any.whl → 5.0.7__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.
- api/batch_processing/data_preparation/manage_local_batch.py +302 -263
- api/batch_processing/data_preparation/manage_video_batch.py +81 -2
- api/batch_processing/postprocessing/add_max_conf.py +1 -0
- api/batch_processing/postprocessing/categorize_detections_by_size.py +50 -19
- api/batch_processing/postprocessing/compare_batch_results.py +110 -60
- api/batch_processing/postprocessing/load_api_results.py +56 -70
- api/batch_processing/postprocessing/md_to_coco.py +1 -1
- api/batch_processing/postprocessing/md_to_labelme.py +2 -1
- api/batch_processing/postprocessing/postprocess_batch_results.py +240 -81
- api/batch_processing/postprocessing/render_detection_confusion_matrix.py +625 -0
- api/batch_processing/postprocessing/repeat_detection_elimination/find_repeat_detections.py +71 -23
- api/batch_processing/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +1 -1
- api/batch_processing/postprocessing/repeat_detection_elimination/repeat_detections_core.py +227 -75
- api/batch_processing/postprocessing/subset_json_detector_output.py +132 -5
- api/batch_processing/postprocessing/top_folders_to_bottom.py +1 -1
- api/synchronous/api_core/animal_detection_api/detection/run_detector_batch.py +2 -2
- classification/prepare_classification_script.py +191 -191
- data_management/coco_to_yolo.py +68 -45
- data_management/databases/integrity_check_json_db.py +7 -5
- data_management/generate_crops_from_cct.py +3 -3
- data_management/get_image_sizes.py +8 -6
- data_management/importers/add_timestamps_to_icct.py +79 -0
- data_management/importers/animl_results_to_md_results.py +160 -0
- data_management/importers/auckland_doc_test_to_json.py +4 -4
- data_management/importers/auckland_doc_to_json.py +1 -1
- data_management/importers/awc_to_json.py +5 -5
- data_management/importers/bellevue_to_json.py +5 -5
- data_management/importers/carrizo_shrubfree_2018.py +5 -5
- data_management/importers/carrizo_trail_cam_2017.py +5 -5
- data_management/importers/cct_field_adjustments.py +2 -3
- data_management/importers/channel_islands_to_cct.py +4 -4
- data_management/importers/ena24_to_json.py +5 -5
- data_management/importers/helena_to_cct.py +10 -10
- data_management/importers/idaho-camera-traps.py +12 -12
- data_management/importers/idfg_iwildcam_lila_prep.py +8 -8
- data_management/importers/jb_csv_to_json.py +4 -4
- data_management/importers/missouri_to_json.py +1 -1
- data_management/importers/noaa_seals_2019.py +1 -1
- data_management/importers/pc_to_json.py +5 -5
- data_management/importers/prepare-noaa-fish-data-for-lila.py +4 -4
- data_management/importers/prepare_zsl_imerit.py +5 -5
- data_management/importers/rspb_to_json.py +4 -4
- data_management/importers/save_the_elephants_survey_A.py +5 -5
- data_management/importers/save_the_elephants_survey_B.py +6 -6
- data_management/importers/snapshot_safari_importer.py +9 -9
- data_management/importers/snapshot_serengeti_lila.py +9 -9
- data_management/importers/timelapse_csv_set_to_json.py +5 -7
- data_management/importers/ubc_to_json.py +4 -4
- data_management/importers/umn_to_json.py +4 -4
- data_management/importers/wellington_to_json.py +1 -1
- data_management/importers/wi_to_json.py +2 -2
- data_management/importers/zamba_results_to_md_results.py +181 -0
- data_management/labelme_to_coco.py +35 -7
- data_management/labelme_to_yolo.py +229 -0
- data_management/lila/add_locations_to_island_camera_traps.py +1 -1
- data_management/lila/add_locations_to_nacti.py +147 -0
- data_management/lila/create_lila_blank_set.py +474 -0
- data_management/lila/create_lila_test_set.py +2 -1
- data_management/lila/create_links_to_md_results_files.py +106 -0
- data_management/lila/download_lila_subset.py +46 -21
- data_management/lila/generate_lila_per_image_labels.py +23 -14
- data_management/lila/get_lila_annotation_counts.py +17 -11
- data_management/lila/lila_common.py +14 -11
- data_management/lila/test_lila_metadata_urls.py +116 -0
- data_management/ocr_tools.py +829 -0
- data_management/resize_coco_dataset.py +13 -11
- data_management/yolo_output_to_md_output.py +84 -12
- data_management/yolo_to_coco.py +38 -20
- detection/process_video.py +36 -14
- detection/pytorch_detector.py +23 -8
- detection/run_detector.py +76 -19
- detection/run_detector_batch.py +178 -63
- detection/run_inference_with_yolov5_val.py +326 -57
- detection/run_tiled_inference.py +153 -43
- detection/video_utils.py +34 -8
- md_utils/ct_utils.py +172 -1
- md_utils/md_tests.py +372 -51
- md_utils/path_utils.py +167 -39
- md_utils/process_utils.py +26 -7
- md_utils/split_locations_into_train_val.py +215 -0
- md_utils/string_utils.py +10 -0
- md_utils/url_utils.py +0 -2
- md_utils/write_html_image_list.py +9 -26
- md_visualization/plot_utils.py +12 -8
- md_visualization/visualization_utils.py +106 -7
- md_visualization/visualize_db.py +16 -8
- md_visualization/visualize_detector_output.py +208 -97
- {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/METADATA +3 -6
- {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/RECORD +98 -121
- {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/WHEEL +1 -1
- taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +1 -1
- taxonomy_mapping/map_new_lila_datasets.py +43 -39
- taxonomy_mapping/prepare_lila_taxonomy_release.py +5 -2
- taxonomy_mapping/preview_lila_taxonomy.py +27 -27
- taxonomy_mapping/species_lookup.py +33 -13
- taxonomy_mapping/taxonomy_csv_checker.py +7 -5
- api/synchronous/api_core/yolov5/detect.py +0 -252
- api/synchronous/api_core/yolov5/export.py +0 -607
- api/synchronous/api_core/yolov5/hubconf.py +0 -146
- api/synchronous/api_core/yolov5/models/__init__.py +0 -0
- api/synchronous/api_core/yolov5/models/common.py +0 -738
- api/synchronous/api_core/yolov5/models/experimental.py +0 -104
- api/synchronous/api_core/yolov5/models/tf.py +0 -574
- api/synchronous/api_core/yolov5/models/yolo.py +0 -338
- api/synchronous/api_core/yolov5/train.py +0 -670
- api/synchronous/api_core/yolov5/utils/__init__.py +0 -36
- api/synchronous/api_core/yolov5/utils/activations.py +0 -103
- api/synchronous/api_core/yolov5/utils/augmentations.py +0 -284
- api/synchronous/api_core/yolov5/utils/autoanchor.py +0 -170
- api/synchronous/api_core/yolov5/utils/autobatch.py +0 -66
- api/synchronous/api_core/yolov5/utils/aws/__init__.py +0 -0
- api/synchronous/api_core/yolov5/utils/aws/resume.py +0 -40
- api/synchronous/api_core/yolov5/utils/benchmarks.py +0 -148
- api/synchronous/api_core/yolov5/utils/callbacks.py +0 -71
- api/synchronous/api_core/yolov5/utils/dataloaders.py +0 -1087
- api/synchronous/api_core/yolov5/utils/downloads.py +0 -178
- api/synchronous/api_core/yolov5/utils/flask_rest_api/example_request.py +0 -19
- api/synchronous/api_core/yolov5/utils/flask_rest_api/restapi.py +0 -46
- api/synchronous/api_core/yolov5/utils/general.py +0 -1018
- api/synchronous/api_core/yolov5/utils/loggers/__init__.py +0 -187
- api/synchronous/api_core/yolov5/utils/loggers/wandb/__init__.py +0 -0
- api/synchronous/api_core/yolov5/utils/loggers/wandb/log_dataset.py +0 -27
- api/synchronous/api_core/yolov5/utils/loggers/wandb/sweep.py +0 -41
- api/synchronous/api_core/yolov5/utils/loggers/wandb/wandb_utils.py +0 -577
- api/synchronous/api_core/yolov5/utils/loss.py +0 -234
- api/synchronous/api_core/yolov5/utils/metrics.py +0 -355
- api/synchronous/api_core/yolov5/utils/plots.py +0 -489
- api/synchronous/api_core/yolov5/utils/torch_utils.py +0 -314
- api/synchronous/api_core/yolov5/val.py +0 -394
- md_utils/matlab_porting_tools.py +0 -97
- {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/LICENSE +0 -0
- {megadetector-5.0.5.dist-info → megadetector-5.0.7.dist-info}/top_level.txt +0 -0
detection/run_detector_batch.py
CHANGED
|
@@ -350,26 +350,56 @@ def process_image(im_file, detector, confidence_threshold, image=None,
|
|
|
350
350
|
# ...def process_image(...)
|
|
351
351
|
|
|
352
352
|
|
|
353
|
+
def load_custom_class_mapping(class_mapping_filename):
|
|
354
|
+
"""
|
|
355
|
+
This is an experimental hack to allow the use of non-MD YOLOv5 models through
|
|
356
|
+
the same infrastructure; it disables the code that enforces MDv5-like class lists.
|
|
357
|
+
|
|
358
|
+
Should be a .json file that maps int-strings to strings, or a YOLOv5 dataset.yaml file.
|
|
359
|
+
"""
|
|
360
|
+
|
|
361
|
+
if class_mapping_filename is None:
|
|
362
|
+
return
|
|
363
|
+
|
|
364
|
+
run_detector.USE_MODEL_NATIVE_CLASSES = True
|
|
365
|
+
if class_mapping_filename.endswith('.json'):
|
|
366
|
+
with open(class_mapping_filename,'r') as f:
|
|
367
|
+
class_mapping = json.load(f)
|
|
368
|
+
elif (class_mapping_filename.endswith('.yml') or class_mapping_filename.endswith('.yaml')):
|
|
369
|
+
from data_management.yolo_output_to_md_output import read_classes_from_yolo_dataset_file
|
|
370
|
+
class_mapping = read_classes_from_yolo_dataset_file(class_mapping_filename)
|
|
371
|
+
# convert from ints to int-strings
|
|
372
|
+
class_mapping = {str(k):v for k,v in class_mapping.items()}
|
|
373
|
+
else:
|
|
374
|
+
raise ValueError('Unrecognized class mapping file {}'.format(class_mapping_filename))
|
|
375
|
+
|
|
376
|
+
print('Loaded custom class mapping:')
|
|
377
|
+
print(class_mapping)
|
|
378
|
+
run_detector.DEFAULT_DETECTOR_LABEL_MAP = class_mapping
|
|
379
|
+
return class_mapping
|
|
380
|
+
|
|
381
|
+
|
|
353
382
|
#%% Main function
|
|
354
383
|
|
|
355
384
|
def load_and_run_detector_batch(model_file, image_file_names, checkpoint_path=None,
|
|
356
385
|
confidence_threshold=run_detector.DEFAULT_OUTPUT_CONFIDENCE_THRESHOLD,
|
|
357
386
|
checkpoint_frequency=-1, results=None, n_cores=1,
|
|
358
|
-
use_image_queue=False, quiet=False, image_size=None,
|
|
359
|
-
|
|
360
|
-
include_exif_data=False):
|
|
387
|
+
use_image_queue=False, quiet=False, image_size=None,
|
|
388
|
+
class_mapping_filename=None, include_image_size=False,
|
|
389
|
+
include_image_timestamp=False, include_exif_data=False):
|
|
361
390
|
"""
|
|
362
391
|
Args
|
|
363
392
|
- model_file: path to model file, or supported model string (e.g. "MDV5A")
|
|
364
393
|
- image_file_names: list of strings (image filenames), a single image filename,
|
|
365
|
-
a folder to recursively search for images in, or a .json file
|
|
366
|
-
a list of images.
|
|
394
|
+
a folder to recursively search for images in, or a .json or .txt file
|
|
395
|
+
containing a list of images.
|
|
367
396
|
- checkpoint_path: str, path to JSON checkpoint file
|
|
368
397
|
- confidence_threshold: float, only detections above this threshold are returned
|
|
369
398
|
- checkpoint_frequency: int, write results to JSON checkpoint file every N images
|
|
370
399
|
- results: list of dict, existing results loaded from checkpoint
|
|
371
400
|
- n_cores: int, # of CPU cores to use
|
|
372
401
|
- class_mapping_filename: str, use a non-default class mapping supplied in a .json file
|
|
402
|
+
or YOLOv5 dataset.yaml file.
|
|
373
403
|
|
|
374
404
|
Returns
|
|
375
405
|
- results: list of dicts; each dict represents detections on one image
|
|
@@ -384,15 +414,8 @@ def load_and_run_detector_batch(model_file, image_file_names, checkpoint_path=No
|
|
|
384
414
|
if checkpoint_frequency is None:
|
|
385
415
|
checkpoint_frequency = -1
|
|
386
416
|
|
|
387
|
-
# This is an experimental hack to allow the use of non-MD YOLOv5 models through
|
|
388
|
-
# the same infrastructure; it disables the code that enforces MDv5-like class lists.
|
|
389
417
|
if class_mapping_filename is not None:
|
|
390
|
-
|
|
391
|
-
with open(class_mapping_filename,'r') as f:
|
|
392
|
-
class_mapping = json.load(f)
|
|
393
|
-
print('Loaded custom class mapping:')
|
|
394
|
-
print(class_mapping)
|
|
395
|
-
run_detector.DEFAULT_DETECTOR_LABEL_MAP = class_mapping
|
|
418
|
+
load_custom_class_mapping(class_mapping_filename)
|
|
396
419
|
|
|
397
420
|
# Handle the case where image_file_names is not yet actually a list
|
|
398
421
|
if isinstance(image_file_names,str):
|
|
@@ -403,22 +426,32 @@ def load_and_run_detector_batch(model_file, image_file_names, checkpoint_path=No
|
|
|
403
426
|
image_file_names = path_utils.find_images(image_dir, True)
|
|
404
427
|
print('{} image files found in folder {}'.format(len(image_file_names),image_dir))
|
|
405
428
|
|
|
406
|
-
# A
|
|
407
|
-
elif os.path.isfile(image_file_names)
|
|
429
|
+
# A single file, or a list of image paths
|
|
430
|
+
elif os.path.isfile(image_file_names):
|
|
408
431
|
list_file = image_file_names
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
432
|
+
if image_file_names.endswith('.json'):
|
|
433
|
+
with open(list_file,'r') as f:
|
|
434
|
+
image_file_names = json.load(f)
|
|
435
|
+
print('Loaded {} image filenames from .json list file {}'.format(
|
|
436
|
+
len(image_file_names),list_file))
|
|
437
|
+
elif image_file_names.endswith('.txt'):
|
|
438
|
+
with open(list_file,'r') as f:
|
|
439
|
+
image_file_names = f.readlines()
|
|
440
|
+
image_file_names = [s.strip() for s in image_file_names if len(s.strip()) > 0]
|
|
441
|
+
print('Loaded {} image filenames from .txt list file {}'.format(
|
|
442
|
+
len(image_file_names),list_file))
|
|
443
|
+
elif path_utils.is_image_file(image_file_names):
|
|
444
|
+
image_file_names = [image_file_names]
|
|
445
|
+
print('Processing image {}'.format(image_file_names[0]))
|
|
446
|
+
else:
|
|
447
|
+
raise ValueError(
|
|
448
|
+
'File {} supplied as [image_file_names] argument, but extension is neither .json nor .txt'\
|
|
449
|
+
.format(
|
|
450
|
+
list_file))
|
|
451
|
+
else:
|
|
452
|
+
raise ValueError(
|
|
453
|
+
'{} supplied as [image_file_names] argument, but it does not appear to be a file or folder')
|
|
417
454
|
|
|
418
|
-
else:
|
|
419
|
-
raise ValueError('image_file_names is a string, but is not a directory, a json ' + \
|
|
420
|
-
'list (.json), or an image file')
|
|
421
|
-
|
|
422
455
|
if results is None:
|
|
423
456
|
results = []
|
|
424
457
|
|
|
@@ -718,17 +751,75 @@ if False:
|
|
|
718
751
|
|
|
719
752
|
#%%
|
|
720
753
|
|
|
754
|
+
model_file = 'MDV5A'
|
|
755
|
+
image_dir = r'g:\camera_traps\camera_trap_images'
|
|
756
|
+
output_file = r'g:\temp\md-test.json'
|
|
757
|
+
|
|
758
|
+
recursive = True
|
|
759
|
+
output_relative_filenames = True
|
|
760
|
+
include_max_conf = False
|
|
761
|
+
quiet = True
|
|
762
|
+
image_size = None
|
|
763
|
+
use_image_queue = False
|
|
764
|
+
confidence_threshold = 0.0001
|
|
765
|
+
checkpoint_frequency = 5
|
|
721
766
|
checkpoint_path = None
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
checkpoint_frequency = -1
|
|
725
|
-
results = None
|
|
767
|
+
resume_from_checkpoint = 'auto'
|
|
768
|
+
allow_checkpoint_overwrite = False
|
|
726
769
|
ncores = 1
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
770
|
+
class_mapping_filename = None
|
|
771
|
+
include_image_size = True
|
|
772
|
+
include_image_timestamp = True
|
|
773
|
+
include_exif_data = True
|
|
774
|
+
overwrite_handling = None
|
|
775
|
+
|
|
776
|
+
# Generate a command line
|
|
777
|
+
cmd = 'python run_detector_batch.py "{}" "{}" "{}"'.format(
|
|
778
|
+
model_file,image_dir,output_file)
|
|
779
|
+
|
|
780
|
+
if recursive:
|
|
781
|
+
cmd += ' --recursive'
|
|
782
|
+
if output_relative_filenames:
|
|
783
|
+
cmd += ' --output_relative_filenames'
|
|
784
|
+
if include_max_conf:
|
|
785
|
+
cmd += ' --include_max_conf'
|
|
786
|
+
if quiet:
|
|
787
|
+
cmd += ' --quiet'
|
|
788
|
+
if image_size is not None:
|
|
789
|
+
cmd += ' --image_size {}'.format(image_size)
|
|
790
|
+
if use_image_queue:
|
|
791
|
+
cmd += ' --use_image_queue'
|
|
792
|
+
if confidence_threshold is not None:
|
|
793
|
+
cmd += ' --threshold {}'.format(confidence_threshold)
|
|
794
|
+
if checkpoint_frequency is not None:
|
|
795
|
+
cmd += ' --checkpoint_frequency {}'.format(checkpoint_frequency)
|
|
796
|
+
if checkpoint_path is not None:
|
|
797
|
+
cmd += ' --checkpoint_path "{}"'.format(checkpoint_path)
|
|
798
|
+
if resume_from_checkpoint is not None:
|
|
799
|
+
cmd += ' --resume_from_checkpoint "{}"'.format(resume_from_checkpoint)
|
|
800
|
+
if allow_checkpoint_overwrite:
|
|
801
|
+
cmd += ' --allow_checkpoint_overwrite'
|
|
802
|
+
if ncores is not None:
|
|
803
|
+
cmd += ' --ncores {}'.format(ncores)
|
|
804
|
+
if class_mapping_filename is not None:
|
|
805
|
+
cmd += ' --class_mapping_filename "{}"'.format(class_mapping_filename)
|
|
806
|
+
if include_image_size:
|
|
807
|
+
cmd += ' --include_image_size'
|
|
808
|
+
if include_image_timestamp:
|
|
809
|
+
cmd += ' --include_image_timestamp'
|
|
810
|
+
if include_exif_data:
|
|
811
|
+
cmd += ' --include_exif_data'
|
|
812
|
+
if overwrite_handling is not None:
|
|
813
|
+
cmd += ' --overwrite_handling {}'.format(overwrite_handling)
|
|
814
|
+
|
|
815
|
+
print(cmd)
|
|
816
|
+
import clipboard; clipboard.copy(cmd)
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
#%% Run inference interactively
|
|
820
|
+
|
|
731
821
|
image_file_names = path_utils.find_images(image_dir, recursive=False)
|
|
822
|
+
results = None
|
|
732
823
|
|
|
733
824
|
start_time = time.time()
|
|
734
825
|
|
|
@@ -759,7 +850,8 @@ def main():
|
|
|
759
850
|
help='Path to detector model file (.pb or .pt). Can also be the strings "MDV4", "MDV5A", or "MDV5B" to request automatic download.')
|
|
760
851
|
parser.add_argument(
|
|
761
852
|
'image_file',
|
|
762
|
-
help
|
|
853
|
+
help=\
|
|
854
|
+
'Path to a single image file, a .json or .txt file containing a list of paths to images, or a directory')
|
|
763
855
|
parser.add_argument(
|
|
764
856
|
'output_file',
|
|
765
857
|
help='Path to output JSON results file, should end with a .json extension')
|
|
@@ -806,12 +898,15 @@ def main():
|
|
|
806
898
|
'--checkpoint_path',
|
|
807
899
|
type=str,
|
|
808
900
|
default=None,
|
|
809
|
-
help='File name to which checkpoints will be written if checkpoint_frequency is > 0'
|
|
901
|
+
help='File name to which checkpoints will be written if checkpoint_frequency is > 0, ' + \
|
|
902
|
+
'defaults to md_checkpoint_[date].json in the same folder as the output file')
|
|
810
903
|
parser.add_argument(
|
|
811
904
|
'--resume_from_checkpoint',
|
|
812
905
|
type=str,
|
|
813
906
|
default=None,
|
|
814
|
-
help='Path to a JSON checkpoint file to resume from'
|
|
907
|
+
help='Path to a JSON checkpoint file to resume from, or "auto" to ' + \
|
|
908
|
+
'find the most recent checkpoint in the same folder as the output file. "auto" uses' + \
|
|
909
|
+
'checkpoint_path (rather than searching the output folder) if checkpoint_path is specified.')
|
|
815
910
|
parser.add_argument(
|
|
816
911
|
'--allow_checkpoint_overwrite',
|
|
817
912
|
action='store_true',
|
|
@@ -828,7 +923,7 @@ def main():
|
|
|
828
923
|
default=None,
|
|
829
924
|
help='Use a non-default class mapping, supplied in a .json file with a dictionary mapping' + \
|
|
830
925
|
'int-strings to strings. This will also disable the addition of "1" to all category ' + \
|
|
831
|
-
'IDs, so your class mapping should start at zero.')
|
|
926
|
+
'IDs, so your class mapping should start at zero. Can also be a YOLOv5 dataset.yaml file.')
|
|
832
927
|
parser.add_argument(
|
|
833
928
|
'--include_image_size',
|
|
834
929
|
action='store_true',
|
|
@@ -863,7 +958,7 @@ def main():
|
|
|
863
958
|
|
|
864
959
|
assert os.path.exists(args.detector_file), \
|
|
865
960
|
'detector file {} does not exist'.format(args.detector_file)
|
|
866
|
-
assert 0.0
|
|
961
|
+
assert 0.0 <= args.threshold <= 1.0, 'Confidence threshold needs to be between 0 and 1'
|
|
867
962
|
assert args.output_file.endswith('.json'), 'output_file specified needs to end with .json'
|
|
868
963
|
if args.checkpoint_frequency != -1:
|
|
869
964
|
assert args.checkpoint_frequency > 0, 'Checkpoint_frequency needs to be > 0 or == -1'
|
|
@@ -885,26 +980,42 @@ def main():
|
|
|
885
980
|
else:
|
|
886
981
|
raise ValueError('Illegal overwrite handling string {}'.format(args.overwrite_handling))
|
|
887
982
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
if
|
|
891
|
-
|
|
892
|
-
with open(args.class_mapping_filename,'r') as f:
|
|
893
|
-
class_mapping = json.load(f)
|
|
894
|
-
print('Loaded custom class mapping:')
|
|
895
|
-
print(class_mapping)
|
|
896
|
-
run_detector.DEFAULT_DETECTOR_LABEL_MAP = class_mapping
|
|
983
|
+
output_dir = os.path.dirname(args.output_file)
|
|
984
|
+
|
|
985
|
+
if len(output_dir) > 0:
|
|
986
|
+
os.makedirs(output_dir,exist_ok=True)
|
|
897
987
|
|
|
988
|
+
assert not os.path.isdir(args.output_file), 'Specified output file is a directory'
|
|
989
|
+
|
|
990
|
+
if args.class_mapping_filename is not None:
|
|
991
|
+
load_custom_class_mapping(args.class_mapping_filename)
|
|
992
|
+
|
|
898
993
|
# Load the checkpoint if available
|
|
899
994
|
#
|
|
900
995
|
# Relative file names are only output at the end; all file paths in the checkpoint are
|
|
901
|
-
# still
|
|
996
|
+
# still absolute paths.
|
|
902
997
|
if args.resume_from_checkpoint is not None:
|
|
903
|
-
|
|
998
|
+
if args.resume_from_checkpoint == 'auto':
|
|
999
|
+
checkpoint_files = os.listdir(output_dir)
|
|
1000
|
+
checkpoint_files = [fn for fn in checkpoint_files if \
|
|
1001
|
+
(fn.startswith('md_checkpoint') and fn.endswith('.json'))]
|
|
1002
|
+
if len(checkpoint_files) == 0:
|
|
1003
|
+
raise ValueError('resume_from_checkpoint set to "auto", but no checkpoints found in {}'.format(
|
|
1004
|
+
output_dir))
|
|
1005
|
+
else:
|
|
1006
|
+
if len(checkpoint_files) > 1:
|
|
1007
|
+
print('Warning: found {} checkpoints in {}, using the latest'.format(
|
|
1008
|
+
len(checkpoint_files),output_dir))
|
|
1009
|
+
checkpoint_files = sorted(checkpoint_files)
|
|
1010
|
+
checkpoint_file_relative = checkpoint_files[-1]
|
|
1011
|
+
checkpoint_file = os.path.join(output_dir,checkpoint_file_relative)
|
|
1012
|
+
else:
|
|
1013
|
+
checkpoint_file = args.resume_from_checkpoint
|
|
1014
|
+
assert os.path.exists(checkpoint_file), \
|
|
904
1015
|
'File at resume_from_checkpoint specified does not exist'
|
|
905
|
-
with open(
|
|
1016
|
+
with open(checkpoint_file) as f:
|
|
906
1017
|
print('Loading previous results from checkpoint file {}'.format(
|
|
907
|
-
|
|
1018
|
+
checkpoint_file))
|
|
908
1019
|
saved = json.load(f)
|
|
909
1020
|
assert 'images' in saved, \
|
|
910
1021
|
'The checkpoint file does not have the correct fields; cannot be restored'
|
|
@@ -931,7 +1042,15 @@ def main():
|
|
|
931
1042
|
elif os.path.isfile(args.image_file) and args.image_file.endswith('.json'):
|
|
932
1043
|
with open(args.image_file) as f:
|
|
933
1044
|
image_file_names = json.load(f)
|
|
934
|
-
print('Loaded {} image filenames from list file {}'.format(
|
|
1045
|
+
print('Loaded {} image filenames from .json list file {}'.format(
|
|
1046
|
+
len(image_file_names),args.image_file))
|
|
1047
|
+
|
|
1048
|
+
# A text list of image paths
|
|
1049
|
+
elif os.path.isfile(args.image_file) and args.image_file.endswith('.txt'):
|
|
1050
|
+
with open(args.image_file) as f:
|
|
1051
|
+
image_file_names = f.readlines()
|
|
1052
|
+
image_file_names = [fn.strip() for fn in image_file_names if len(fn.strip()) > 0]
|
|
1053
|
+
print('Loaded {} image filenames from .txt list file {}'.format(
|
|
935
1054
|
len(image_file_names),args.image_file))
|
|
936
1055
|
|
|
937
1056
|
# A single image file
|
|
@@ -945,14 +1064,7 @@ def main():
|
|
|
945
1064
|
|
|
946
1065
|
assert len(image_file_names) > 0, 'Specified image_file does not point to valid image files'
|
|
947
1066
|
assert os.path.exists(image_file_names[0]), \
|
|
948
|
-
'The first image to be
|
|
949
|
-
|
|
950
|
-
output_dir = os.path.dirname(args.output_file)
|
|
951
|
-
|
|
952
|
-
if len(output_dir) > 0:
|
|
953
|
-
os.makedirs(output_dir,exist_ok=True)
|
|
954
|
-
|
|
955
|
-
assert not os.path.isdir(args.output_file), 'Specified output file is a directory'
|
|
1067
|
+
'The first image to be processed does not exist at {}'.format(image_file_names[0])
|
|
956
1068
|
|
|
957
1069
|
# Test that we can write to the output_file's dir if checkpointing requested
|
|
958
1070
|
if args.checkpoint_frequency != -1:
|
|
@@ -961,7 +1073,7 @@ def main():
|
|
|
961
1073
|
checkpoint_path = args.checkpoint_path
|
|
962
1074
|
else:
|
|
963
1075
|
checkpoint_path = os.path.join(output_dir,
|
|
964
|
-
'
|
|
1076
|
+
'md_checkpoint_{}.json'.format(
|
|
965
1077
|
datetime.utcnow().strftime("%Y%m%d%H%M%S")))
|
|
966
1078
|
|
|
967
1079
|
# Don't overwrite existing checkpoint files, this is a sure-fire way to eventually
|
|
@@ -988,6 +1100,9 @@ def main():
|
|
|
988
1100
|
|
|
989
1101
|
else:
|
|
990
1102
|
|
|
1103
|
+
if args.checkpoint_path is not None:
|
|
1104
|
+
print('Warning: checkpointing disabled because checkpoint_frequency is -1, ' + \
|
|
1105
|
+
'but a checkpoint path was specified')
|
|
991
1106
|
checkpoint_path = None
|
|
992
1107
|
|
|
993
1108
|
start_time = time.time()
|