megadetector 10.0.9__tar.gz → 10.0.10__tar.gz
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-10.0.9/megadetector.egg-info → megadetector-10.0.10}/PKG-INFO +1 -1
- {megadetector-10.0.9 → megadetector-10.0.10}/README.md +2 -2
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/read_exif.py +15 -2
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/run_detector_batch.py +58 -41
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/run_md_and_speciesnet.py +81 -23
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/tf_detector.py +3 -5
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/classification_postprocessing.py +12 -13
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/directory_listing.py +3 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/path_utils.py +67 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/string_utils.py +21 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/wi_platform_utils.py +168 -24
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/wi_taxonomy_utils.py +1 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/visualize_detector_output.py +1 -0
- {megadetector-10.0.9 → megadetector-10.0.10/megadetector.egg-info}/PKG-INFO +1 -1
- {megadetector-10.0.9 → megadetector-10.0.10}/pyproject.toml +1 -1
- {megadetector-10.0.9 → megadetector-10.0.10}/LICENSE +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/README-package.md +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/api/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/api/batch_processing/integration/digiKam/setup.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/api/batch_processing/integration/eMammal/test_scripts/config_template.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/aggregate_classifier_probs.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/analyze_failed_images.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/cache_batchapi_outputs.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/create_classification_dataset.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/crop_detections.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/csv_to_json.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/detect_and_crop.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/efficientnet/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/efficientnet/model.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/efficientnet/utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/evaluate_model.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/identify_mislabeled_candidates.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/json_to_azcopy_list.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/json_validator.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/map_classification_categories.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/merge_classification_detection_output.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/prepare_classification_script.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/prepare_classification_script_mc.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/run_classifier.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/save_mislabeled.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/train_classifier.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/train_classifier_tf.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/classification/train_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/animl_to_md.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/annotations/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/annotations/annotation_constants.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/camtrap_dp_to_coco.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/cct_json_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/cct_to_md.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/cct_to_wi.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/coco_to_labelme.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/coco_to_yolo.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/databases/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/databases/add_width_and_height_to_db.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/databases/combine_coco_camera_traps_files.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/databases/integrity_check_json_db.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/databases/subset_json_db.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/generate_crops_from_cct.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/get_image_sizes.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/labelme_to_coco.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/labelme_to_yolo.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/create_lila_blank_set.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/create_lila_test_set.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/create_links_to_md_results_files.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/download_lila_subset.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/generate_lila_per_image_labels.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/get_lila_annotation_counts.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/get_lila_image_counts.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/lila_common.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/lila/test_lila_metadata_urls.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/mewc_to_md.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/ocr_tools.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/remap_coco_categories.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/remove_exif.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/rename_images.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/resize_coco_dataset.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/speciesnet_to_md.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/wi_download_csv_to_coco.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/yolo_output_to_md_output.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/yolo_to_coco.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/data_management/zamba_to_md.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/change_detection.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/process_video.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/pytorch_detector.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/run_detector.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/run_inference_with_yolov5_val.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/run_tiled_inference.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/detection/video_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/add_max_conf.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/categorize_detections_by_size.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/combine_batch_outputs.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/compare_batch_results.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/convert_output_format.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/create_crop_folder.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/detector_calibration.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/generate_csv_report.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/load_api_results.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/md_to_coco.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/md_to_labelme.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/md_to_wi.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/merge_detections.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/postprocess_batch_results.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/remap_detection_categories.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/render_detection_confusion_matrix.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/separate_detections_into_folders.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/subset_json_detector_output.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/top_folders_to_bottom.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/postprocessing/validate_batch_results.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/map_new_lila_datasets.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/preview_lila_taxonomy.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/retrieve_sample_image.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/simple_image_download.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/species_lookup.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/taxonomy_csv_checker.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/taxonomy_graph.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/taxonomy_mapping/validate_lila_category_mappings.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/tests/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/tests/test_nms_synthetic.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/ct_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/extract_frames_from_video.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/gpu_test.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/md_tests.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/process_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/split_locations_into_train_val.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/url_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/utils/write_html_image_list.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/__init__.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/plot_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/render_images_with_thumbnails.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/visualization_utils.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/visualize_db.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector/visualization/visualize_video_output.py +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector.egg-info/SOURCES.txt +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector.egg-info/dependency_links.txt +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector.egg-info/requires.txt +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/megadetector.egg-info/top_level.txt +0 -0
- {megadetector-10.0.9 → megadetector-10.0.10}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: megadetector
|
|
3
|
-
Version: 10.0.
|
|
3
|
+
Version: 10.0.10
|
|
4
4
|
Summary: MegaDetector is an AI model that helps conservation folks spend less time doing boring things with camera trap images.
|
|
5
5
|
Author-email: Your friendly neighborhood MegaDetector team <cameratraps@lila.science>
|
|
6
6
|
Maintainer-email: Your friendly neighborhood MegaDetector team <cameratraps@lila.science>
|
|
@@ -47,7 +47,6 @@ Here are a few of the organizations that have used MegaDetector... we're only li
|
|
|
47
47
|
* [Blackbird Environmental](https://blackbirdenv.com/)
|
|
48
48
|
* [Camelot](https://camelotproject.org/)
|
|
49
49
|
* [Canadian Parks and Wilderness Society (CPAWS) Northern Alberta Chapter](https://cpawsnab.org/)
|
|
50
|
-
* [Conservation X Labs](https://conservationxlabs.com/)
|
|
51
50
|
* [Czech University of Life Sciences Prague](https://www.czu.cz/en)
|
|
52
51
|
* [Dudek Camera Trap AI Image Toolkit (AIT)](https://ait.dudek.com/)
|
|
53
52
|
* [EcoLogic Consultants Ltd.](https://www.consult-ecologic.com/)
|
|
@@ -122,7 +121,6 @@ Here are a few of the organizations that have used MegaDetector... we're only li
|
|
|
122
121
|
|
|
123
122
|
* [School of Natural Sciences](https://www.utas.edu.au/natural-sciences), University of Tasmania ([story](https://www.utas.edu.au/about/news-and-stories/articles/2022/1204-innovative-camera-network-keeps-close-eye-on-tassie-wildlife))
|
|
124
123
|
* [Kenai National Wildlife Refuge](https://www.fws.gov/refuge/kenai), U.S. Fish & Wildlife Service ([story](https://www.peninsulaclarion.com/sports/refuge-notebook-new-technology-increases-efficiency-of-refuge-cameras/))
|
|
125
|
-
|
|
126
124
|
* [Idaho Department of Fish and Game](https://idfg.idaho.gov/) ([fancy PBS video](https://www.youtube.com/watch?v=uEsL8EZKpbA&t=261s&ab_channel=OutdoorIdaho))
|
|
127
125
|
* [Australian Wildlife Conservancy](https://www.australianwildlife.org/) (blog posts [1](https://www.australianwildlife.org/cutting-edge-technology-delivering-efficiency-gains-in-conservation/), [2](https://www.australianwildlife.org/efficiency-gains-at-the-cutting-edge-of-technology/), [3](https://www.australianwildlife.org/federal-grant-to-fund-ai-supported-wildlife-recognisers))
|
|
128
126
|
* [Bavarian Forest National Park](https://www.nationalpark-bayerischer-wald.bayern.de/english/index.htm) ([story](https://customers.microsoft.com/en-au/story/1667539539271247797-nationalparkbayerischerwald-azure-en))
|
|
@@ -148,6 +146,8 @@ Here are a few of the organizations that have used MegaDetector... we're only li
|
|
|
148
146
|
* [San Diego Zoo Wildlife Alliance](https://science.sandiegozoo.org/) ([Animl R package](https://github.com/conservationtechlab/animl))
|
|
149
147
|
* [TerrOïko](https://www.terroiko.fr/) ([OCAPI platform](https://www.terroiko.fr/ocapi))
|
|
150
148
|
* [Wildlife Division](https://www.michigan.gov/dnr/about/contact/wildlife), Michigan Department of Natural Resources ([blog post](https://www.michigan.gov/dnr/about/newsroom/releases/2025/08/18/dnr-researchers-to-test-trail-cameras-in-elk-survey))
|
|
149
|
+
* [Cleveland Metroparks](https://www.clevelandmetroparks.com/) ([presentation](https://www.clevelandmetroparks.com/getmedia/d4978f4b-5641-4e6b-ac16-b29e9e3d43d1/AI_8_21_25.pdf))
|
|
150
|
+
* [Conservation X Labs](https://conservationxlabs.com/) ([story](https://news.mongabay.com/2025/09/turning-camera-traps-into-real-time-sentinels-interview-with-conservation-x-labs-dante-wasmuht/))
|
|
151
151
|
|
|
152
152
|
Also see:
|
|
153
153
|
|
|
@@ -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
|
|
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
|
|
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:
|
|
@@ -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
|
|
@@ -890,7 +894,7 @@ def _process_images(im_files,
|
|
|
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,
|
|
@@ -907,7 +911,7 @@ def _process_images(im_files,
|
|
|
907
911
|
image_size=image_size,
|
|
908
912
|
include_image_size=include_image_size,
|
|
909
913
|
include_image_timestamp=include_image_timestamp,
|
|
910
|
-
|
|
914
|
+
include_exif_tags=include_exif_tags,
|
|
911
915
|
augment=augment)
|
|
912
916
|
|
|
913
917
|
if checkpoint_queue is not None:
|
|
@@ -929,7 +933,7 @@ def _process_image(im_file,
|
|
|
929
933
|
image_size=None,
|
|
930
934
|
include_image_size=False,
|
|
931
935
|
include_image_timestamp=False,
|
|
932
|
-
|
|
936
|
+
include_exif_tags=False,
|
|
933
937
|
augment=False):
|
|
934
938
|
"""
|
|
935
939
|
Runs a detector (typically MegaDetector) on a single image file.
|
|
@@ -947,7 +951,7 @@ def _process_image(im_file,
|
|
|
947
951
|
doing
|
|
948
952
|
include_image_size (bool, optional): should we include image size in the output for each image?
|
|
949
953
|
include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
|
|
950
|
-
|
|
954
|
+
include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
|
|
951
955
|
augment (bool, optional): enable image augmentation
|
|
952
956
|
|
|
953
957
|
Returns:
|
|
@@ -1000,7 +1004,9 @@ def _process_image(im_file,
|
|
|
1000
1004
|
if include_image_timestamp:
|
|
1001
1005
|
result['datetime'] = get_image_datetime(image)
|
|
1002
1006
|
|
|
1003
|
-
if
|
|
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
|
|
1004
1010
|
result['exif_metadata'] = read_exif.read_pil_exif(image,exif_options)
|
|
1005
1011
|
|
|
1006
1012
|
return result
|
|
@@ -1055,7 +1061,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1055
1061
|
class_mapping_filename=None,
|
|
1056
1062
|
include_image_size=False,
|
|
1057
1063
|
include_image_timestamp=False,
|
|
1058
|
-
|
|
1064
|
+
include_exif_tags=None,
|
|
1059
1065
|
augment=False,
|
|
1060
1066
|
force_model_download=False,
|
|
1061
1067
|
detector_options=None,
|
|
@@ -1088,7 +1094,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1088
1094
|
file or YOLOv5 dataset.yaml file
|
|
1089
1095
|
include_image_size (bool, optional): should we include image size in the output for each image?
|
|
1090
1096
|
include_image_timestamp (bool, optional): should we include image timestamps in the output for each image?
|
|
1091
|
-
|
|
1097
|
+
include_exif_tags (str, optional): comma-separated list of EXIF tags to include in output
|
|
1092
1098
|
augment (bool, optional): enable image augmentation
|
|
1093
1099
|
force_model_download (bool, optional): force downloading the model file if
|
|
1094
1100
|
a named model (e.g. "MDV5A") is supplied, even if the local file already
|
|
@@ -1207,7 +1213,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1207
1213
|
image_size=image_size,
|
|
1208
1214
|
include_image_size=include_image_size,
|
|
1209
1215
|
include_image_timestamp=include_image_timestamp,
|
|
1210
|
-
|
|
1216
|
+
include_exif_tags=include_exif_tags,
|
|
1211
1217
|
augment=augment,
|
|
1212
1218
|
detector_options=detector_options,
|
|
1213
1219
|
loader_workers=loader_workers,
|
|
@@ -1269,7 +1275,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1269
1275
|
image_size=image_size,
|
|
1270
1276
|
include_image_size=include_image_size,
|
|
1271
1277
|
include_image_timestamp=include_image_timestamp,
|
|
1272
|
-
|
|
1278
|
+
include_exif_tags=include_exif_tags,
|
|
1273
1279
|
augment=augment)
|
|
1274
1280
|
|
|
1275
1281
|
results.extend(batch_results)
|
|
@@ -1295,7 +1301,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1295
1301
|
image_size=image_size,
|
|
1296
1302
|
include_image_size=include_image_size,
|
|
1297
1303
|
include_image_timestamp=include_image_timestamp,
|
|
1298
|
-
|
|
1304
|
+
include_exif_tags=include_exif_tags,
|
|
1299
1305
|
augment=augment)
|
|
1300
1306
|
results.append(result)
|
|
1301
1307
|
|
|
@@ -1354,7 +1360,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1354
1360
|
checkpoint_queue=checkpoint_queue,
|
|
1355
1361
|
include_image_size=include_image_size,
|
|
1356
1362
|
include_image_timestamp=include_image_timestamp,
|
|
1357
|
-
|
|
1363
|
+
include_exif_tags=include_exif_tags,
|
|
1358
1364
|
augment=augment,
|
|
1359
1365
|
detector_options=detector_options),
|
|
1360
1366
|
image_chunks)
|
|
@@ -1374,7 +1380,7 @@ def load_and_run_detector_batch(model_file,
|
|
|
1374
1380
|
image_size=image_size,
|
|
1375
1381
|
include_image_size=include_image_size,
|
|
1376
1382
|
include_image_timestamp=include_image_timestamp,
|
|
1377
|
-
|
|
1383
|
+
include_exif_tags=include_exif_tags,
|
|
1378
1384
|
augment=augment,
|
|
1379
1385
|
detector_options=detector_options),
|
|
1380
1386
|
image_chunks)
|
|
@@ -1495,7 +1501,7 @@ def get_image_datetime(image):
|
|
|
1495
1501
|
returns None if EXIF datetime is not available.
|
|
1496
1502
|
"""
|
|
1497
1503
|
|
|
1498
|
-
exif_tags = read_exif.read_pil_exif(image,
|
|
1504
|
+
exif_tags = read_exif.read_pil_exif(image,exif_options_base)
|
|
1499
1505
|
|
|
1500
1506
|
try:
|
|
1501
1507
|
datetime_str = exif_tags['DateTimeOriginal']
|
|
@@ -1654,7 +1660,7 @@ if False:
|
|
|
1654
1660
|
class_mapping_filename = None
|
|
1655
1661
|
include_image_size = True
|
|
1656
1662
|
include_image_timestamp = True
|
|
1657
|
-
|
|
1663
|
+
include_exif_tags = None
|
|
1658
1664
|
overwrite_handling = None
|
|
1659
1665
|
|
|
1660
1666
|
# Generate a command line
|
|
@@ -1689,8 +1695,8 @@ if False:
|
|
|
1689
1695
|
cmd += ' --include_image_size'
|
|
1690
1696
|
if include_image_timestamp:
|
|
1691
1697
|
cmd += ' --include_image_timestamp'
|
|
1692
|
-
if
|
|
1693
|
-
cmd += ' --
|
|
1698
|
+
if include_exif_tags is not None:
|
|
1699
|
+
cmd += ' --include_exif_tags "{}"'.format(include_exif_tags)
|
|
1694
1700
|
if overwrite_handling is not None:
|
|
1695
1701
|
cmd += ' --overwrite_handling {}'.format(overwrite_handling)
|
|
1696
1702
|
|
|
@@ -1837,9 +1843,10 @@ def main(): # noqa
|
|
|
1837
1843
|
help='Include image datetime (if available) in output file'
|
|
1838
1844
|
)
|
|
1839
1845
|
parser.add_argument(
|
|
1840
|
-
'--
|
|
1841
|
-
|
|
1842
|
-
|
|
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'
|
|
1843
1850
|
)
|
|
1844
1851
|
parser.add_argument(
|
|
1845
1852
|
'--overwrite_handling',
|
|
@@ -1878,6 +1885,12 @@ def main(): # noqa
|
|
|
1878
1885
|
action='store_true',
|
|
1879
1886
|
help=argparse.SUPPRESS)
|
|
1880
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
|
+
|
|
1881
1894
|
if len(sys.argv[1:]) == 0:
|
|
1882
1895
|
parser.print_help()
|
|
1883
1896
|
parser.exit()
|
|
@@ -1888,6 +1901,10 @@ def main(): # noqa
|
|
|
1888
1901
|
if args.use_threads_for_queue:
|
|
1889
1902
|
use_threads_for_queue = True
|
|
1890
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
|
+
|
|
1891
1908
|
detector_options = parse_kvp_list(args.detector_options)
|
|
1892
1909
|
|
|
1893
1910
|
# If the specified detector file is really the name of a known model, find
|
|
@@ -2094,7 +2111,7 @@ def main(): # noqa
|
|
|
2094
2111
|
class_mapping_filename=args.class_mapping_filename,
|
|
2095
2112
|
include_image_size=args.include_image_size,
|
|
2096
2113
|
include_image_timestamp=args.include_image_timestamp,
|
|
2097
|
-
|
|
2114
|
+
include_exif_tags=args.include_exif_tags,
|
|
2098
2115
|
augment=args.augment,
|
|
2099
2116
|
# Don't download the model *again*
|
|
2100
2117
|
force_model_download=False,
|