postprocessing package
This subpackage contains modules for working with MegaDetector batch processing results.
Subpackages
Submodules
postprocessing.analyze_classification_results module
analyze_classification_results.py
Given a results file in MD format, and a ground truth file in COCO Camera Traps format, both containing classification results, perform various analyses, including:
Precision/recall analysis
Confusion matrix with links to visualization pages
Only analyzes image-level correctness, i.e., box locations are ignored in both the predictions and the ground truth.
- class megadetector.postprocessing.analyze_classification_results.AnalysisResults[source]
Bases:
objectResults returned by analyze_classification_results().
- active_categories
Ordered list of category names corresponding to matrix rows/columns
- confusion_matrix
The confusion matrix as a 2D numpy array
- html_output_file
Path to the output HTML file (if generated)
- per_category_results
Dictionary mapping category names to dicts, where each item has at least the keys “precision”, “recall”, “f1”, “n_ground_truth”, “n_predicted”
- class megadetector.postprocessing.analyze_classification_results.ClassificationAnalysisOptions[source]
Bases:
objectOptions used to parameterize analyze_classification_results().
- apply_detection_category_mapping_when_classifications_are_present
When this is True (default), we trust detection categories regardless of classifications. I.e., a detection category of “person” with a classification of “elk” will be treated as a classification of “person”.
When this is False, we trust classifications, if present. This is generally used when I’m simulating Wildlife Insights ensemble behavior, where “classifications” at this point really represent the output of the entire WI ensemble.
- categories_to_ignore
List of category names to completely exclude from the analysis, whether they appear in ground truth or predictions. Checked after detection category remapping (e.g. person -> human).
- classification_confidence_threshold
Confidence threshold to apply to classification (not detection) results
- detection_category_mapping
A dict mapping detection category names to classification category names, for categories we want to handle specially. Any detection in a matching category with an above-threshold confidence value is treated as if it had a classification with the corresponding (mapped) classification category, with a confidence of 1.0, whether or not that category exists in the ground truth.
For example, by default a detection with category “person” with confidence 0.4 should be treated as a classification of category “human” with confidence 1.0.
Defaults to detection_category_mapping.
- detection_threshold
Ignore all detections below this confidence threshold
If this is None, a confidence threshold is selected based on the detector version.
- gt_category_name_mappings
Before processing, optionally map a subset of GT classification categories to alternative names. Typically used to reconcile category names across predictions/GT.
If not None, should be a str –> str dict.
- gt_file
Ground truth file in COCO Camera Traps format
- html_output_dir
Folder to which we should write html output page
- image_base_dir
Folder where images live; filenames in [results_file] and [gt_file] should be relative to this path. Only required if html_output_dir is not None.
- max_classifications_per_detection
Only review this many classifications per detection
- max_images_per_cell
Try to sample this many images to render per confusion matrix cell. Only relevant if html_output_dir is not None. Total number is still capped by max_total_images.
- max_images_per_html_file
Maximum number of images to include in any HTML page, generally only relevant when calling render_misprediction_pages(…).
- max_total_images
Approximate maximum number of total images to render. May be exceeded slightly if required to make sure that at least one image is rendered per non-empty cell in the confusion matrix. Only relevant if html_output_dir is not None.
- n_mispredictions_for_table
Number of top misprediction categories to show in the per-category statistics table (for both “mispredicted as this” and “this was mispredicted as” columns).
- output_image_width
Width of rendered output images (-1 to preserve original size)
- overwrite
Should we over-write images that already exist?
- predicted_category_name_mappings
Before processing, optionally map a subset of predicted classification categories to alternative names. Typically used to reconcile category names across predictions/GT.
If not None, should be a str –> str dict.
- random_seed
Random seed to be used if image sampling is necessary
- rendering_pool_type
Should we use threads (“threads”) or processes (“processes”) for rendering?
Only relevant if rendering_workers is > 1.
- rendering_workers
Number of workers to use when rendering images
- results_file
MD-formatted results file to analyze
- sequence_level_analysis
If True, the entire analysis will be performed at the sequence level, rather than the image level.
- single_label_per_image
If True, collapse each image’s (or sequence’s) ground truth to a single category. For image-level analyses, ties are broken alphabetically. For sequence-level analyses, ties are broken by count (how many images in the sequence have that category), then alphabetically.
- single_prediction_per_image
If True, collapse each image’s (or sequence’s) predictions to a single category. The winner is chosen by the number of above- threshold classifications for that category, with max classification confidence as a tie-breaker. For sequence-level analyses, collapsing happens at the sequence level (counts are summed across images in the sequence), not per-image.
- megadetector.postprocessing.analyze_classification_results.analyze_classification_results(options)[source]
Perform precision-recall analysis on classification results.
- Parameters:
options (ClassificationAnalysisOptions) – options object defining filenames and analysis parameters.
- Returns:
results of the classification analysis
- Return type:
- megadetector.postprocessing.analyze_classification_results.render_misprediction_pages(options, cells_to_render)[source]
Render detailed HTML pages for specific misprediction cells, typically with a large number of images (e.g. 2000) for deep-dive analysis.
Uses the same data-loading and preparation logic as analyze_classification_results.
- Parameters:
options (ClassificationAnalysisOptions) – options object; needs results_file, gt_file, image_base_dir, html_output_dir. max_images_per_cell controls page length (e.g. set to 2000 for deep dives).
cells_to_render (list) –
list of (true_cat, pred_cat, mode) tuples where mode is one of:
’standard’: entities where true_cat is in GT, pred_cat is in predictions, true_cat != pred_cat, and the off-diagonal skip condition is not met.
’strict_fp’: entities where pred_cat is among the predictions and pred_cat is NOT in the ground truth, and true_cat is in GT. (The “mispredicted as this category” criterion.)
’strict_fn’: entities where true_cat is in GT and true_cat is NOT among the predictions, and pred_cat is in predictions. (The “mispredicted as” criterion.)
- Returns:
paths to the generated HTML files
- Return type:
list
analyze_classification_results - CLI interface
Analyze classification results against ground truth, computing precision/recall/F1 and generating an HTML report.
analyze_classification_results [-h] [--image_base_dir IMAGE_BASE_DIR]
[--html_output_dir HTML_OUTPUT_DIR]
[--detection_threshold DETECTION_THRESHOLD]
[--classification_confidence_threshold CLASSIFICATION_CONFIDENCE_THRESHOLD]
[--max_total_images MAX_TOTAL_IMAGES]
[--max_images_per_cell MAX_IMAGES_PER_CELL]
[--random_seed RANDOM_SEED] [--sequence_level]
[--rendering_workers RENDERING_WORKERS]
[--rendering_pool_type {threads,processes}]
[--output_image_width OUTPUT_IMAGE_WIDTH]
[--n_mispredictions_for_table N_MISPREDICTIONS_FOR_TABLE]
[--categories_to_ignore CATEGORIES_TO_IGNORE]
[--single_prediction_per_image] [--single_label_per_image]
results_file gt_file
analyze_classification_results positional arguments
results_file- MD-formatted results file (.json)gt_file- Ground truth file in COCO Camera Traps format (.json)
analyze_classification_results options
--image_base_dirIMAGE_BASE_DIR- Folder where images live; required if –html_output_dir is specified--html_output_dirHTML_OUTPUT_DIR- Folder for HTML output with confusion matrix and image galleries--detection_thresholdDETECTION_THRESHOLD- Detection confidence threshold (auto-detected if not specified)--classification_confidence_thresholdCLASSIFICATION_CONFIDENCE_THRESHOLD- Classification confidence threshold--max_total_imagesMAX_TOTAL_IMAGES- Maximum total number of images to render--max_images_per_cellMAX_IMAGES_PER_CELL- Maximum number of images per confusion matrix cell--random_seedRANDOM_SEED- Random seed for image sampling--sequence_level- Perform analysis at the sequence level instead of image level--rendering_workersRENDERING_WORKERS- Number of workers for image rendering--rendering_pool_typeRENDERING_POOL_TYPE- Type of worker pool for rendering--output_image_widthOUTPUT_IMAGE_WIDTH- Width of rendered output images (-1 for original size)--n_mispredictions_for_tableN_MISPREDICTIONS_FOR_TABLE- Number of top misprediction categories to show in the per-category table--categories_to_ignoreCATEGORIES_TO_IGNORE- Comma-separated list of category names to exclude from analysis--single_prediction_per_image- Collapse predictions to a single category per image/sequence--single_label_per_image- Collapse ground truth to a single category per image/sequence
postprocessing.categorize_detections_by_size module
categorize_detections_by_size.py
Given a MegaDetector .json file, creates a separate category for bounding boxes above one or more size thresholds.
- class megadetector.postprocessing.categorize_detections_by_size.SizeCategorizationOptions[source]
Bases:
objectOptions used to parameterize categorize_detections_by_size().
- categories_to_separate
List of category numbers to use in separation; uses all categories if None
- default_category_is_smallest
Is the default category above the largest threshold in size_thresholds, or below the smallest? By default we are separating large detections into a new category, so the default is smaller than the smallest threshold
- measurement
Dimension to use for thresholding; can be “size”, “width”, or “height”
- size_category_names
Categories to assign to thresholded ranges; should have the same length as “size_thresholds”.
- size_thresholds
Thresholds to use for separation, as a fraction of the image size.
Will get sorted by categorize_detections_by_size, so the order doesn’t matter, as long as the order matches size_category_names.
- megadetector.postprocessing.categorize_detections_by_size.categorize_detections_by_size(input_file, output_file=None, options=None)[source]
Given a MegaDetector .json file, creates a separate category for bounding boxes above one or more size thresholds, optionally writing results to [output_file].
- Parameters:
input_file (str) – file to process
output_file (str, optional) – optional output file
options (SizeCategorizationOptions, optional) – categorization parameters
- Returns:
data loaded from [input_file], with the new size-based categories. Identical to what’s written to [output_file], if [output_file] is not None.
- Return type:
dict
postprocessing.create_crop_folder module
create_crop_folder.py
Given a MegaDetector .json file and a folder of images, creates a new folder of images representing all above-threshold crops from the original folder.
- class megadetector.postprocessing.create_crop_folder.CreateCropFolderOptions[source]
Bases:
objectOptions used to parameterize create_crop_folder().
- category_names_to_include
Include only these categories, or None to include all
options.category_names_to_include = [‘animal’]
- confidence_threshold
Confidence threshold determining which detections get written
- expansion
Number of pixels to expand each crop
- n_workers
Number of concurrent workers
- overwrite
Whether to overwrite existing images
- pool_type
Whether to use processes (‘process’) or threads (‘thread’) for parallelization
- quality
JPEG quality to use for saving crops (None for default)
- megadetector.postprocessing.create_crop_folder.create_crop_folder(input_file, input_folder, output_folder, output_file=None, crops_output_file=None, options=None)[source]
Given a MegaDetector .json file and a folder of images, creates a new folder of images representing all above-threshold crops from the original folder.
Optionally writes a new .json file that attaches unique IDs to each detection.
- Parameters:
input_file (str) – MD-formatted .json file to process
input_folder (str) – Input image folder
output_folder (str) – Output (cropped) image folder
output_file (str, optional) – new .json file that attaches unique IDs to each detection.
crops_output_file (str, optional) – new .json file that includes whole-image detections for each of the crops, using confidence values from the original results
options (CreateCropFolderOptions, optional) – crop parameters
- megadetector.postprocessing.create_crop_folder.crop_results_to_image_results(image_results_file_with_crop_ids, crop_results_file, output_file, delete_crop_information=True, require_identical_detection_categories=True, restrict_to_top_n=-1, crop_results_prefix=None, detections_without_classification_handling='error')[source]
This function is intended to be run after you have:
Run MegaDetector on a folder
Generated a crop folder using create_crop_folder
Run a species classifier on those crops
This function will take the crop-level results and transform them back to the original images. Classification categories, if available, are taken from [crop_results_file].
- Parameters:
image_results_file_with_crop_ids (str) – results file for the original images, containing crop IDs, likely generated via create_crop_folder. All non-standard fields in this file will be passed along to [output_file].
crop_results_file (str) – results file for the crop folder
output_file (str) – output .json file, containing crop-level classifications mapped back to the image level.
delete_crop_information (bool, optional) – whether to delete the “crop_id” and “crop_filename_relative” fields from each detection, if present.
require_identical_detection_categories (bool, optional) – if True, error if the image-level and crop-level detection categories are different. If False, ignore the crop-level detection categories.
restrict_to_top_n (int, optional) – If >0, removes all but the top N classification results for each detection.
crop_results_prefix (str, optional) – if not None, removes this prefix from crop results filenames. Intended to support the case where the crop results use absolute paths.
detections_without_classification_handling (str, optional) – what to do when we encounter a crop that doesn’t appear in classification results: ‘error’, or ‘include’ (“include” means “leave the detection alone, without classifications”
create_crop_folder - CLI interface
Create a folder of crops from MegaDetector results
create_crop_folder [-h] [--output_file OUTPUT_FILE] [--crops_output_file CROPS_OUTPUT_FILE]
[--confidence_threshold CONFIDENCE_THRESHOLD] [--expansion EXPANSION]
[--quality QUALITY] [--overwrite {true,false}] [--n_workers N_WORKERS]
[--pool_type {thread,process}] [--category_names CATEGORY_NAMES]
input_file input_folder output_folder
create_crop_folder positional arguments
input_file- Path to the MegaDetector .json results fileinput_folder- Path to the folder containing the original imagesoutput_folder- Path to the folder where cropped images will be saved
create_crop_folder options
--output_fileOUTPUT_FILE- Path to save the modified MegaDetector .json file (with crop IDs and filenames)--crops_output_fileCROPS_OUTPUT_FILE- Path to save a new .json file for the crops themselves (with full-image detections for each crop)--confidence_thresholdCONFIDENCE_THRESHOLD- Confidence threshold for detections to be cropped (default: 0.1)--expansionEXPANSION- Number of pixels to expand each crop (default: 0)--qualityQUALITY- JPEG quality for saving crops (default: 95)--overwriteOVERWRITE- Overwrite existing crop images (default:'true')--n_workersN_WORKERS- Number of concurrent workers (default: 8)--pool_typePOOL_TYPE- Type of parallelism to use ('thread'or'process', default:'thread')--category_namesCATEGORY_NAMES- Comma-separated list of category names to include (e.g.,'animal,person'). If None (default), all categories are included.
postprocessing.classification_postprocessing module
classification_postprocessing.py
Functions for postprocessing species classification results, particularly:
Smoothing results within an image (an image with 700 cows and one deer is really just 701 cows)
Smoothing results within a sequence (a sequence that looks like deer/deer/deer/elk/deer/deer is really just a deer)
- class megadetector.postprocessing.classification_postprocessing.ClassificationSmoothingOptions[source]
Bases:
objectOptions used to parameterize smooth_classification_results_image_level() and smooth_classification_results_sequence_level()
- add_pre_smoothing_description
Should we record information about the state of labels prior to smoothing?
- break_at_image
Enable additional debug output for a particular image
- classification_confidence_threshold
We’re not even going to mess around with classifications below this threshold.
We won’t count them, we won’t over-write them, they don’t exist during the within-image smoothing step.
- detection_category_names_to_smooth
Only include these categories in the smoothing process (None to use all categories)
- detection_confidence_threshold
We’re not even going to mess around with detections below this threshold.
We won’t count them, we won’t over-write them, they don’t exist during the within-image smoothing step.
- max_detections_nondominant_class
Even if we have a dominant class, if a non-dominant class has at least this many classifications in an image, leave them alone.
If this is <= 1, we won’t replace non-dominant, non-other classes with the dominant class, even if there are 900 cows and 1 deer.
- max_detections_nondominant_class_same_family
If we have this many classifications of a nondominant category, we won’t do same-family overwrites. <= 1 means “even if there are a million deer, if there are two million moose, call all the deer moose”. This option doesn’t mean anything if min_detections_to_overwrite_secondary_same_family <= 0.
- min_detections_to_overwrite_other
If the dominant class has at least this many classifications, overwrite “other” classifications with the dominant class
- min_detections_to_overwrite_secondary
How many detections do we need in a dominant category to overwrite non-dominant classifications? This is irrelevant if max_detections_nondominant_class <= 1.
- min_detections_to_overwrite_secondary_same_family
How many detections do we need in a dominant category to overwrite non-dominant classifications in the same family? If this is <= 0, we’ll skip this step. This option doesn’t mean anything if max_detections_nondominant_class_same_family <= 1.
- modify_in_place
When a dict (rather than a file) is passed to either smoothing function, if this is True, we’ll make a copy of the input dict before modifying.
- other_category_names
Names to treat as “other” categories; can’t be None, but can be empty
“Other” classifications will be changed to the dominant category, regardless of confidence, as long as there are at least min_detections_to_overwrite_other examples of the dominant class. For example, cow/other will remain unchanged, but cow/cow/other will become cow/cow/cow.
- propagate_classifications_through_taxonomy
If classification descriptions are present and appear to represent taxonomic information, should we propagate classifications when lower-level taxa are more common in an image? For example, if we see “carnivore/fox/fox/deer”, should we make that “fox/fox/fox/deer”?
- taxonomy_propagation_count_weight
When propagating classifications down through taxonomy levels, we have to decide whether we prefer more frequent categories or more specific categories. taxonomy_propagation_level_weight and taxonomy_propagation_count_weight balance levels against counts in this process.
With a very low default value, this just breaks ties.
- taxonomy_propagation_level_weight
When propagating classifications down through taxonomy levels, we have to decide whether we prefer more frequent categories or more specific categories. taxonomy_propagation_level_weight and taxonomy_propagation_count_weight balance levels against counts in this process.
- megadetector.postprocessing.classification_postprocessing.combine_redundant_classification_categories(input_file, output_file=None, classification_threshold=0.5)[source]
If [input_file] contains multiple categories with the same category name, merges each equivalence class into a single category, optionally writing the results to [output_file].
- Parameters:
input_file (str or dict) – .json file to read, in MD format (or an already-loaded dict)
output_file (str) – .json file to write, in MD format
classification_threshold (float, optional) – only used when sorting descriptions by count
- Returns:
remapped MD-formatted dict
- Return type:
dict
- megadetector.postprocessing.classification_postprocessing.count_detections_by_classification_category(detections, options=None)[source]
Count the number of instances of each classification category in the detections list [detections] that have an above-threshold detection. Sort results in descending order by count. Returns a dict mapping category ID –> count. If no detections are above threshold, returns an empty dict.
Only processes the top classification for each detection.
- Parameters:
detections (list of dict) – detections list
options (ClassificationSmoothingOptions, optional) – see ClassificationSmoothingOptions
- Returns:
dict mapping above-threshold category IDs to counts
- megadetector.postprocessing.classification_postprocessing.get_classification_description_string(category_to_count, classification_descriptions)[source]
Return a string summarizing the image content according to [category_to_count].
- Parameters:
category_to_count (dict) – a dict mapping category IDs to counts
classification_descriptions (dict) – a dict mapping category IDs to description strings
- Returns:
a description of this image’s content, e.g. “rabbit (4), human (1)”
- Return type:
string
- megadetector.postprocessing.classification_postprocessing.merge_classification_categories(target_file, source_file, output_file=None)[source]
Modify the classification categories in [source file] to be compatible with the categories in [target_file], optionally writing a new file. Uses only category names, does not use category descriptions to decide whether to merge categories. Behavior is undefined if multiple source categories have the same name. Does not look at detection categories at all. If neither file has classification categories, just re-writes the source file. Errors if exactly one file has classification categories.
- Parameters:
target_file (str or dict) – target .json file, in MD format (or an already-loaded dict)
source_file (str) – .json file to modify, in MD format (or an already-loaded dict)
output_file (str, optional) – .json file to which we should write a modified version of [source_file]
- Returns:
remapped MD-formatted dict
- Return type:
dict
- megadetector.postprocessing.classification_postprocessing.remove_classifications_from_non_animal_detections(input_file, output_file, animal_category_names=None)[source]
Remove classifications from non-animal detections in a MD .json file, optionally writing the results to a new .json file
- Parameters:
input_file (str) – the MD-formatted .json file to process
output_file (str, optional) – the output file to write the modified results
animal_category_names (list, optional) – the detection category names that should be treated as animals (defaults to just ‘animal’).
- Returns:
the modified results
- Return type:
dict
- megadetector.postprocessing.classification_postprocessing.restrict_to_taxa_list(taxa_list, speciesnet_taxonomy_file, input_file, output_file, allow_walk_down=False, add_pre_filtering_description=True, add_post_filtering_description=True, allow_redundant_latin_names=True, protected_common_names=None, use_original_common_names_if_available=True, verbose=True, classification_threshold=None, combine_redundant_categories=True)[source]
Given a prediction file in MD .json format, likely without having had a geofence applied, apply a custom taxa list.
- Parameters:
taxa_list (str) – .csv file with at least the columns “latin” and “common”
speciesnet_taxonomy_file (str) – taxonomy filename, in the same format used for model release (with 7-token taxonomy entries)
input_file (str) – .json file to read, in MD format. This can be None, in which case this function just validates [taxa_list].
output_file (str) – .json file to write, in MD format
allow_walk_down (bool, optional) – should we walk down the taxonomy tree when making mappings if a parent has only a single allowable child? For example, if only a single felid species is allowed, should other felid predictions be mapped to that species, as opposed to being mapped to the family?
add_pre_filtering_description (bool, optional) – should we add a new metadata field that summarizes each image’s classifications prior to taxonomic restriction?
add_post_filtering_description (bool, optional) – should we add a new metadata field that summarizes each image’s classifications after taxonomic restriction?
allow_redundant_latin_names (bool, optional) – if False, we’ll raise an Exception if the same latin name appears twice in the taxonomy list; if True, we’ll just print a warning and ignore all entries other than the first for this latin name
protected_common_names (list, optional) – these categories should be unmodified, even if they aren’t used, or have the same taxonomic description as other categories
use_original_common_names_if_available (bool, optional) – if an “original_common” column is present in [taxa_list], use those common names instead of the ones in the taxonomy file
verbose (bool, optional) – enable additional debug output
classification_threshold (float, optional) – only relevant for the pre/post filtering descriptions
combine_redundant_categories (bool, optional) – whether to combine categories with the same common name
- megadetector.postprocessing.classification_postprocessing.smooth_classification_results_image_level(input_file, output_file=None, options=None)[source]
Smooth classifications at the image level for all results in the MD-formatted results file [input_file], optionally writing a new set of results to [output_file].
This function generally expresses the notion that an image with 700 cows and one deer is really just 701 cows.
Only count detections with a classification confidence threshold above [options.classification_confidence_threshold], which in practice means we’re only looking at one category per detection.
If an image has at least [options.min_detections_to_overwrite_secondary] such detections in the most common category, and no more than [options.max_detections_nondominant_class] in the second-most-common category, flip all detections to the most common category.
Optionally treat some classes as particularly unreliable, typically used to overwrite an “other” class.
This function also removes everything but the non-dominant classification for each detection.
- Parameters:
input_file (str) – MegaDetector-formatted classification results file to smooth. Can also be an already-loaded results dict.
output_file (str, optional) – .json file to write smoothed results
options (ClassificationSmoothingOptions, optional) – see ClassificationSmoothingOptions for details.
- Returns:
MegaDetector-results-formatted dict, identical to what’s written to [output_file] if [output_file] is not None.
- Return type:
dict
- megadetector.postprocessing.classification_postprocessing.smooth_classification_results_sequence_level(input_file, cct_sequence_information, output_file=None, options=None)[source]
Smooth classifications at the sequence level for all results in the MD-formatted results file [md_results_file], optionally writing a new set of results to [output_file].
This function generally expresses the notion that a sequence that looks like deer/deer/deer/elk/deer/deer/deer/deer is really just a deer.
- Parameters:
input_file (str or dict) – MegaDetector-formatted classification results file to smooth (or already-loaded results). If you supply a dict, it’s copied by default, but in-place modification is supported via options.modify_in_place.
cct_sequence_information (str, dict, or list) – COCO Camera Traps file containing sequence IDs for each image (or an already-loaded CCT-formatted dict, or just the ‘images’ list from a CCT dict).
output_file (str, optional) – .json file to write smoothed results
options (ClassificationSmoothingOptions, optional) – see ClassificationSmoothingOptions for details.
- Returns:
MegaDetector-results-formatted dict, identical to what’s written to [output_file] if [output_file] is not None.
- Return type:
dict
postprocessing.combine_batch_outputs module
combine_batch_outputs.py
Merges two or more .json files in MD output format, optionally writing the results to another .json file.
Concatenates image lists, erroring if images are not unique.
Errors if class lists are conflicting; errors on unrecognized fields.
Checks compatibility in info structs, within reason.
File format:
Command-line use:
combine_batch_outputs input1.json input2.json … inputN.json output.json
This does no checking for redundancy; if you are looking to ensemble the results of multiple model versions, see merge_detections.py.
- megadetector.postprocessing.combine_batch_outputs.combine_batch_output_dictionaries(input_dicts, require_uniqueness=True)[source]
Merges the list of MD results dictionaries [input_dicts] into a single dict. See module header comment for details on merge rules.
- Parameters:
input_dicts (list of dicts) – list of dicts in which each dict represents the contents of a MD output file
require_uniqueness (bool, optional) – whether to require that the images in each input dict be unique; if this is True and image filenames are not unique, an error is raised.
- Returns:
merged MD results
- Return type:
dict
- megadetector.postprocessing.combine_batch_outputs.combine_batch_output_files(input_files, output_file=None, require_uniqueness=True, verbose=True)[source]
Merges the list of MD results files [input_files] into a single dictionary, optionally writing the result to [output_file].
Always overwrites [output_file] if it exists.
- Parameters:
input_files (list of str) – paths to JSON detection files
output_file (str, optional) – path to write merged JSON
require_uniqueness (bool, optional) – whether to require that the images in each list of images be unique
verbose (bool, optional) – enable additional debug output
- Returns:
merged dictionaries loaded from [input_files], identical to what’s written to [output_file] if [output_file] is not None
- Return type:
dict
combine_batch_outputs - CLI interface
combine_batch_outputs [-h] input_paths [input_paths ...] output_path
combine_batch_outputs positional arguments
input_paths- List of input .json filesoutput_path- Output .json file
combine_batch_outputs options
postprocessing.compare_batch_results module
compare_batch_results.py
Compare sets of batch results; typically used to compare:
Results from different MegaDetector versions
Results before/after RDE
Results with/without augmentation
Makes pairwise comparisons between sets of results, but can take lists of results files (will perform all pairwise comparisons). Results are written to an HTML page that shows the number and nature of disagreements (in the sense of each image being a detection or non-detection), with sample images for each category.
Operates in one of three modes, depending on whether ground truth labels/boxes are available:
The most common mode assumes no ground truth, just finds agreement/disagreement between results files, or class discrepancies.
If image-level ground truth is available, finds image-level agreements on TPs/TNs/FPs/FNs, but also finds image-level TPs/TNs/FPs/FNs that are unique to each set of results (at the specified confidence threshold).
If box-level ground truth is available, finds box-level agreements on TPs/TNs/FPs/FNs, but also finds image-level TPs/TNs/FPs/FNs that are unique to each set of results (at the specified confidence threshold).
- class megadetector.postprocessing.compare_batch_results.BatchComparisonOptions[source]
Bases:
objectDefines the options for a set of (possibly many) pairwise comparisons.
- category_names_to_include
List of category names to include in the comparison, or None to use all categories
- class_agnostic_comparison
Compare only detections/non-detections, ignore categories (still renders categories)
- colormap_a
Colormap to use for detections in file A (maps detection categories to colors)
- colormap_b
Colormap to use for detections in file B (maps detection categories to colors)
- error_on_non_matching_lists
The expectation is that all results sets being compared will refer to the same images; if this is True (default), we’ll error if that’s not the case, otherwise non-matching lists will just be a warning.
- filenames_to_include
List of filenames to include in the comparison, or None to use all files
- fn_to_display_fn
When rendering to the output table, optionally write alternative strings to describe images
- ground_truth_file
Ground truth .json file in COCO Camera Traps format, or an already-loaded COCO dictionary
- gt_empty_categories
Category names that refer to empty images when image-level ground truth is provided
- gt_iou_threshold
IoU threshold to use when comparing to ground truth with boxes
- image_folder
Base folder for images (which are specified as relative files)
- include_clean_categories
Separate out the “clean TP” and “clean TN” categories, only relevant when GT is available
- include_toc
Should we include a TOC? TOC is always omitted if <=2 comparisons are performed.
- job_name
Job name to use in the HTML output file
- max_images_per_category
Maximum number of images to render for each category, where a “category” here is “detections_a_only”, “detections_b_only”, etc., or None to render all images.
- max_images_per_page
Maximum number of images per HTML page (paginates if a category page goes beyond this), or None to disable pagination.
- n_rendering_workers
Number of workers to use for rendering, or <=1 to disable parallelization
- output_folder
Folder to which we should write HTML output
- pairwise_options
List of PairwiseBatchComparisonOptions that defines the comparisons we’ll render
- parallelize_rendering_with_threads
Whether to render images with threads (True) or processes (False)
- parse_link_paths
Should we run urllib.parse.quote() on paths before using them as links in the output page?
- random_seed
Random seed for image sampling (not used if max_images_per_category is None)
- required_token
Only process images whose file names contain this token
This can also be a pointer to a function that takes a string (filename) and returns a bool (if the function returns True, the image will be included in the comparison).
- return_images_by_category
Should we return the mapping from categories (e.g. “common detections”) to image pairs? Makes the return dict much larger, but allows post-hoc exploration.
- show_category_names_on_detected_boxes
Should we show category names (instead of numbers) on detected boxes?
- show_category_names_on_gt_boxes
Should we show category names (instead of numbers) on GT boxes?
- show_classification_categories
Should we show classification categories if present?
- show_labels_for_image_level_gt
Should we show image-level labels as text on each image when boxes are not available?
- sort_by_confidence
Whether to sort results by confidence; if this is False, sorts by filename
- target_width
Width of images to render in the output HTML (None to use original size)
- verbose
Enable additional debug output
- class megadetector.postprocessing.compare_batch_results.BatchComparisonResults[source]
Bases:
objectThe results from a set of pairwise comparisons
- html_output_file
Filename containing HTML output
- pairwise_results
A list of PairwiseBatchComparisonResults
- class megadetector.postprocessing.compare_batch_results.PairwiseBatchComparisonOptions[source]
Bases:
objectDefines the options used for a single pairwise comparison; a list of these pairwise options sets is stored in the BatchComparisonsOptions class.
- classification_confidence_threshold_a
Classification threshold to use for filename A, only relevant if classifications are present
- classification_confidence_threshold_b
Classification threshold to use for filename B, only relevant if classifications are present
- detection_thresholds_a
Per-class detection thresholds to use for filename A (including a ‘default’ threshold)
- detection_thresholds_b
Per-class detection thresholds to use for filename B (including a ‘default’ threshold)
- rendering_confidence_threshold_a
Rendering threshold to use for all categories for filename A
- rendering_confidence_threshold_b
Rendering threshold to use for all categories for filename B
- results_description_a
Description to use in the output HTML for filename A
- results_description_b
Description to use in the output HTML for filename B
- results_filename_a
First filename to compare
- results_filename_b
Second filename to compare
- class megadetector.postprocessing.compare_batch_results.PairwiseBatchComparisonResults[source]
Bases:
objectThe results from a single pairwise comparison.
- categories_to_image_pairs
Values are dicts with fields ‘im_a’, ‘im_b’, ‘sort_conf’, and ‘im_gt’
- comparison_friendly_name
Friendly identifier for this comparison
- comparison_short_name
Short identifier for this comparison
- html_content
String of HTML content suitable for rendering to an HTML file
- pairwise_options
Possibly-modified version of the PairwiseBatchComparisonOptions supplied as input
- megadetector.postprocessing.compare_batch_results.compare_batch_results(options)[source]
The main entry point for this module. Runs one or more batch results comparisons, writing results to an html page. Most of the work is deferred to _pairwise_compare_batch_results().
- Parameters:
options (BatchComparisonOptions) – job options to use for this comparison task, including the list of specific pairswise comparisons to make (in the pairwise_options field)
- Returns:
the results of this comparison task
- Return type:
- megadetector.postprocessing.compare_batch_results.find_equivalent_threshold(results_a, results_b, threshold_a=0.2, category_names=None, verbose=False)[source]
Given two sets of detector results, finds the confidence threshold for results_b that produces the same fraction of images with detections as threshold_a does for results_a. Uses all categories.
- Parameters:
results_a (str or dict) – the first set of results, either a .json filename or a results dict
results_b (str or dict) – the second set of results, either a .json filename or a results dict
threshold_a (float, optional) – the threshold used to determine the target number of detections in results_a
category_names (list or str, optional) – the list of category names to consider (defaults to using all categories), or the name of a single category.
verbose (bool, optional) – enable additional debug output
- Returns:
the threshold that - when applied to results_b - produces the same number of image-level detections that results from applying threshold_a to results_a
- Return type:
float
- megadetector.postprocessing.compare_batch_results.find_image_level_detections_above_threshold(results, threshold=0.2, category_names=None)[source]
Returns images in the set of MD results [results] with detections above a threshold confidence level, optionally only counting certain categories.
- Parameters:
results (str or dict) – the set of results, either a .json filename or a results dict
threshold (float, optional) – the threshold used to determine the target number of detections in [results]
category_names (list or str, optional) – the list of category names to consider (defaults to using all categories), or the name of a single category.
- Returns:
the images with above-threshold detections
- Return type:
list
- megadetector.postprocessing.compare_batch_results.n_way_comparison(filenames, options, detection_thresholds=None, rendering_thresholds=None, model_names=None)[source]
Performs N pairwise comparisons for the list of results files in [filenames], by generating sets of pairwise options and calling compare_batch_results.
- Parameters:
filenames (list) – list of MD results filenames to compare
options (BatchComparisonOptions) – task options set in which pairwise_options is still empty; that will get populated from [filenames]
detection_thresholds (list, optional) – list of detection thresholds with the same length as [filenames], or None to use sensible defaults
rendering_thresholds (list, optional) – list of rendering thresholds with the same length as [filenames], or None to use sensible defaults
model_names (list, optional) – list of model names to use the output HTML file, with the same length as [filenames], or None to use sensible defaults
- Returns:
the results of this comparison task
- Return type:
compare_batch_results - CLI interface
compare_batch_results [-h] [--detection_thresholds [DETECTION_THRESHOLDS ...]]
[--rendering_thresholds [RENDERING_THRESHOLDS ...]]
[--max_images_per_category MAX_IMAGES_PER_CATEGORY]
[--target_width TARGET_WIDTH] [--use_processes] [--open_results]
[--n_rendering_workers N_RENDERING_WORKERS]
output_folder image_folder [results_files ...]
compare_batch_results positional arguments
output_folder- folder to which to write html resultsimage_folder- image source folderresults_files- list of .json files to be compared
compare_batch_results options
--detection_thresholdsDETECTION_THRESHOLDS- list of detection thresholds, same length as the number of .json files, defaults to 0.15 for all files--rendering_thresholdsRENDERING_THRESHOLDS- list of rendering thresholds, same length as the number of .json files, defaults to 0.10 for all files--max_images_per_categoryMAX_IMAGES_PER_CATEGORY- number of images to sample for each agreement category (common detections, etc.)--target_widthTARGET_WIDTH- output image width, defaults to 800--use_processes- use processes rather than threads for parallelization--open_results- open the output html file when done--n_rendering_workersN_RENDERING_WORKERS- number of workers for parallel rendering, defaults to 10
Example:
python compare_batch_results.py output_folder image_folder mdv5a.json mdv5b.json mdv4.json --detection_thresholds 0.15 0.15 0.7
postprocessing.validate_batch_results module
validate_batch_results.py
Given a .json file containing MD results, validate that it’s compliant with the format spec:
https://lila.science/megadetector-output-format
- class megadetector.postprocessing.validate_batch_results.ValidateBatchResultsOptions[source]
Bases:
objectOptions controlling the behavior of validate_batch_results()
- check_image_existence
Should we verify that images exist? If this is True, and the .json file contains relative paths, relative_path_base needs to be specified.
- raise_errors
Should we raise errors immediately (vs. just catching and reporting)?
- relative_path_base
If check_image_existence is True, where do the images live?
If None, assumes absolute paths.
- return_data
Should we return the loaded data, or just the validation results?
- verbose
Enable additional debug output
- megadetector.postprocessing.validate_batch_results.validate_batch_results(json_filename, options=None)[source]
Verify that [json_filename] is a valid MD output file. Currently errors on invalid files.
- Parameters:
json_filename (str or dict) – the filename to validate, or an already loaded results dict
options (ValidateBatchResultsOptions, optional) – all the parameters used to control this process, see ValidateBatchResultsOptions for details
- Returns:
a dict with a field called “validation_results”, which is itself a dict. The reason it’s a dict inside a dict is that if return_data is True, the outer dict also contains all the loaded data. The “validation_results” dict contains fields called “errors”, “warnings”, and “filename”. “errors” and “warnings” are lists of strings, although “errors” will never be longer than N=1, since validation fails at the first error.
- Return type:
dict
validate_batch_results - CLI interface
validate_batch_results [-h] [--check_image_existence]
[--relative_path_base RELATIVE_PATH_BASE]
json_filename
validate_batch_results positional arguments
json_filename- path to .json file containing MegaDetector results
validate_batch_results options
--check_image_existence- check that all images referred to in the results file exist--relative_path_baseRELATIVE_PATH_BASE- if –check_image_existence is specified and paths are relative, use this as the base folder
postprocessing.detector_calibration module
detector_calibration.py
Tools for comparing/calibrating confidence values from detectors, particularly different versions of MegaDetector.
- class megadetector.postprocessing.detector_calibration.CalibrationMatchColumns(value)[source]
Bases:
IntEnumEnumeration defining columns in the calibration_matches list we’ll assemble below.
- COLUMN_CATEGORY_ID = 4
- COLUMN_CONF_A = 0
- COLUMN_CONF_B = 1
- COLUMN_IOU = 2
- COLUMN_I_IMAGE = 3
- COLUMN_MATCHES_GT = 5
- class megadetector.postprocessing.detector_calibration.CalibrationOptions[source]
Bases:
objectOptions controlling comparison/calibration behavior.
- categories_to_plot
List of category IDs to use for plotting comparisons, or None to plot all categories.
- category_id_to_name
Optionally map category ID to name in plot labels
- confidence_threshold
Minimum confidence threshold to consider for calibration (should be lower than the lowest value you would use in realistic situations)
- iou_threshold
IoU threshold used for determining whether two detections are the same
When multiple detections match, we will only use the highest-matching IoU.
- max_samples_per_category
Maximum number of samples to use for plotting or calibration per category, or None to use all paired values. If separate_plots_by_category is False, this is the overall number of points sampled.
- model_name_a
Model name to use in printouts and plots for result set A
- model_name_b
Model name to use in printouts and plots for result set B
- return_data
Should we populate the data_a and data_b fields in the return value?
- separate_plots_by_category
Should we make separate plots for each category? Mutually exclusive with separate_plots_by_correctness.
- separate_plots_by_correctness
Should we make separate plots for TPs/FPs? Mutually exclusive with separate_plots_by_category.
- verbose
Enable additional debug output
- class megadetector.postprocessing.detector_calibration.CalibrationResults[source]
Bases:
objectResults of a model-to-model comparison.
- calibration_matches
[conf_a, conf_b, iou, i_image, category_id, matches_gt]
If ground truth is supplied, [matches_gt] is a bool indicating whether either of the detected boxes matches a ground truth box of the same category. If ground truth is not supplied, [matches_gt] is None.
- Type:
List of tuples
- data_a
Populated with the data loaded from json_filename_a if options.return_data is True
- data_b
Populated with the data loaded from json_filename_b if options.return_data is True
- megadetector.postprocessing.detector_calibration.compare_model_confidence_values(json_filename_a, json_filename_b, json_filename_gt=None, options=None)[source]
Compare confidence values across two .json results files. Compares only detections that can be matched by IoU, i.e., does not do anything with detections that only appear in one file.
- Parameters:
json_filename_a (str or dict) – filename containing results from the first model to be compared; should refer to the same images as [json_filename_b]. Can also be a loaded results dict.
json_filename_b (str or dict) – filename containing results from the second model to be compared; should refer to the same images as [json_filename_a]. Can also be a loaded results dict.
json_filename_gt (str or dict, optional) – filename containing ground truth; should refer to the same images as [json_filename_a] and [json_filename_b]. Can also be a loaded results dict. Should be in COCO format.
options (CalibrationOptions, optional) – all the parameters used to control this process, see CalibrationOptions for details
- Returns:
description of the comparison results
- Return type:
- megadetector.postprocessing.detector_calibration.plot_matched_confidence_values(calibration_results, output_filename, options=None)[source]
Given a set of paired confidence values for matching detections (from compare_model_confidence_values), plot histograms of those pairs for each detection category.
- Parameters:
calibration_results (CalibrationResults) – output from a call to compare_model_confidence_values, containing paired confidence values for two sets of detection results.
output_filename (str) – filename to write the plot (.png or .jpg)
options (CalibrationOptions, optional) – plotting options, see CalibrationOptions for details.
postprocessing.convert_output_format module
convert_output_format.py
Converts between file .json and .csv representations of MD output. The .csv format is largely obsolete, don’t use it unless you’re super-duper sure you need it.
- megadetector.postprocessing.convert_output_format.convert_csv_to_json(input_path, output_path=None, overwrite=True)[source]
Convert .csv to .json. If output_path is None, will convert x.csv to x.json. This supports a largely obsolete .csv format, there’s almost no reason you want to do this.
- Parameters:
input_path (str) – .csv filename to convert to .json
output_path (str, optional) – the output .json file to generate; if this is None, uses [input_path].json
overwrite (bool, optional) – whether to overwrite an existing .json file; if this is False and the output file exists, no-ops and returns
- megadetector.postprocessing.convert_output_format.convert_json_to_csv(input_path, output_path=None, min_confidence=None, omit_bounding_boxes=False, output_encoding=None, overwrite=True, verbose=False)[source]
Converts a MD results .json file to a totally non-standard .csv format.
If [output_path] is None, will convert x.json to x.csv.
- Parameters:
input_path (str) – the input .json file to convert
output_path (str, optional) – the output .csv file to generate; if this is None, uses [input_path].csv
min_confidence (float, optional) – the minimum-confidence detection we should include in the “detections” column; has no impact on the other columns
omit_bounding_boxes (bool, optional) – whether to leave out the json-formatted bounding boxes that make up the “detections” column, which are not generally useful for someone who wants to consume this data as a .csv file
output_encoding (str, optional) – encoding to use for the .csv file
overwrite (bool, optional) – whether to overwrite an existing .csv file; if this is False and the output file exists, no-ops and returns
verbose (bool, optional) – enable additional debug output
convert_output_format - CLI interface
convert_output_format [-h] [--output_path OUTPUT_PATH] [--omit_bounding_boxes] input_path
convert_output_format positional arguments
input_path- Input filename ending in .json or .csv
convert_output_format options
--output_pathOUTPUT_PATH- Output filename ending in .json or .csv (defaults to input file, with .json/.csv replaced by .csv/.json)--omit_bounding_boxes- Omit bounding box text from .csv output (large and usually not useful)
postprocessing.md_to_coco module
md_to_coco.py
“Converts” MegaDetector output files to COCO format. “Converts” is in quotes because this is an opinionated transformation that requires a confidence threshold for most applications.
Does not currently handle classification information.
- megadetector.postprocessing.md_to_coco.md_to_coco(md_results_file, coco_output_file=None, image_folder=None, confidence_threshold=0.15, validate_image_sizes=False, info=None, preserve_nonstandard_metadata=True, include_failed_images=True, include_annotations_without_bounding_boxes=True, empty_category_id='0', overwrite_behavior='skip', verbose=True, image_filename_to_size=None, unrecognized_category_handling='error', precision=3)[source]
“Converts” MegaDetector output files to COCO format. “Converts” is in quotes because this is an opinionated transformation that typically requires a confidence threshold.
The default confidence threshold is not 0; the assumption is that by default, you are going to treat the resulting COCO file as a set of labels. If you are using the resulting COCO file to evaluate a detector, rather than as a set of labels, you likely want a confidence threshold of 0. Confidence values will be written to the semi-standard “score” field for each image (regardless of the threshold) if preserve_nonstandard_metadata is True.
A folder of images is required if width and height information are not available in the MD results file.
- Parameters:
md_results_file (str) – MD results .json file to convert to COCO format
coco_output_file (str, optional) – COCO .json file to write; if this is None, we’ll return a COCO-formatted dict, but won’t write it to disk. If this is ‘auto’, we’ll write to [md_results_file_without_extension].coco.json.
image_folder (str, optional) – folder of images, required if ‘width’ and ‘height’ are not present in the MD results file (they are not required by the format)
confidence_threshold (float, optional) – boxes below this confidence threshold will not be included in the output data
validate_image_sizes (bool, optional) – if this is True, we’ll check the image sizes regardless of whether “width” and “height” are present in the MD results file.
info (dict, optional) – arbitrary metadata to include in an “info” field in the COCO-formatted output
preserve_nonstandard_metadata (bool, optional) – if this is True, confidence will be preserved in a non-standard “score” field in each annotation, and any random fields present in each image’s data (e.g. EXIF metadata) will be propagated to COCO output
include_failed_images (bool, optional) – if this is True, failed images will be propagated to COCO output with a non-empty “failure” field and no other fields, otherwise failed images will be skipped.
include_annotations_without_bounding_boxes (bool, optional) – the only time we end up with annotations without bounding boxes is when a detection has the category [empty_category_id]; this determines whether those annotations are included in the output.
empty_category_id (str, optional) – category ID reserved for the ‘empty’ class, should not be attached to any bounding boxes
overwrite_behavior (str, optional) – determines behavior if the output file exists (‘skip’ to skip conversion, ‘overwrite’ to overwrite the existing file, ‘error’ to raise an error, ‘skip_if_valid’ to skip conversion if the .json file appears to be intact (does not verify COCO formatting, just intact-.json-ness))
verbose (bool, optional) – enable debug output, including the progress bar,
image_filename_to_size (dict, optional) – dictionary mapping relative image paths to (w,h) tuples. Reading image sizes is the slowest step, so if you need to convert many results files at once for the same set of images, things will be gobs faster if you read the image sizes in advance and pass them in via this argument. The format used here is the same format output by parallel_get_image_sizes().
unrecognized_category_handling (str or float, optional) – specifies what to do when encountering category IDs not in the category mapping. Can be “error”, “ignore”, or “warning”. Can also be a float, in which case an error is thrown if an unrecognized category has a confidence value higher than this value.
precision (int, optional) – round box coordinates to this many decimal places, or None to bypass rounding.
- Returns:
the COCO data dict, identical to what’s written to [coco_output_file] if [coco_output_file] is not None.
- Return type:
dict
md_to_coco - CLI interface
“Convert” MD output to COCO format, in quotes because this is an opinionated transformation that requires a confidence threshold
md_to_coco [-h] [--image_folder IMAGE_FOLDER] [--preserve_nonstandard_metadata]
[--include_failed_images]
md_results_file coco_output_file confidence_threshold
md_to_coco positional arguments
md_results_file- Path to MD results file (.json)coco_output_file- Output filename (.json)confidence_threshold- Confidence threshold (default 0.15)
md_to_coco options
--image_folderIMAGE_FOLDER- Image folder, only required if we will need to access image sizes--preserve_nonstandard_metadata- Preserve metadata that isn’t normally included in COCO-formatted data (e.g. EXIF metadata, confidence values)--include_failed_images- Keep a record of corrupted images in the output; may not be completely COCO-compliant
postprocessing.md_to_labelme module
md_to_labelme.py
“Converts” a MegaDetector output .json file to labelme format (one .json per image file). “Convert” is in quotes because this is an opinionated transformation that requires a confidence threshold.
TODO: # noqa
support variable confidence thresholds across classes
support classification data
- megadetector.postprocessing.md_to_labelme.get_labelme_dict_for_image(im, image_base_name=None, category_id_to_name=None, info=None, confidence_threshold=None)[source]
For the given image struct in MD results format, reformat the detections into labelme format.
- Parameters:
im (dict) – MegaDetector-formatted results dict, must include ‘height’ and ‘width’ fields
image_base_name (str, optional) – written directly to the ‘imagePath’ field in the output; defaults to os.path.basename(im[‘file’]).
category_id_to_name (dict, optional) – maps string-int category IDs to category names, defaults to the standard MD categories
info (dict, optional) – arbitrary metadata to write to the “detector_info” field in the output dict
confidence_threshold (float, optional) – only detections at or above this confidence threshold will be included in the output dict
- Returns:
labelme-formatted dictionary, suitable for writing directly to a labelme-formatted .json file
- Return type:
dict
- megadetector.postprocessing.md_to_labelme.md_to_labelme(results_file, image_base, confidence_threshold=None, overwrite=False, extension_prefix='', n_workers=1, use_threads=False, bypass_image_size_read=False, verbose=False)[source]
For all the images in [results_file], write a .json file in labelme format alongside the corresponding relative path within image_base.
- Parameters:
results_file (str) – MD results .json file to convert to Labelme format
image_base (str) – folder of images; filenames in [results_file] should be relative to this folder
confidence_threshold (float, optional) – only detections at or above this confidence threshold will be included in the output dict. If None, no threshold will be applied.
overwrite (bool, optional) – whether to overwrite existing output files; if this is False and the output file for an image exists, we’ll skip that image
extension_prefix (str, optional) – if non-empty, “extension_prefix” will be inserted before the .json extension (typically used to generate multiple copies of labelme files representing different MD thresholds)
n_workers (int, optional) – enables multiprocessing if > 1
use_threads (bool, optional) – if [n_workers] > 1, determines whether we parallelize via threads (True) or processes (False)
bypass_image_size_read (bool, optional) – if True, skips reading image sizes and trusts whatever is in the MD results file (don’t set this to “True” if your MD results file doesn’t contain image sizes)
verbose (bool, optional) – enables additionald ebug output
md_to_labelme - CLI interface
Convert MD output to labelme annotation format
md_to_labelme [-h] [--confidence_threshold CONFIDENCE_THRESHOLD] [--overwrite]
results_file image_base
md_to_labelme positional arguments
results_file- Path to MD results file (.json)image_base- Path to images (also the output folder)
md_to_labelme options
--confidence_thresholdCONFIDENCE_THRESHOLD- Confidence threshold (default 0.15)--overwrite- Overwrite existing labelme .json files
postprocessing.md_to_wi module
md_to_wi.py
Converts the MD .json format to the WI predictions.json format.
md_to_wi - CLI interface
md_to_wi [-h] [--base_folder BASE_FOLDER] md_results_file predictions_json_file
md_to_wi positional arguments
md_results_file- output file in MD format to convertpredictions_json_file- .json file to write in predictions.json format
md_to_wi options
--base_folderBASE_FOLDER- folder name to prepend to each path in md_results_file, to convert relative paths to absolute paths.
postprocessing.merge_detections module
merge_detections.py
Merge high-confidence detections from one or more results files into another file. Typically used to combine results from MDv5b and/or MDv4 and/or MDv5a into a “primary” results file from MDv5a or MDv1000-redwood.
Detection categories must be the same in both files; if you want to first remap one file’s category mapping to be the same as another’s, see remap_detection_categories.
If you want to literally merge two .json files, see combine_batch_outputs.py.
- class megadetector.postprocessing.merge_detections.MergeDetectionsOptions[source]
Bases:
objectClass defining options for merge_detections().
- categories_to_exclude
If you want to merge only certain categories, specify one (but not both) of these. These are category IDs, not names.
- categories_to_include
If you want to merge only certain categories, specify one (but not both) of these. These are category IDs, not names.
- iou_threshold
IoU threshold above which two detections are considered the same
- mark_copied_detections
Add a ‘merged’ field (value True) to all merged detections.
Only used for debugging.
- max_detection_size
Maximum detection size to include in the merged output
- merge_empty_only
Only merge detections into images that have no above-threshold detections in the target results file.
- min_detection_size
Minimum detection size to include in the merged output
- overwrite
Error if this is False and the output file exists
- source_confidence_thresholds
Exclude detections whose confidence in the source file(s) is less than this. Should have the same length as the number of source files.
- target_confidence_threshold
Don’t bother merging into target images if there is a similar detection above this threshold (or if there is any detection above this threshold, and merge_empty_only is True)
- megadetector.postprocessing.merge_detections.merge_detections(source_files, target_file, output_file=None, options=None)[source]
Merge high-confidence detections from one or more results files into another file. Typically used to combine results from, e.g., MDv5a and/or MDv5b into a “primary” results file from MDv1000-redwood.
[source_files] (a list of files or a single filename) specifies the set of results files that will be merged into [target_file]. The difference between a “source file” and the “target file” is that if no merging is necessary, either because two boxes are nearly identical or because merge_only_empty is True and the target file already has above-threshold detection for an image+category, the output file gets the results of the “target” file. I.e., the “target” file wins all ties.
Merges classification categories based on category names (ignoring descriptions).
The results are written to [output_file].
- Parameters:
source_files (list of str) – list of files to merge into the results in [target_file]
target_file (str) – filename that is treated as the primary source of results
output_file (str, optional) – file to which we should write merged results
options (MergeDetectionsOptions, optional) – see MergeDetectionsOptions
- Returns:
dict in MegaDetector format, containing merged results
merge_detections - CLI interface
Merge detections from one or more MegaDetector results files into an existing results file
merge_detections [-h] [--max_detection_size MAX_DETECTION_SIZE]
[--min_detection_size MIN_DETECTION_SIZE]
[--source_confidence_thresholds SOURCE_CONFIDENCE_THRESHOLDS [SOURCE_CONFIDENCE_THRESHOLDS ...]]
[--target_confidence_threshold TARGET_CONFIDENCE_THRESHOLD]
[--categories_to_include CATEGORIES_TO_INCLUDE [CATEGORIES_TO_INCLUDE ...]]
[--categories_to_exclude CATEGORIES_TO_EXCLUDE [CATEGORIES_TO_EXCLUDE ...]]
[--merge_empty_only] [--iou_threshold IOU_THRESHOLD]
source_files [source_files ...] target_file output_file
merge_detections positional arguments
source_files- Path to source .json file(s) to merge fromtarget_file- Path to a .json file to merge detections intooutput_file- Path to output .json results file
merge_detections options
--max_detection_sizeMAX_DETECTION_SIZE- Ignore detections with an area larger than this (as a fraction of image size) (default 1.01)--min_detection_sizeMIN_DETECTION_SIZE- Ignore detections with an area smaller than this (as a fraction of image size) (default 0)--source_confidence_thresholdsSOURCE_CONFIDENCE_THRESHOLDS- List of thresholds for each source file (default [0.05]). Merge only if the source file’s detection confidence is higher than its corresponding threshold. Should be the same length as the number of source files.--target_confidence_thresholdTARGET_CONFIDENCE_THRESHOLD- Do not merge if target file detection confidence is already higher than this (default 0.2)--categories_to_includeCATEGORIES_TO_INCLUDE- List of numeric detection category IDs to include--categories_to_excludeCATEGORIES_TO_EXCLUDE- List of numeric detection categories to exclude--merge_empty_only- Ignore individual detections and only merge images for which the target file contains no detections--iou_thresholdIOU_THRESHOLD- Sets the minimum IoU for a source detection to be considered the same as a target detection (default 0.65)
postprocessing.postprocess_batch_results module
postprocess_batch_results.py
Given a .json or .csv file containing MD results, do one or more of the following:
Sample detections/non-detections and render to HTML (when ground truth isn’t available) (this is 99.9% of what this module is for)
Evaluate detector precision/recall, optionally rendering results (requires ground truth)
Sample true/false positives/negatives and render to HTML (requires ground truth)
Ground truth, if available, must be in COCO Camera Traps format:
- class megadetector.postprocessing.postprocess_batch_results.PostProcessingOptions[source]
Bases:
objectOptions used to parameterize process_batch_results().
- additional_image_fields_to_display
Additional image fields to display in image headers. If this is a list, we’ll include those fields; if this is a dict, we’ll use that dict to choose alternative display names for each field.
- almost_detection_confidence_threshold
Only a float is supported here (unlike the “confidence_threshold” parameter, which can be a dict).
- api_detection_results
Allow bypassing API output loading when operating on previously-loaded results. If present, this is a Pandas DataFrame. Almost never useful.
- api_other_fields
Allow bypassing API output loading when operating on previously-loaded results. If present, this is a str –> obj dict. Almost never useful.
- api_output_filename_replacements
Optionally replace one or more strings in filenames with other strings; useful for taking a set of results generated for one folder structure and applying them to a slightly different folder structure.
- box_expansion
Box expansion (in pixels) for rendering detections
- category_name_to_sort_weight
When classification results are present, use this dictionary to push some categories to the bottom of the list. Larger numbers == later groups. Default sort weight is zero. Line breaks will separate equal sort weights. Sort weights must be integers.
In practice this is used to push generic categories like “blank”, “animal”, and “unreliable” to the bottom of the list, like:
- options.category_name_to_sort_weight =
{‘animal’:1,’blank’:1,’unknown’:1,’unreliable’:1,’mammal’:1,’no cv result’:1}
- classification_confidence_threshold
Confidence threshold to apply to classification (not detection) results
Only a float is supported here (unlike the “confidence_threshold” parameter, which can be a dict).
- confidence_threshold
If this is None, a confidence threshold is selected based on the detector version.
This can either be a float or a dictionary mapping category names (not IDs) to thresholds. The category “default” can be used to specify thresholds for other categories. Currently the use of a dict here is not supported when ground truth is supplied.
- ground_truth_filename_replacements
Optionally replace one or more strings in filenames with other strings; useful for taking a set of results generated for one folder structure and applying them to a slightly different folder structure.
- ground_truth_json_file
Optional .json file containing ground truth information
- html_sort_order
Sort order for the output, should be one of “filename”, “confidence”, or “random”
- image_base_dir
Folder where images live (filenames in [md_results_file] should be relative to this folder)
Can be ‘’ if [md_results_file] uses absolute paths.
- include_almost_detections
Should we also split out a separate report about the detections that were just below our main confidence threshold?
Currently only supported when ground truth is unavailable.
- include_category_descriptions_with_global_counts
The category/count summary typically only includes category names, this flag includes descriptions (typically taxonomic strings) as well.
- include_classification_category_report
If classification results are present, should we include a summary of classification categories?
- include_size_range
Display the min/max normalized size of above-threshold detections for each image
- job_name_string
Job name to include in big letters in the output HTML
- line_thickness
Line width (in pixels) for rendering detections
- link_images_to_originals
If True, images in the output HTML will be links back to the original images
- max_figures_per_html_file
Should we split individual pages up into smaller pages if there are more than N images?
- md_results_file
MD results .json file to process
- model_version_string
Model version string to include in the output HTML
- negative_classes
List of classes we’ll treat as negative (defaults to “empty”, typically includes classes like “blank”, “misfire”, etc.).
Include the token “#NO_LABELS#” to indicate that an image with no annotations should be considered empty.
- num_images_to_sample
Number of images to sample, -1 for “all images”
- output_dir
Folder to which we should write HTML output
- output_html_encoding
Character encoding to use when writing the index HTML html
- parallelize_rendering
Enable/disable rendering parallelization
- parallelize_rendering_n_cores
Number of threads/processes to use for rendering parallelization
- parallelize_rendering_with_threads
Whether to use threads (True) or processes (False) for rendering parallelization
- rendering_bypass_sets
List of output sets that we should count, but not render images for.
Typically used to preview sets with lots of empties, where you don’t want to subset but also don’t want to render 100,000 empty images.
Example strings that are valid for this option:
detections, non_detections detections_animal, detections_person, detections_vehicle tn, tp, fn, fp
- sample_seed
Random seed for sampling, or None
- separate_detections_by_category
Optionally separate detections into categories (animal/vehicle/human)
Currently only supported when ground truth is unavailable
- sort_classification_results_by_count
When classification results are present, should be sort alphabetically by class name (False) or in descending order by frequency (True)?
- target_recall
Used for summary statistics only
- unlabeled_classes
List of classes we’ll treat as neither positive nor negative (defaults to “unknown”, typically includes classes like “unidentifiable”).
- viz_target_width
Image width for images in the HTML output
- class megadetector.postprocessing.postprocess_batch_results.PostProcessingResults[source]
Bases:
objectReturn format from process_batch_results
- api_detection_results
Pandas Dataframe containing detection results
- api_other_fields
str –> obj dictionary containing other information loaded from the results file
- output_html_file
HTML file to which preview information was written
- megadetector.postprocessing.postprocess_batch_results.process_batch_results(options)[source]
Given a .json or .csv file containing MD results, do one or more of the following:
Sample detections/non-detections and render to HTML (when ground truth isn’t available) (this is 99.9% of what this module is for)
Evaluate detector precision/recall, optionally rendering results (requires ground truth)
Sample true/false positives/negatives and render to HTML (requires ground truth)
Ground truth, if available, must be in COCO Camera Traps format:
- Parameters:
options (PostProcessingOptions) – everything we need to render a preview/analysis for this set of results; see the PostProcessingOptions class for details.
- Returns:
information about the results/preview, most importantly the HTML filename of the output. See the PostProcessingResults class for details.
- Return type:
postprocess_batch_results - CLI interface
postprocess_batch_results [-h] [--image_base_dir IMAGE_BASE_DIR]
[--ground_truth_json_file GROUND_TRUTH_JSON_FILE]
[--confidence_threshold CONFIDENCE_THRESHOLD]
[--almost_detection_confidence_threshold ALMOST_DETECTION_CONFIDENCE_THRESHOLD]
[--target_recall TARGET_RECALL]
[--num_images_to_sample NUM_IMAGES_TO_SAMPLE]
[--viz_target_width VIZ_TARGET_WIDTH] [--include_almost_detections]
[--html_sort_order HTML_SORT_ORDER] [--sort_by_confidence]
[--n_cores N_CORES] [--parallelize_rendering_with_processes]
[--no_separate_detections_by_category] [--open_output_file]
[--max_figures_per_html_file MAX_FIGURES_PER_HTML_FILE]
md_results_file output_dir
postprocess_batch_results positional arguments
md_results_file- path to .json file containing MegaDetector resultsoutput_dir- base directory for output
postprocess_batch_results options
--image_base_dirIMAGE_BASE_DIR- base directory for images (optional, can compute statistics without images)--ground_truth_json_fileGROUND_TRUTH_JSON_FILE- ground truth labels (optional, can render detections without ground truth), in the COCO Camera Traps format--confidence_thresholdCONFIDENCE_THRESHOLD- Confidence threshold for statistics and visualization--almost_detection_confidence_thresholdALMOST_DETECTION_CONFIDENCE_THRESHOLD- Almost-detection confidence threshold for statistics and visualization--target_recallTARGET_RECALL- Target recall (for statistics only)--num_images_to_sampleNUM_IMAGES_TO_SAMPLE- number of images to visualize, -1 for all images (default: 500)--viz_target_widthVIZ_TARGET_WIDTH- Output image width--include_almost_detections- Include a separate category for images just above a second confidence threshold--html_sort_orderHTML_SORT_ORDER- Sort order for output pages, should be one of [filename,confidence,random] (defaults to filename)--sort_by_confidence- Sort output in decreasing order by confidence (defaults to sorting by filename)--n_coresN_CORES- Number of threads to use for rendering (default: 1)--parallelize_rendering_with_processes- Should we use processes (instead of threads) for parallelization?--no_separate_detections_by_category- Collapse all categories into just"detections"and"non-detections"--open_output_file- Open the HTML output file when finished--max_figures_per_html_fileMAX_FIGURES_PER_HTML_FILE- Maximum number of images to put on a single HTML page
postprocessing.remap_detection_categories module
remap_detection_categories.py
Given a MegaDetector results file, remap the category IDs according to a specified dictionary, writing the results to a new file.
Currently only supports remapping detection categories, not classification categories.
- megadetector.postprocessing.remap_detection_categories.remap_detection_categories(input_file, output_file, target_category_map, input_category_name_to_output_category_name, overwrite=False, invalid_category_handling='unknown')[source]
Given a MegaDetector results file [input_file], remap the category IDs according to the dictionary [target_category_map], writing the results to [output_file]. The remapped dictionary needs to have the same category names as the input file’s detection_categories dictionary.
Typically used to map, e.g., a variety of species to the class “mammal” or the class “animal”.
Currently only supports remapping detection categories, not classification categories.
- Parameters:
input_file (str) – the MD .json results file to remap
output_file (str) – the remapped .json file to write
target_category_map (dict) – the category mapping that should be used in the output file, mapping string-ints to class names. This can also be a MD results file, in which case we’ll use that file’s detection_categories dictionary.
input_category_name_to_output_category_name (dict) – str->str, the specific category mapping that should be used, otherwise will determine from target class names
overwrite (bool, optional) – whether to overwrite [output_file] if it exists; if this is True and [output_file] exists, this function is a no-op
invalid_category_handling (str, optional) – what to do about categories that are not in the input file’s category list (‘error’ or ‘unknown’), if ‘unknown’, creates a new “unknown” category
postprocessing.render_detection_confusion_matrix module
render_detection_confusion_matrix.py
Given a CCT-formatted ground truth file and a MegaDetector-formatted results file, render an HTML confusion matrix. Typically used for multi-class detectors. Currently assumes a single class per image.
- megadetector.postprocessing.render_detection_confusion_matrix.render_detection_confusion_matrix(ground_truth_file, results_file, image_folder, preview_folder, force_render_images=False, confidence_thresholds=None, rendering_confidence_thresholds=None, target_image_size=(1280, -1), parallelize_rendering=True, parallelize_rendering_n_cores=None, parallelize_rendering_with_threads=False, job_name='unknown', model_file=None, empty_category_name='empty', html_image_list_options=None)[source]
Given a CCT-formatted ground truth file and a MegaDetector-formatted results file, render an HTML confusion matrix in [preview_folder. Typically used for multi-class detectors. Currently assumes a single class per image.
confidence_thresholds and rendering_confidence_thresholds are dictionaries mapping class names to thresholds. “default” is a special token that will be used for all classes not otherwise assigned thresholds.
- Parameters:
ground_truth_file (str) – the CCT-formatted .json file with ground truth information
results_file (str) – the MegaDetector results .json file
image_folder (str) – the folder where images live; filenames in [ground_truth_file] and [results_file] should be relative to this folder.
preview_folder (str) – the output folder, i.e. the folder in which we’ll create our nifty HTML stuff.
force_render_images (bool, optional) – if False, skips images that already exist
confidence_thresholds (dict, optional) – a dictionary mapping class names to thresholds; all classes not explicitly named here will use the threshold for the “default” category.
rendering_confidence_thresholds (dict, optional) – a dictionary mapping class names to thresholds; all classes not explicitly named here will use the threshold for the “default” category.
target_image_size (tuple, optional) – output image size, as a pair of ints (width,height). If one value is -1 and the other is not, aspect ratio is preserved. If both are -1, the original image sizes are preserved.
parallelize_rendering (bool, optional) – enable (default) or disable parallelization when rendering
parallelize_rendering_n_cores (int, optional) – number of threads or processes to use for rendering, only used if parallelize_rendering is True
parallelize_rendering_with_threads (bool, optional) – whether to use threads (True) or processes (False) when rendering, only used if parallelize_rendering is True
job_name (str, optional) – job name to include in big letters in the output file
model_file (str, optional) – model filename to include in HTML output
empty_category_name (str, optional) – special category name that we should treat as empty, typically “empty”
html_image_list_options (dict, optional) – options listed passed along to write_html_image_list; see write_html_image_list for documentation.
- Returns:
confusion matrix information, containing at least the key “html_file”
- Return type:
dict
postprocessing.separate_detections_into_folders module
separate_detections_into_folders.py
Overview
Given a .json file with batch processing results, separate the files in that set of results into folders that contain animals/people/vehicles/nothing, according to per-class thresholds.
Image files are copied, not moved.
Output structure
Preserves relative paths within each of those folders; cannot be used with .json files that have absolute paths in them.
For example, if your .json file has these images:
a/b/c/1.jpg
a/b/d/2.jpg
a/b/e/3.jpg
a/b/f/4.jpg
a/x/y/5.jpg
And let’s say:
The results say that the first three images are empty/person/vehicle, respectively
The fourth image is above threshold for “animal” and “person”
The fifth image contains an animal
You specify an output base folder of c:/out
You will get the following files:
c:/out/empty/a/b/c/1.jpg
c:/out/people/a/b/d/2.jpg
c:/out/vehicles/a/b/e/3.jpg
c:/out/animal_person/a/b/f/4.jpg
c:/out/animals/a/x/y/5.jpg
Rendering bounding boxes
By default, images are just copied to the target output folder. If you specify –render_boxes, bounding boxes will be rendered on the output images. Because this is no longer strictly a copy operation, this may result in the loss of metadata. More accurately, this may result in the loss of some EXIF metadata; this will result in the loss of IPTC/XMP metadata.
Rendering boxes also makes this script a lot slower.
Classification-based separation
If you have a results file with classification data, you can also specify classes to put in their own folders, within the “animals” folder, like this:
--classification_thresholds "deer=0.75,cow=0.75"
So, e.g., you might get:
c:/out/animals/deer/a/x/y/5.jpg
In this scenario, the folders within “animals” will be:
deer, cow, multiple, unclassified
“multiple” in this case only means “deer and cow”; if an image is classified as containing a bird and a bear, that would end up in “unclassified”, since the folder separation is based only on the categories you provide at the command line.
No classification-based separation is done within the animal_person, animal_vehicle, or animal_person_vehicle folders.
- class megadetector.postprocessing.separate_detections_into_folders.SeparateDetectionsIntoFoldersOptions(threshold=None)[source]
Bases:
objectOptions used to parameterize separate_detections_into_folders()
- allow_existing_directory
By default, this function errors if you try to output to an existing folder
- allow_missing_files
By default, this function errors if any of the images specified in the results file don’t exist in the source folder.
- base_input_folder
The folder containing source images; filenames in [results_file] should be relative to this folder.
- base_output_folder
The folder to which we should write output images; see the module header comment for information about how that folder will be structured.
- box_expansion
Box expansion in pixels; only relevant if [render_boxes] is True
- category_id_to_category_name
Do not set explicitly; this gets loaded from [results_file]
- category_name_to_folder
Do not set explicitly; this gets created based on [results_file]
Dictionary mapping categories (plus combinations of categories, and ‘empty’) to output folders
- category_name_to_threshold
Dict mapping category names to thresholds; for example, an image with only a detection of class “animal” whose confidence is greater than or equal to category_name_to_threshold[‘animal’] will be put in the “animal” folder.
- category_names_to_blur
List of category names for which we should blur detections, most commonly [‘person’]
Can also be a comma-separated list.
- classification_categories
Do not set explicitly; populated from data when using classification results
- classification_category_id_to_name
Do not set explicitly; populated from data when using classification results
- classification_thresholds
Originally specified as a string that looks like this:
deer=0.75,cow=0.75
String, converted internally to a dict mapping name:threshold
- debug_max_images
Used to test this script; sets a limit on the number of images to process.
- line_thickness
Line thickness in pixels; only relevant if [render_boxes] is True
- move_images
Should we move rather than copy?
- n_threads
Number of workers to use, set to <= 1 to disable parallelization
- overwrite
Whether to overwrite images that already exist in the target folder; only relevant if [allow_existing_directory] is True
- remove_empty_folders
Remove all empty folders from the target folder at the end of the process, whether or not they were created by this script
- render_boxes
Should we render boxes on the output images? Makes everything a lot slower.
- results_file
The MD results .json file to process
- skip_empty_images
Whether to skip empty images; if this is False, empty images (i.e., images with no detections above the corresponding threshold) will be copied to an “empty” folder.
- threshold
Default threshold for categories not specified in category_name_to_threshold
- megadetector.postprocessing.separate_detections_into_folders.separate_detections_into_folders(options)[source]
Given a .json file with batch processing results, separate the files in that set of results into folders that contain animals/people/vehicles/nothing, according to per-class thresholds. See the header comment of this module for more details about the output folder structure.
- Parameters:
options (SeparateDetectionsIntoFoldersOptions) – parameters guiding image
separation
specific (see the SeparateDetectionsIntoFoldersOptions documentation for)
options.
separate_detections_into_folders - CLI interface
separate_detections_into_folders [-h] [--threshold THRESHOLD]
[--animal_threshold ANIMAL_THRESHOLD]
[--human_threshold HUMAN_THRESHOLD]
[--vehicle_threshold VEHICLE_THRESHOLD]
[--classification_thresholds CLASSIFICATION_THRESHOLDS]
[--n_threads N_THREADS] [--allow_existing_directory]
[--no_overwrite] [--skip_empty_images] [--move_images]
[--render_boxes] [--line_thickness LINE_THICKNESS]
[--box_expansion BOX_EXPANSION]
[--category_names_to_blur CATEGORY_NAMES_TO_BLUR]
[--remove_empty_folders]
results_file base_input_folder base_output_folder
separate_detections_into_folders positional arguments
results_file- Input .json filenamebase_input_folder- Input image folderbase_output_folder- Output image folder
separate_detections_into_folders options
--thresholdTHRESHOLD- Default confidence threshold for all categories (defaults to selection based on model version, other options may override this for specific categories)--animal_thresholdANIMAL_THRESHOLD- Confidence threshold for the animal category--human_thresholdHUMAN_THRESHOLD- Confidence threshold for the human category--vehicle_thresholdVEHICLE_THRESHOLD- Confidence threshold for vehicle category--classification_thresholdsCLASSIFICATION_THRESHOLDS- List of classification thresholds to use for species-based folder separation, formatted as, e.g.,"deer=0.75,cow=0.75"--n_threadsN_THREADS- Number of threads to use for parallel operation (default=1)--allow_existing_directory- Proceed even if the target directory exists and is not empty--no_overwrite- Skip images that already exist in the target folder, must also specify –allow_existing_directory--skip_empty_images- Do not copy empty images to the output folder--move_images- Move images (rather than copying) (not recommended this if you have not backed up your data!)--render_boxes- Render bounding boxes on output images; may result in some metadata not being transferred--line_thicknessLINE_THICKNESS- Line thickness (in pixels) for rendering, only meaningful if using render_boxes (defaults to 8)--box_expansionBOX_EXPANSION- Box expansion (in pixels) for rendering, only meaningful if using render_boxes (defaults to 3)--category_names_to_blurCATEGORY_NAMES_TO_BLUR- Comma-separated list of category names to blur (or a single category name, e.g."person")--remove_empty_folders- Remove all empty folders from the target folder at the end of the process, whether or not they were created by this script
postprocessing.subset_json_detector_output module
subset_json_detector_output.py
Creates one or more subsets of a detector results file (.json), doing either or both of the following (if both are requested, they happen in this order):
Retrieve all elements where filenames contain a specified query string, optionally replacing that query with a replacement token. If the query is blank, can also be used to prepend content to all filenames.
Does not support regex’s, but supports a special case of ^string to indicate “must start with to match”.
Create separate .jsons for each unique path, optionally making the filenames in those .json’s relative paths. In this case, you specify an output directory, rather than an output path. All images in the folder blah/foo/bar will end up in a .json file called blah_foo_bar.json.
Can also apply a confidence threshold.
Can also subset by categories above a threshold (programmatic invocation only, this is not supported at the command line yet).
To subset a COCO Camera Traps .json database, see subset_json_db.py
Sample invocation (splitting into multiple json’s)
Read from “1800_idfg_statewide_wolf_detections_w_classifications.json”, split up into individual .jsons in ‘d:/temp/idfg/output’, making filenames relative to their individual folders:
- python subset_json_detector_output.py ^
“d:/temp/idfg/1800_idfg_statewide_wolf_detections_w_classifications.json” “d:/temp/idfg/output” ^ –split_folders –make_folder_relative
Now do the same thing, but instead of writing .json’s to d:/temp/idfg/output, write them to subfolders corresponding to the subfolders for each .json file.
- python subset_json_detector_output.py ^
“d:/temp/idfg/1800_detections_S2.json” “d:/temp/idfg/output_to_folders” ^ –split_folders –make_folder_relative –copy_jsons_to_folders
Sample invocation (creating a single subset matching a query)
Read from “1800_detections.json”, write to “1800_detections_2017.json”
Include only images matching “2017”, and change “2017” to “blah”
- python subset_json_detector_output.py “d:/temp/1800_detections.json” “d:/temp/1800_detections_2017_blah.json” ^
–query 2017 –replacement blah
Include all images, prepend with “prefix/”
- python subset_json_detector_output.py “d:/temp/1800_detections.json” “d:/temp/1800_detections_prefix.json” ^
–replacement “prefix/”
- class megadetector.postprocessing.subset_json_detector_output.SubsetJsonDetectorOutputOptions[source]
Bases:
objectOptions used to parameterize subset_json_detector_output()
- categories_to_keep
Either a list of category IDs (as string-ints) (not names), or a dictionary mapping category IDs (as string-ints) (not names) to thresholds. Removes non-matching detections, does not remove images. Not technically mutually exclusize with category_names_to_keep, but it’s an esoteric scenario indeed where you would want to specify both.
- category_names_to_keep
Either a list of category names (not IDs), or a dictionary mapping category names (not IDs) to thresholds. Removes non-matching detections, does not remove images. Not technically mutually exclusize with category_ids_to_keep, but it’s an esoteric scenario indeed where you would want to specify both.
- confidence_threshold
Optional confidence threshold; if not None, detections below this confidence won’t be included in the output.
- copy_jsons_to_folders
if not None, will copy .json files to their corresponding output directories, relative to output_filename
- Type:
Only meaningful if split_folders and make_folder_relative are True
- copy_jsons_to_folders_directories_must_exist
If copy_jsons_to_folders is true, do we require that directories already exist?
- debug_max_images
Set to >0 during testing to limit the number of images that get processed.
- keep_files_in_list
Assumes that the input .json file contains relative paths when comparing to a folder.
- make_folder_relative
should we convert pathnames to be relative the folder for each .json file?
- Type:
Only meaningful if split_folders is True
- maximum_detection_size
Remove detections above a threshold size (as a fraction of the image size)
- minimum_detection_size
Remove detections below a threshold size (as a fraction of the image size)
- overwrite_json_files
Should we over-write .json files?
- query
Only process files containing the token ‘query’
Does not support general regexes, but supports ^ as a special case regex-like notation for “starts with”
- remove_classification_categories_below_count
Remove classification with <= N instances. Does not re-map categories to be contiguous. Set to 1 to remove empty categories only.
- remove_failed_images
Should we remove failed images?
- replacement
Replace ‘query’ with ‘replacement’ if ‘replacement’ is not None. If ‘query’ is None, prepend ‘replacement’
- split_folder_mode
Folder level to use for splitting [‘bottom’,’n_from_bottom’,’n_from_top’,’dict’]
‘dict’ requires ‘split_folder_param’ to be a dictionary mapping each filename to a token.
- split_folder_param
When using the ‘n_from_bottom’ parameter to define folder splitting, this defines the number of directories from the bottom. ‘n_from_bottom’ with a parameter of zero is the same as ‘bottom’.
Same story with ‘n_from_top’.
When ‘split_folder_mode’ is ‘dict’, this should be a dictionary mapping each filename to a token.
- split_folders
Should we split output into individual .json files for each folder?
- megadetector.postprocessing.subset_json_detector_output.remove_classification_categories_below_count(data, options)[source]
Removes all classification categories below a threshold count. Does not re-map classification category IDs.
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.remove_failed_images(data, options)[source]
Removed failed images from [data]
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.subset_json_detector_output(input_filename, output_filename, options, data=None)[source]
Main entry point; creates one or more subsets of a detector results file. See the module header comment for more information about the available subsetting approaches.
Makes a copy of [data] before modifying if a data dictionary is supplied.
- Parameters:
input_filename (str) – filename to load and subset; can be None if [data] is supplied
output_filename (str) – file or folder name (depending on [options]) to which we should write subset results.
options (SubsetJsonDetectorOutputOptions) – parameters for .json splitting/subsetting; see SubsetJsonDetectorOutputOptions for details.
data (dict, optional) – data loaded from a .json file; if this is not None, [input_filename] will be ignored. If supplied, this will be copied before it’s modified.
- Returns:
Results that are either loaded from [input_filename] and processed, or copied from [data] and processed.
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.subset_json_detector_output_by_categories(data, options)[source]
Removes all detections without detections above a threshold for specific categories.
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.subset_json_detector_output_by_confidence(data, options)[source]
Removes all detections below options.confidence_threshold.
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.subset_json_detector_output_by_list(data, options)[source]
Keeps only files in options.keep_files_in_list, which can be a .json results file or a folder. Assumes that the input .json file contains relative paths when comparing to a folder.
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.subset_json_detector_output_by_query(data, options)[source]
Subsets to images whose filename matches options.query; replace all instances of options.query with options.replacement. No-op if options.query_string is None or ‘’.
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
- megadetector.postprocessing.subset_json_detector_output.subset_json_detector_output_by_size(data, options)[source]
Remove detections above or below threshold sizes (as a fraction of the image size).
- Parameters:
data (dict) – data loaded from a MD results file
options (SubsetJsonDetectorOutputOptions) – parameters for subsetting
- Returns:
Possibly-modified version of [data] (also modifies in place)
- Return type:
dict
subset_json_detector_output - CLI interface
subset_json_detector_output [-h] [--query QUERY] [--replacement REPLACEMENT]
[--confidence_threshold CONFIDENCE_THRESHOLD]
[--maximum_detection_size MAXIMUM_DETECTION_SIZE]
[--minimum_detection_size MINIMUM_DETECTION_SIZE]
[--keep_files_in_list KEEP_FILES_IN_LIST] [--split_folders]
[--split_folder_param SPLIT_FOLDER_PARAM]
[--split_folder_mode SPLIT_FOLDER_MODE] [--make_folder_relative]
[--overwrite_json_files] [--copy_jsons_to_folders]
[--create_folders]
[--remove_classification_categories_below_count REMOVE_CLASSIFICATION_CATEGORIES_BELOW_COUNT]
input_file output_file
subset_json_detector_output positional arguments
input_file- Input .json filenameoutput_file- Output .json filename
subset_json_detector_output options
--queryQUERY- Query string to search for (omitting this matches all)--replacementREPLACEMENT- Replace [query] with this--confidence_thresholdCONFIDENCE_THRESHOLD- Remove detections below this confidence level--maximum_detection_sizeMAXIMUM_DETECTION_SIZE- Remove detections above this size (as a fraction of the image size)--minimum_detection_sizeMINIMUM_DETECTION_SIZE- Remove detections below this size (as a fraction of the image size)--keep_files_in_listKEEP_FILES_IN_LIST- Keep only files in this list, which can be a .json results file or a folder. Assumes that the input .json file contains relative paths when comparing to a folder.--split_folders- Split .json files by leaf-node folder--split_folder_paramSPLIT_FOLDER_PARAM- Directory level count for n_from_bottom and n_from_top splitting--split_folder_modeSPLIT_FOLDER_MODE- Folder level to use for splitting ("bottom","n_from_bottom", or"n_from_top")--make_folder_relative- Make image paths relative to their containing folder (only meaningful with split_folders)--overwrite_json_files- Overwrite output files--copy_jsons_to_folders- When using split_folders and make_folder_relative, copy jsons to their corresponding folders (relative to output_file)--create_folders- When using copy_jsons_to_folders, create folders that dont exist--remove_classification_categories_below_countREMOVE_CLASSIFICATION_CATEGORIES_BELOW_COUNT- Remove classification categories with less than this many instances (no removal by default)
postprocessing.top_folders_to_bottom module
top_folders_to_bottom.py
Given a base folder with files like:
A/1/2/a.jpg
B/3/4/b.jpg
…moves the top-level folders to the bottom in a new output folder, i.e., creates:
1/2/A/a.jpg
3/4/B/b.jpg
In practice, this is used to make this:
animal/camera01/image01.jpg
…look like:
camera01/animal/image01.jpg
- class megadetector.postprocessing.top_folders_to_bottom.TopFoldersToBottomOptions(input_folder, output_folder, copy=True, n_threads=1, overwrite=False)[source]
Bases:
objectOptions used to parameterize top_folders_to_bottom()
- copy
Whether to copy (True) vs. move (False) false when re-organizing
- input_folder
Input folder
- n_threads
Number of worker threads to use, or <1 to disable parallelization
- output_folder
Output folder
- overwrite
If this is False and an output file exists, throw an error
- megadetector.postprocessing.top_folders_to_bottom.top_folders_to_bottom(options)[source]
top_folders_to_bottom.py
Given a base folder with files like:
A/1/2/a.jpg
B/3/4/b.jpg
…moves the top-level folders to the bottom in a new output folder, i.e., creates:
1/2/A/a.jpg
3/4/B/b.jpg
In practice, this is used to make this:
animal/camera01/image01.jpg
…look like:
camera01/animal/image01.jpg
- Parameters:
options (TopFoldersToBottomOptions) – See TopFoldersToBottomOptions for parameter details.
top_folders_to_bottom - CLI interface
top_folders_to_bottom [-h] [--copy] [--overwrite] [--n_threads N_THREADS]
input_folder output_folder
top_folders_to_bottom positional arguments
input_folder- Input image folderoutput_folder- Output image folder
top_folders_to_bottom options
--copy- Copy images, instead of moving (moving is the default)--overwrite- Allow image overwrite (default=False)--n_threadsN_THREADS- Number of threads to use for parallel operation (default=1)
postprocessing.generate_csv_report module
generate_csv_report.py
Generates a .csv report from a MD-formatted .json file with the following columns:
filename
datetime (if images or EXIF information is supplied)
detection_category
max_detection_confidence
classification_category
max_classification_confidence
count
One row is generated per category pair per image. For example, these would be unique rows:
image0001.jpg,animal,deer,4 image0001.jpg,animal,lion,4 image0001.jpg,animal,[none],4 image0001.jpg,person,[none],2
Images with no above-threshold detections will have a single row:
image0001.jpg,empty,[none],-1
Images with processing errors will have a single row:
image0001.jpg,error,error_string,-1
- megadetector.postprocessing.generate_csv_report.generate_csv_report(md_results_file, output_file=None, datetime_source=None, folder_level_columns=None, detection_confidence_threshold=None, classification_confidence_threshold=None, verbose=True)[source]
Generates a .csv report from a MD-formatted .json file
- Parameters:
md_results_file (str) – MD results .json file for which we should generate a report
output_file (str, optional) – .csv file to write; if this is None, we’ll use md_results_file.csv
datetime_source (str, optional) – if datetime information is required, this should point to a folder of images, a MD results .json file (can be the same as the input file), or an exif_info.json file created with read_exif().
folder_level_columns (list of int, optional) – list of folder levels (where zero is the top-level folder in a path name) for which we should create separate columns. Should be zero-indexed ints, or a comma-delimited list of zero-indexed int-strings.
detection_confidence_threshold (float, optional) – detections below this confidence threshold will not be included in the output data. Defaults to the recommended value based on the .json file.
classification_confidence_threshold (float, optional) – classifications below this confidence threshold will not be included in the output data (i.e., detections will be considered “animal”).
verbose (bool, optional) – enable debug output, including the progress bar,
- Returns:
the output .csv filename
- Return type:
str
generate_csv_report - CLI interface
Generates a .csv report from a MD-formatted .json file
generate_csv_report [-h] [--output_file OUTPUT_FILE] [--datetime_source DATETIME_SOURCE]
[--folder_level_columns FOLDER_LEVEL_COLUMNS]
[--detection_confidence_threshold DETECTION_CONFIDENCE_THRESHOLD]
[--classification_confidence_threshold CLASSIFICATION_CONFIDENCE_THRESHOLD]
[--verbose]
md_results_file
generate_csv_report positional arguments
md_results_file- Path to MD results file (.json)
generate_csv_report options
--output_fileOUTPUT_FILE- Output filename (.csv) (if omitted, will append .csv to the input file)--datetime_sourceDATETIME_SOURCE- Image folder, exif_info.json file, or MD results file from which we should read datetime information--folder_level_columnsFOLDER_LEVEL_COLUMNS- Comma-separated list of zero-indexed folder levels that should become columns in the output file--detection_confidence_thresholdDETECTION_CONFIDENCE_THRESHOLD- Detection threshold (if omitted, chooses a reasonable default based on the .json file)--classification_confidence_thresholdCLASSIFICATION_CONFIDENCE_THRESHOLD- Classification threshold (default 0.3)--verbose- Enable additional debug output