megadetector 5.0.16__tar.gz → 5.0.17__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-5.0.16/megadetector.egg-info → megadetector-5.0.17}/PKG-INFO +4 -6
- {megadetector-5.0.16 → megadetector-5.0.17}/README-package.md +3 -5
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/snapshot_safari_importer_reprise.py +28 -16
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/process_video.py +20 -10
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/run_detector_batch.py +1 -1
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/video_utils.py +15 -4
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/postprocess_batch_results.py +4 -4
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +5 -2
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/ct_utils.py +48 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/md_tests.py +43 -15
- megadetector-5.0.17/megadetector/utils/torch_test.py +32 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/url_utils.py +94 -3
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/visualization/visualization_utils.py +21 -6
- {megadetector-5.0.16 → megadetector-5.0.17/megadetector.egg-info}/PKG-INFO +4 -6
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector.egg-info/SOURCES.txt +1 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/pyproject.toml +1 -1
- {megadetector-5.0.16 → megadetector-5.0.17}/LICENSE +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/README.md +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/batch_service/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/batch_service/score.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server_api_config.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server_app_config.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server_batch_job_manager.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server_job_status_table.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server_orchestration.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core/server_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core_support/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_core_support/aggregate_results_manually.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_support/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/api_support/summarize_daily_activity.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/data_preparation/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/integration/digiKam/setup.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/integration/eMammal/test_scripts/config_template.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/api_core/animal_detection_api/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/api_core/animal_detection_api/api_backend.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/api_core/animal_detection_api/api_frontend.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/api_core/animal_detection_api/config.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/api_core/tests/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/api/synchronous/api_core/tests/load_test.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/aggregate_classifier_probs.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/analyze_failed_images.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/cache_batchapi_outputs.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/create_classification_dataset.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/crop_detections.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/csv_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/detect_and_crop.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/efficientnet/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/efficientnet/model.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/efficientnet/utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/evaluate_model.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/identify_mislabeled_candidates.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/json_to_azcopy_list.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/json_validator.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/map_classification_categories.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/merge_classification_detection_output.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/prepare_classification_script.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/prepare_classification_script_mc.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/run_classifier.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/save_mislabeled.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/train_classifier.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/train_classifier_tf.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/classification/train_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/annotations/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/annotations/annotation_constants.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/camtrap_dp_to_coco.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/cct_json_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/cct_to_md.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/cct_to_wi.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/coco_to_labelme.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/coco_to_yolo.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/databases/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/databases/add_width_and_height_to_db.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/databases/combine_coco_camera_traps_files.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/databases/integrity_check_json_db.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/databases/subset_json_db.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/generate_crops_from_cct.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/get_image_sizes.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/add_nacti_sizes.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/add_timestamps_to_icct.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/animl_results_to_md_results.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/auckland_doc_test_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/auckland_doc_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/awc_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/bellevue_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/cacophony-thermal-importer.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/carrizo_shrubfree_2018.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/carrizo_trail_cam_2017.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/cct_field_adjustments.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/channel_islands_to_cct.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/eMammal/copy_and_unzip_emammal.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/eMammal/eMammal_helpers.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/eMammal/make_eMammal_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/ena24_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/filenames_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/helena_to_cct.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/idaho-camera-traps.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/idfg_iwildcam_lila_prep.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/import_desert_lion_conservation_camera_traps.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/jb_csv_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/mcgill_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/missouri_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/nacti_fieldname_adjustments.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/noaa_seals_2019.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/pc_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/plot_wni_giraffes.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/prepare-noaa-fish-data-for-lila.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/prepare_zsl_imerit.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/rspb_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/save_the_elephants_survey_A.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/save_the_elephants_survey_B.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/snapshot_safari_importer.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/snapshot_serengeti_lila.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/snapshotserengeti/make_full_SS_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/snapshotserengeti/make_per_season_SS_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/sulross_get_exif.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/timelapse_csv_set_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/ubc_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/umn_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/wellington_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/wi_to_json.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/importers/zamba_results_to_md_results.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/labelme_to_coco.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/labelme_to_yolo.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/add_locations_to_island_camera_traps.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/add_locations_to_nacti.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/create_lila_blank_set.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/create_lila_test_set.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/create_links_to_md_results_files.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/download_lila_subset.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/generate_lila_per_image_labels.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/get_lila_annotation_counts.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/get_lila_image_counts.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/lila_common.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/lila/test_lila_metadata_urls.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/ocr_tools.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/read_exif.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/remap_coco_categories.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/remove_exif.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/rename_images.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/resize_coco_dataset.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/wi_download_csv_to_coco.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/yolo_output_to_md_output.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/data_management/yolo_to_coco.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/detector_training/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/detector_training/model_main_tf2.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/pytorch_detector.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/run_detector.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/run_inference_with_yolov5_val.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/run_tiled_inference.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/detection/tf_detector.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/add_max_conf.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/categorize_detections_by_size.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/classification_postprocessing.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/combine_api_outputs.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/compare_batch_results.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/convert_output_format.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/load_api_results.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/md_to_coco.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/md_to_labelme.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/merge_detections.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/remap_detection_categories.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/render_detection_confusion_matrix.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/separate_detections_into_folders.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/subset_json_detector_output.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/top_folders_to_bottom.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/map_new_lila_datasets.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/preview_lila_taxonomy.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/retrieve_sample_image.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/simple_image_download.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/species_lookup.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/taxonomy_csv_checker.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/taxonomy_graph.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/taxonomy_mapping/validate_lila_category_mappings.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/azure_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/directory_listing.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/path_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/process_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/sas_blob_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/split_locations_into_train_val.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/string_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/utils/write_html_image_list.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/visualization/__init__.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/visualization/plot_utils.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/visualization/render_images_with_thumbnails.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/visualization/visualize_db.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector/visualization/visualize_detector_output.py +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector.egg-info/dependency_links.txt +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector.egg-info/requires.txt +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/megadetector.egg-info/top_level.txt +0 -0
- {megadetector-5.0.16 → megadetector-5.0.17}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: megadetector
|
|
3
|
-
Version: 5.0.
|
|
3
|
+
Version: 5.0.17
|
|
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>
|
|
@@ -57,22 +57,20 @@ This package is a pip-installable version of the support/inference code for [Meg
|
|
|
57
57
|
If you aren't looking for the Python package specifically, and you just want to learn more about what MegaDetector is all about, head over to the [MegaDetector repo](https://github.com/agentmorris/MegaDetector/?tab=readme-ov-file#megadetector).
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
## Reasons
|
|
60
|
+
## Reasons might not be looking for this package
|
|
61
61
|
|
|
62
62
|
### If you are an ecologist...
|
|
63
63
|
|
|
64
|
-
If you are an ecologist looking to use MegaDetector to help you get through your camera trap images, you probably don't want this package. We recommend starting with our "[Getting started with MegaDetector](https://github.com/agentmorris/MegaDetector/blob/main/getting-started.md)" page, then digging in to the [MegaDetector User Guide](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md), which will walk you through the process of using MegaDetector.
|
|
64
|
+
If you are an ecologist looking to use MegaDetector to help you get through your camera trap images, you probably don't want this package, or at least you probably don't want to start at this page. We recommend starting with our "[Getting started with MegaDetector](https://github.com/agentmorris/MegaDetector/blob/main/getting-started.md)" page, then digging in to the [MegaDetector User Guide](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md), which will walk you through the process of using MegaDetector.
|
|
65
65
|
|
|
66
66
|
### If you are a computer-vision-y type...
|
|
67
67
|
|
|
68
|
-
If you are a computer-vision-y person looking to run or fine-tune MegaDetector programmatically, you
|
|
68
|
+
If you are a computer-vision-y person looking to run or fine-tune MegaDetector programmatically, you probably don't want this package. MegaDetector is just a fine-tuned version of [YOLOv5](https://github.com/ultralytics/yolov5), and the [ultralytics](https://github.com/ultralytics/ultralytics/) package (from the developers of YOLOv5) has a zillion bells and whistles for both inference and fine-tuning that this package doesn't.
|
|
69
69
|
|
|
70
70
|
## Reasons you might want to use this package
|
|
71
71
|
|
|
72
72
|
If you want to programmatically interact with the postprocessing tools from the MegaDetector repo, or programmatically run MegaDetector in a way that produces [Timelapse](https://saul.cpsc.ucalgary.ca/timelapse)-friendly output (i.e., output in the standard [MegaDetector output format](https://github.com/agentmorris/MegaDetector/tree/main/megadetector/api/batch_processing#megadetector-batch-output-format)), this package might be for you.
|
|
73
73
|
|
|
74
|
-
Although even if that describes you, you <i>still</i> might be better off cloning the MegaDetector repo. Pip-installability requires that some dependencies be newer than what was available at the time MDv5 was trained, so results are <i>very slightly</i> different than results produced in the "official" environment. These differences <i>probably</i> don't matter much, but they have not been formally characterized.
|
|
75
|
-
|
|
76
74
|
## If I haven't talked you out of using this package...
|
|
77
75
|
|
|
78
76
|
To install:
|
|
@@ -5,22 +5,20 @@ This package is a pip-installable version of the support/inference code for [Meg
|
|
|
5
5
|
If you aren't looking for the Python package specifically, and you just want to learn more about what MegaDetector is all about, head over to the [MegaDetector repo](https://github.com/agentmorris/MegaDetector/?tab=readme-ov-file#megadetector).
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
## Reasons
|
|
8
|
+
## Reasons might not be looking for this package
|
|
9
9
|
|
|
10
10
|
### If you are an ecologist...
|
|
11
11
|
|
|
12
|
-
If you are an ecologist looking to use MegaDetector to help you get through your camera trap images, you probably don't want this package. We recommend starting with our "[Getting started with MegaDetector](https://github.com/agentmorris/MegaDetector/blob/main/getting-started.md)" page, then digging in to the [MegaDetector User Guide](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md), which will walk you through the process of using MegaDetector.
|
|
12
|
+
If you are an ecologist looking to use MegaDetector to help you get through your camera trap images, you probably don't want this package, or at least you probably don't want to start at this page. We recommend starting with our "[Getting started with MegaDetector](https://github.com/agentmorris/MegaDetector/blob/main/getting-started.md)" page, then digging in to the [MegaDetector User Guide](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md), which will walk you through the process of using MegaDetector.
|
|
13
13
|
|
|
14
14
|
### If you are a computer-vision-y type...
|
|
15
15
|
|
|
16
|
-
If you are a computer-vision-y person looking to run or fine-tune MegaDetector programmatically, you
|
|
16
|
+
If you are a computer-vision-y person looking to run or fine-tune MegaDetector programmatically, you probably don't want this package. MegaDetector is just a fine-tuned version of [YOLOv5](https://github.com/ultralytics/yolov5), and the [ultralytics](https://github.com/ultralytics/ultralytics/) package (from the developers of YOLOv5) has a zillion bells and whistles for both inference and fine-tuning that this package doesn't.
|
|
17
17
|
|
|
18
18
|
## Reasons you might want to use this package
|
|
19
19
|
|
|
20
20
|
If you want to programmatically interact with the postprocessing tools from the MegaDetector repo, or programmatically run MegaDetector in a way that produces [Timelapse](https://saul.cpsc.ucalgary.ca/timelapse)-friendly output (i.e., output in the standard [MegaDetector output format](https://github.com/agentmorris/MegaDetector/tree/main/megadetector/api/batch_processing#megadetector-batch-output-format)), this package might be for you.
|
|
21
21
|
|
|
22
|
-
Although even if that describes you, you <i>still</i> might be better off cloning the MegaDetector repo. Pip-installability requires that some dependencies be newer than what was available at the time MDv5 was trained, so results are <i>very slightly</i> different than results produced in the "official" environment. These differences <i>probably</i> don't matter much, but they have not been formally characterized.
|
|
23
|
-
|
|
24
22
|
## If I haven't talked you out of using this package...
|
|
25
23
|
|
|
26
24
|
To install:
|
|
@@ -24,7 +24,7 @@ from collections import defaultdict
|
|
|
24
24
|
|
|
25
25
|
from megadetector.utils import path_utils
|
|
26
26
|
|
|
27
|
-
input_base = '
|
|
27
|
+
input_base = 'e:/'
|
|
28
28
|
output_base = os.path.expanduser('~/data/snapshot-safari-metadata')
|
|
29
29
|
file_list_cache_file = os.path.join(output_base,'file_list.json')
|
|
30
30
|
|
|
@@ -76,23 +76,16 @@ print('Found a total of {} files, {} of which are images'.format(
|
|
|
76
76
|
len(all_files_relative),len(all_image_files)))
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
#%% Copy all csv files to the annotation cache folder
|
|
79
|
+
#%% Copy all .csv files to the annotation cache folder
|
|
80
80
|
|
|
81
81
|
# fn = csv_files[0]
|
|
82
|
-
for fn in csv_files:
|
|
82
|
+
for fn in tqdm(csv_files):
|
|
83
|
+
|
|
83
84
|
target_file = os.path.join(annotation_cache_dir,os.path.basename(fn))
|
|
84
85
|
source_file = os.path.join(input_base,fn)
|
|
85
86
|
shutil.copyfile(source_file,target_file)
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
"""
|
|
89
|
-
Later cells will ask to read a .csv file from the original hard drive;
|
|
90
|
-
read from the annotation cache instead.
|
|
91
|
-
"""
|
|
92
|
-
|
|
93
|
-
cached_csv_file = os.path.join(annotation_cache_dir,os.path.basename(fn))
|
|
94
|
-
df = pd.read_csv(cached_csv_file)
|
|
95
|
-
return df
|
|
88
|
+
print('Copied {} .csv files to cache folder'.format(len(csv_files)))
|
|
96
89
|
|
|
97
90
|
|
|
98
91
|
#%% List project folders
|
|
@@ -123,6 +116,21 @@ project_folder_to_project_code = {v: k for k, v in project_code_to_project_folde
|
|
|
123
116
|
project_codes = sorted(list(project_code_to_project_folder.keys()))
|
|
124
117
|
project_folders = sorted(list(project_code_to_project_folder.values()))
|
|
125
118
|
|
|
119
|
+
print('Eumerated {} project folders'.format(len(project_folders)))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
#%% Support functions
|
|
123
|
+
|
|
124
|
+
def read_cached_csv_file(fn):
|
|
125
|
+
"""
|
|
126
|
+
Later cells will ask to read a .csv file from the original hard drive;
|
|
127
|
+
read from the annotation cache instead.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
cached_csv_file = os.path.join(annotation_cache_dir,os.path.basename(fn))
|
|
131
|
+
df = pd.read_csv(cached_csv_file)
|
|
132
|
+
return df
|
|
133
|
+
|
|
126
134
|
def file_to_project_folder(fn):
|
|
127
135
|
"""
|
|
128
136
|
For a given filename relative to the drive root, return the corresponding
|
|
@@ -138,7 +146,6 @@ def file_to_project_folder(fn):
|
|
|
138
146
|
assert project_folder in project_folders
|
|
139
147
|
return project_folder
|
|
140
148
|
|
|
141
|
-
|
|
142
149
|
def file_to_project_code(fn):
|
|
143
150
|
"""
|
|
144
151
|
For a given filename relative to the drive root, return the corresponding
|
|
@@ -147,6 +154,9 @@ def file_to_project_code(fn):
|
|
|
147
154
|
|
|
148
155
|
return project_folder_to_project_code[file_to_project_folder(fn)]
|
|
149
156
|
|
|
157
|
+
|
|
158
|
+
#%% Consistency checking
|
|
159
|
+
|
|
150
160
|
assert file_to_project_folder(
|
|
151
161
|
'APN/APN_S2/DW/DW_R5/APN_S2_DW_R5_IMAG0003.JPG') == 'APN'
|
|
152
162
|
assert file_to_project_folder(
|
|
@@ -163,9 +173,11 @@ assert file_to_project_code(
|
|
|
163
173
|
#
|
|
164
174
|
# E.g.:
|
|
165
175
|
#
|
|
166
|
-
# 'DHP': [
|
|
167
|
-
#
|
|
168
|
-
#
|
|
176
|
+
# 'DHP': [
|
|
177
|
+
# 'Snapshot South Africa/DHP/LILA_Reports/DHP_S1_report_lila.csv',
|
|
178
|
+
# 'Snapshot South Africa/DHP/LILA_Reports/DHP_S2_report_lila.csv',
|
|
179
|
+
# 'Snapshot South Africa/DHP/LILA_Reports/DHP_S3_report_lila.csv'
|
|
180
|
+
# ]
|
|
169
181
|
#
|
|
170
182
|
project_code_to_report_files = defaultdict(list)
|
|
171
183
|
|
|
@@ -345,7 +345,8 @@ def process_video(options):
|
|
|
345
345
|
caller_provided_rendering_output_folder = (options.frame_rendering_folder is not None)
|
|
346
346
|
|
|
347
347
|
frame_output_folder = None
|
|
348
|
-
|
|
348
|
+
frame_filenames = None
|
|
349
|
+
|
|
349
350
|
# If we should re-use existing results, and the output file exists, don't bother running MD
|
|
350
351
|
if (options.reuse_results_if_available and os.path.isfile(options.output_json_file)):
|
|
351
352
|
|
|
@@ -383,7 +384,7 @@ def process_video(options):
|
|
|
383
384
|
verbose=options.verbose,
|
|
384
385
|
frames_to_process=options.frames_to_extract)
|
|
385
386
|
|
|
386
|
-
_add_frame_numbers_to_results(frame_results['results'])
|
|
387
|
+
frame_results['results'] = _add_frame_numbers_to_results(frame_results['results'])
|
|
387
388
|
|
|
388
389
|
run_detector_batch.write_results_to_file(
|
|
389
390
|
frame_results['results'],
|
|
@@ -444,7 +445,7 @@ def process_video(options):
|
|
|
444
445
|
augment=options.augment,
|
|
445
446
|
image_size=options.image_size)
|
|
446
447
|
|
|
447
|
-
_add_frame_numbers_to_results(results)
|
|
448
|
+
results = _add_frame_numbers_to_results(results)
|
|
448
449
|
|
|
449
450
|
run_detector_batch.write_results_to_file(
|
|
450
451
|
results,
|
|
@@ -545,6 +546,7 @@ def process_video_folder(options):
|
|
|
545
546
|
|
|
546
547
|
frame_output_folder = None
|
|
547
548
|
image_file_names = None
|
|
549
|
+
video_filename_to_fs = {}
|
|
548
550
|
|
|
549
551
|
# Run MD in memory if we don't need to generate frames
|
|
550
552
|
#
|
|
@@ -575,6 +577,10 @@ def process_video_folder(options):
|
|
|
575
577
|
|
|
576
578
|
video_results = md_results['results']
|
|
577
579
|
|
|
580
|
+
for i_video,video_filename in enumerate(md_results['video_filenames']):
|
|
581
|
+
assert video_filename not in video_filename_to_fs
|
|
582
|
+
video_filename_to_fs[video_filename] = md_results['frame_rates'][i_video]
|
|
583
|
+
|
|
578
584
|
all_frame_results = []
|
|
579
585
|
|
|
580
586
|
# r = video_results[0]
|
|
@@ -586,13 +592,15 @@ def process_video_folder(options):
|
|
|
586
592
|
all_frame_results,
|
|
587
593
|
frames_json,
|
|
588
594
|
relative_path_base=None,
|
|
589
|
-
detector_file=options.model_file
|
|
590
|
-
custom_metadata={'video_frame_rate':md_results['frame_rates']})
|
|
595
|
+
detector_file=options.model_file)
|
|
591
596
|
|
|
592
597
|
else:
|
|
593
598
|
|
|
594
599
|
## Split every video into frames
|
|
595
600
|
|
|
601
|
+
if options.verbose:
|
|
602
|
+
print('Extracting frames for folder {}'.format(options.input_video_file))
|
|
603
|
+
|
|
596
604
|
if caller_provided_frame_output_folder:
|
|
597
605
|
frame_output_folder = options.frame_folder
|
|
598
606
|
else:
|
|
@@ -600,8 +608,6 @@ def process_video_folder(options):
|
|
|
600
608
|
|
|
601
609
|
os.makedirs(frame_output_folder, exist_ok=True)
|
|
602
610
|
|
|
603
|
-
print('Extracting frames')
|
|
604
|
-
|
|
605
611
|
frame_filenames, Fs, video_filenames = \
|
|
606
612
|
video_folder_to_frames(input_folder=options.input_video_file,
|
|
607
613
|
output_folder_base=frame_output_folder,
|
|
@@ -615,6 +621,10 @@ def process_video_folder(options):
|
|
|
615
621
|
frames_to_extract=options.frames_to_extract,
|
|
616
622
|
allow_empty_videos=options.allow_empty_videos)
|
|
617
623
|
|
|
624
|
+
for i_video,video_filename in enumerate(video_filenames):
|
|
625
|
+
assert video_filename not in video_filename_to_fs
|
|
626
|
+
video_filename_to_fs[video_filename] = Fs[i_video]
|
|
627
|
+
|
|
618
628
|
print('Extracted frames for {} videos'.format(len(set(video_filenames))))
|
|
619
629
|
image_file_names = list(itertools.chain.from_iterable(frame_filenames))
|
|
620
630
|
|
|
@@ -660,15 +670,15 @@ def process_video_folder(options):
|
|
|
660
670
|
results,
|
|
661
671
|
frames_json,
|
|
662
672
|
relative_path_base=frame_output_folder,
|
|
663
|
-
detector_file=options.model_file
|
|
664
|
-
custom_metadata={'video_frame_rate':Fs})
|
|
673
|
+
detector_file=options.model_file)
|
|
665
674
|
|
|
666
675
|
# ...if we're running MD on in-memory frames vs. extracting frames to disk
|
|
667
676
|
|
|
668
677
|
## Convert frame-level results to video-level results
|
|
669
678
|
|
|
670
679
|
print('Converting frame-level results to video-level results')
|
|
671
|
-
frame_results_to_video_results(frames_json,video_json
|
|
680
|
+
frame_results_to_video_results(frames_json,video_json,
|
|
681
|
+
video_filename_to_frame_rate=video_filename_to_fs)
|
|
672
682
|
|
|
673
683
|
|
|
674
684
|
## (Optionally) render output videos
|
|
@@ -846,7 +846,7 @@ def write_results_to_file(results,
|
|
|
846
846
|
https://github.com/agentmorris/MegaDetector/tree/main/megadetector/api/batch_processing#batch-processing-api-output-format
|
|
847
847
|
|
|
848
848
|
Args:
|
|
849
|
-
results (list):
|
|
849
|
+
results (list): list of dict, each dict represents detections on one image
|
|
850
850
|
output_file (str): path to JSON output file, should end in '.json'
|
|
851
851
|
relative_path_base (str, optional): path to a directory as the base for relative paths, can
|
|
852
852
|
be None if the paths in [results] are absolute
|
|
@@ -22,6 +22,7 @@ from functools import partial
|
|
|
22
22
|
from inspect import signature
|
|
23
23
|
|
|
24
24
|
from megadetector.utils import path_utils
|
|
25
|
+
from megadetector.utils.ct_utils import sort_list_of_dicts_by_key
|
|
25
26
|
from megadetector.visualization import visualization_utils as vis_utils
|
|
26
27
|
|
|
27
28
|
default_fourcc = 'h264'
|
|
@@ -197,7 +198,7 @@ def _filename_to_frame_number(filename):
|
|
|
197
198
|
def _add_frame_numbers_to_results(results):
|
|
198
199
|
"""
|
|
199
200
|
Given the 'images' list from a set of MD results that was generated on video frames,
|
|
200
|
-
add a 'frame_number' field to each image.
|
|
201
|
+
add a 'frame_number' field to each image, and return the list, sorted by frame number.
|
|
201
202
|
|
|
202
203
|
Args:
|
|
203
204
|
results (list): list of image dicts
|
|
@@ -208,6 +209,9 @@ def _add_frame_numbers_to_results(results):
|
|
|
208
209
|
fn = im['file']
|
|
209
210
|
frame_number = _filename_to_frame_number(fn)
|
|
210
211
|
im['frame_number'] = frame_number
|
|
212
|
+
|
|
213
|
+
results = sort_list_of_dicts_by_key(results,'frame_number')
|
|
214
|
+
return results
|
|
211
215
|
|
|
212
216
|
|
|
213
217
|
def run_callback_on_frames(input_video_file,
|
|
@@ -332,8 +336,8 @@ def run_callback_on_frames_for_folder(input_video_folder,
|
|
|
332
336
|
recursive (bool, optional): recurse into [input_video_folder]
|
|
333
337
|
|
|
334
338
|
Returns:
|
|
335
|
-
dict: dict with keys 'video_filenames' (list), 'frame_rates' (list of floats),
|
|
336
|
-
video_filenames will
|
|
339
|
+
dict: dict with keys 'video_filenames' (list of str), 'frame_rates' (list of floats),
|
|
340
|
+
'results' (list of list of dicts). 'video_filenames' will contain *relative* filenames.
|
|
337
341
|
"""
|
|
338
342
|
|
|
339
343
|
to_return = {'video_filenames':[],'frame_rates':[],'results':[]}
|
|
@@ -777,7 +781,8 @@ class FrameToVideoOptions:
|
|
|
777
781
|
self.non_video_behavior = 'error'
|
|
778
782
|
|
|
779
783
|
|
|
780
|
-
def frame_results_to_video_results(input_file,output_file,options=None
|
|
784
|
+
def frame_results_to_video_results(input_file,output_file,options=None,
|
|
785
|
+
video_filename_to_frame_rate=None):
|
|
781
786
|
"""
|
|
782
787
|
Given an MD results file produced at the *frame* level, corresponding to a directory
|
|
783
788
|
created with video_folder_to_frames, maps those frame-level results back to the
|
|
@@ -790,6 +795,8 @@ def frame_results_to_video_results(input_file,output_file,options=None):
|
|
|
790
795
|
output_file (str): the .json file to which we should write video-level results
|
|
791
796
|
options (FrameToVideoOptions, optional): parameters for converting frame-level results
|
|
792
797
|
to video-level results, see FrameToVideoOptions for details
|
|
798
|
+
video_filename_to_frame_rate (dict): maps (relative) video path names to frame rates,
|
|
799
|
+
used only to populate the output file
|
|
793
800
|
"""
|
|
794
801
|
|
|
795
802
|
if options is None:
|
|
@@ -878,6 +885,10 @@ def frame_results_to_video_results(input_file,output_file,options=None):
|
|
|
878
885
|
im_out['file'] = video_name
|
|
879
886
|
im_out['detections'] = canonical_detections
|
|
880
887
|
|
|
888
|
+
if (video_filename_to_frame_rate is not None) and \
|
|
889
|
+
(video_name in video_filename_to_frame_rate):
|
|
890
|
+
im_out['frame_rate'] = video_filename_to_frame_rate[video_name]
|
|
891
|
+
|
|
881
892
|
# 'max_detection_conf' is no longer included in output files by default
|
|
882
893
|
if False:
|
|
883
894
|
im_out['max_detection_conf'] = 0
|
{megadetector-5.0.16 → megadetector-5.0.17}/megadetector/postprocessing/postprocess_batch_results.py
RENAMED
|
@@ -770,7 +770,7 @@ def _render_image_no_gt(file_info,detection_categories_to_results_name,
|
|
|
770
770
|
if det['conf'] > max_conf:
|
|
771
771
|
max_conf = det['conf']
|
|
772
772
|
|
|
773
|
-
if ('classifications' in det):
|
|
773
|
+
if ('classifications' in det) and (len(det['classifications']) > 0):
|
|
774
774
|
|
|
775
775
|
# This is a list of [class,confidence] pairs, sorted by confidence
|
|
776
776
|
classifications = det['classifications']
|
|
@@ -1203,13 +1203,13 @@ def process_batch_results(options):
|
|
|
1203
1203
|
# Rows / first index is ground truth, columns / second index is predicted category
|
|
1204
1204
|
classifier_cm = collections.defaultdict(lambda: collections.defaultdict(lambda: 0))
|
|
1205
1205
|
|
|
1206
|
-
#
|
|
1206
|
+
# i_detection = 0; fn = detector_files[i_detection]; print(fn)
|
|
1207
1207
|
assert len(detector_files) == len(detections_df)
|
|
1208
|
-
for
|
|
1208
|
+
for i_detection, fn in enumerate(detector_files):
|
|
1209
1209
|
|
|
1210
1210
|
image_id = ground_truth_indexed_db.filename_to_id[fn]
|
|
1211
1211
|
image = ground_truth_indexed_db.image_id_to_image[image_id]
|
|
1212
|
-
detections = detections_df['detections'].iloc[
|
|
1212
|
+
detections = detections_df['detections'].iloc[i_detection]
|
|
1213
1213
|
pred_class_ids = [det['classifications'][0][0] \
|
|
1214
1214
|
for det in detections if 'classifications' in det.keys()]
|
|
1215
1215
|
pred_classnames = [classification_categories[pd] for pd in pred_class_ids]
|
|
@@ -210,9 +210,12 @@ class RepeatDetectionOptions:
|
|
|
210
210
|
#: a/b/c/RECONYX100 and a/b/c/RECONYX101 may really be the same camera).
|
|
211
211
|
#:
|
|
212
212
|
#: See ct_utils for a common replacement function that handles most common
|
|
213
|
-
#: manufacturer folder names
|
|
213
|
+
#: manufacturer folder names:
|
|
214
|
+
#:
|
|
215
|
+
#: from megadetector.utils import ct_utils
|
|
216
|
+
#: self.customDirNameFunction = ct_utils.image_file_to_camera_folder
|
|
214
217
|
self.customDirNameFunction = None
|
|
215
|
-
|
|
218
|
+
|
|
216
219
|
#: Include only specific folders, mutually exclusive with [excludeFolders]
|
|
217
220
|
self.includeFolders = None
|
|
218
221
|
|
|
@@ -16,6 +16,8 @@ import os
|
|
|
16
16
|
import jsonpickle
|
|
17
17
|
import numpy as np
|
|
18
18
|
|
|
19
|
+
from operator import itemgetter
|
|
20
|
+
|
|
19
21
|
# List of file extensions we'll consider images; comparisons will be case-insensitive
|
|
20
22
|
# (i.e., no need to include both .jpg and .JPG on this list).
|
|
21
23
|
image_extensions = ['.jpg', '.jpeg', '.gif', '.png']
|
|
@@ -294,6 +296,29 @@ def get_max_conf(im):
|
|
|
294
296
|
return max_conf
|
|
295
297
|
|
|
296
298
|
|
|
299
|
+
def sort_results_for_image(im):
|
|
300
|
+
"""
|
|
301
|
+
Sort classification and detection results in descending order by confidence (in place).
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
im (dict): image dictionary in the MD output format (with a 'detections' field)
|
|
305
|
+
"""
|
|
306
|
+
if 'detections' not in im or im['detections'] is None:
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
# Sort detections in descending order by confidence
|
|
310
|
+
im['detections'] = sort_list_of_dicts_by_key(im['detections'],k='conf',reverse=True)
|
|
311
|
+
|
|
312
|
+
for det in im['detections']:
|
|
313
|
+
|
|
314
|
+
# Sort classifications (which are (class,conf) tuples) in descending order by confidence
|
|
315
|
+
if 'classifications' in det and \
|
|
316
|
+
(det['classifications'] is not None) and \
|
|
317
|
+
(len(det['classifications']) > 0):
|
|
318
|
+
L = det['classifications']
|
|
319
|
+
det['classifications'] = sorted(L,key=itemgetter(1),reverse=True)
|
|
320
|
+
|
|
321
|
+
|
|
297
322
|
def point_dist(p1,p2):
|
|
298
323
|
"""
|
|
299
324
|
Computes the distance between two points, represented as length-two tuples.
|
|
@@ -406,6 +431,21 @@ def split_list_into_n_chunks(L, n, chunk_strategy='greedy'):
|
|
|
406
431
|
raise ValueError('Invalid chunk strategy: {}'.format(chunk_strategy))
|
|
407
432
|
|
|
408
433
|
|
|
434
|
+
def sort_list_of_dicts_by_key(L,k,reverse=False):
|
|
435
|
+
"""
|
|
436
|
+
Sorts the list of dictionaries [L] by the key [k].
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
L (list): list of dictionaries to sort
|
|
440
|
+
k (object, typically str): the sort key
|
|
441
|
+
reverse (bool, optional): whether to sort in reverse (descending) order
|
|
442
|
+
|
|
443
|
+
Returns:
|
|
444
|
+
dict: sorted copy of [d]
|
|
445
|
+
"""
|
|
446
|
+
return sorted(L, key=lambda d: d[k], reverse=reverse)
|
|
447
|
+
|
|
448
|
+
|
|
409
449
|
def sort_dictionary_by_key(d,reverse=False):
|
|
410
450
|
"""
|
|
411
451
|
Sorts the dictionary [d] by key.
|
|
@@ -611,3 +651,11 @@ if False:
|
|
|
611
651
|
r1 = [0.4,0.8,10,22]; r2 = [100, 101, 200, 210.4]; assert abs(rect_distance(r1,r2)-119.753) < 0.001
|
|
612
652
|
r1 = [0.4,0.8,10,22]; r2 = [101, 101, 200, 210.4]; assert abs(rect_distance(r1,r2)-120.507) < 0.001
|
|
613
653
|
r1 = [0.4,0.8,10,22]; r2 = [120, 120, 200, 210.4]; assert abs(rect_distance(r1,r2)-147.323) < 0.001
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
#%% Test dictionary sorting
|
|
657
|
+
|
|
658
|
+
L = [{'a':5},{'a':0},{'a':10}]
|
|
659
|
+
k = 'a'
|
|
660
|
+
sort_list_of_dicts_by_key(L, k, reverse=True)
|
|
661
|
+
|