Source code for iaa_od.metrics.scale_complexity

from iaa_od.models import GroundTruthProtocol, Result, STD_IOU_THR, ScaleComplexity
from iaa_od.utils import collapse_categories_interactive, validate_macrocats
from iaa_od.metrics import alpha
from typing import Optional
from numpy import isnan
from copy import deepcopy

[docs] def scale_complexity(gts: list[GroundTruthProtocol], /, *, collapsed_categories: Optional[dict[str, list[int]]], iou_threshold: float = STD_IOU_THR, use_iom: bool = False, precomputed_result: Optional[Result] = None) -> ScaleComplexity: """ Compute the scale complexity metric as defined in "Leadership of Data Annotation Teams" by McCulloh et al. Parameters gts (list[GroundTruthProtocol]): A list of GroundTruth objects representing the ground truth annotations. collapsed_categories (Optional[dict[str, list[int]]]): A dictionary mapping new category names to lists of original category IDs to be collapsed. If None, the function will prompt for interactive input. iou_threshold (float): The IoU threshold to use for matching. Default is STD_IOU_THR. use_iom (bool): Whether to use IoM matching. Default is False. precomputed_result (Optional[Result]): A precomputed Result object containing alpha value, IoU threshold, and lenient IoU settings. If provided, these settings will be used instead of computing them anew. Returns ScaleComplexity: The computed scale complexity value (global and per image), along with the alpha values before and after collapsing categories, both globally and per image. """ # Check that either iou_threshold and lenient_iou are default or precomputed_result is provided if precomputed_result and (iou_threshold != STD_IOU_THR or use_iom): raise ValueError("You cannot provide IoU settings when using a precomputed result.") # If no collapsed categories are provided, run the collapse_categories_interactive function to obtain them collapsed_categories_dict: dict[str, list[int]] = validate_macrocats(gts, collapsed_categories) if collapsed_categories is not None else collapse_categories_interactive(gts) # Check whether the "Excluded" category is included in the collapsed categories excluded: bool = False if "Excluded" in collapsed_categories_dict: excluded = True # Check the precomputed result: if it is passed, use its alpha value, IoU threshold and lenient IoU settings alpha_all: float iou_thr: float iom: bool alpha_per_image: dict[str, float] # Compute or retrieve the overall alpha value if precomputed_result: if precomputed_result.alpha is None: raise ValueError("The provided precomputed result does not contain an alpha value.") alpha_all = precomputed_result.alpha iou_thr = precomputed_result.iou_thr iom = precomputed_result.iom alpha_per_image = deepcopy(precomputed_result.alpha_per_image) else: new_result: Result = alpha(gts, iou_threshold=iou_threshold, use_iom=use_iom ) if new_result.alpha is None: raise ValueError("Something very wrong has happened. Check the alpha computation.") alpha_all = new_result.alpha iou_thr = iou_threshold iom = use_iom alpha_per_image = deepcopy(new_result.alpha_per_image) # Compute the new alpha value with collapsed categories collapsed_result: Result = alpha(gts, iou_threshold=iou_thr, use_iom=iom, collapsed_categories=collapsed_categories_dict ) if collapsed_result.alpha is None: raise ValueError("Something very wrong has happened. Check the alpha computation.") alpha_collapsed: float = collapsed_result.alpha alpha_per_image_collapsed: dict[str, float] = deepcopy(collapsed_result.alpha_per_image) # Compute the scale complexity scale_complexity_value: float = alpha_collapsed - alpha_all scale_complexity_per_image: dict[str, float] = {} if not excluded: for image_filename in alpha_per_image: if image_filename not in alpha_per_image_collapsed: raise ValueError(f"Image filename {image_filename} is missing in the collapsed alpha per image results.") if not isnan(alpha_per_image[image_filename]) and not isnan(alpha_per_image_collapsed[image_filename]): scale_complexity_per_image[image_filename] = alpha_per_image_collapsed[image_filename] - alpha_per_image[image_filename] else: scale_complexity_per_image[image_filename] = float('nan') # Create the ScaleComplexity object scale_complexity = ScaleComplexity( global_sc=scale_complexity_value, per_image_sc=scale_complexity_per_image, global_alpha=alpha_all, per_image_alpha=alpha_per_image, global_alpha_collapsed=alpha_collapsed, per_image_alpha_collapsed=alpha_per_image_collapsed, partial=excluded ) # Return the value return scale_complexity