dataeval.core.compute_ratios

dataeval.core.compute_ratios(stats_output, *, target_stats_output=None, override_map=None)

Compute box-to-image ratios from compute_stats() output.

This function supports two usage patterns:

1. Unified input: Pass a single stats_output containing both image and box statistics (from compute_stats() with per_image=True, per_target=True).

2. Separate inputs: Pass image stats as stats_output and box stats as box_stats_output (useful when migrating from boxratiostats()).

Parameters:
stats_output : StatsResult

Either:

  • Output from compute_stats() with both per_image=True and per_target=True (unified), OR

  • Output from compute_stats() with per_image=True, per_target=False (if box_stats_output provided)

target_stats_output : StatsResult | None, optional

Output from compute_stats() with per_image=False and per_target=True. When provided, stats_output is treated as image-only stats. Default is None (use unified input from stats_output).

override_map : OverrideFunctionMap | None, optional

Optional custom ratio calculations for specific stat keys.

Function signature: (box_stats_dict, img_stats_dict) -> ratio_value

If None, uses default override map for common statistics.

Returns:

Dictionary with same structure as compute_stats() output, including:

  • source_index: Sequence[SourceIndex] - SourceIndex objects with image/box/channel info

  • object_count: Sequence[int] - Object counts per image

  • invalid_box_count: Sequence[int] - Invalid box counts per image

  • image_count: int - Total number of images processed

  • stats: Mapping[str, Sequence[Any]] - Mapping of statistic names to sequences of computed values

Return type:

StatsResult

Raises:
  • ValueError – If inputs don’t contain the required image and box statistics, or if the two inputs are incompatible (different image counts, mismatched channels).

  • KeyError – If stats_output doesn’t contain required ‘source_index’ key.

Notes

  • Only processes entries where source_index.box is not None

  • For each box, finds its corresponding image stats (box=None, same image and channel index)

  • Applies custom calculations from override_map or defaults to simple division

  • Handles per-channel stats automatically via channel_index matching

  • BASE_ATTRS (source_index, object_count, etc.) are preserved for box entries only

Examples

Pattern 1: Unified input (recommended)

>>> from dataeval.core import compute_stats, compute_ratios
>>> from dataeval.flags import ImageStats
>>>
>>> # Single call gets both image and target stats
>>> stats = compute_stats(images, boxes=boxes, stats=ImageStats.DIMENSION, per_image=True, per_target=True)
>>> ratios = compute_ratios(stats)
>>> ratios["stats"]["width"][:12]
array([0.25 , 0.203, 0.328, 0.266, 0.234, 0.297, 0.25 , 0.359, 0.297,
       0.234, 0.359, 0.234], dtype=float32)

Pattern 2: Separate inputs (backward compatibility)

>>> # Separate calls for image and box stats
>>> img_stats = compute_stats(images, boxes=boxes, stats=ImageStats.DIMENSION, per_image=True, per_target=False)
>>> tgt_stats = compute_stats(images, boxes=boxes, stats=ImageStats.DIMENSION, per_image=False, per_target=True)
>>> ratios = compute_ratios(img_stats, target_stats_output=tgt_stats)

Custom override map:

>>> custom_overrides = {
...     "mean": lambda box, img: (box["mean"] - img["mean"]) / (img["std"] + 1e-10),
... }
>>> ratios = compute_ratios(stats, override_map=custom_overrides)

Per-channel statistics:

>>> stats = compute_stats(
...     images, boxes=boxes, stats=ImageStats.PIXEL, per_image=True, per_target=True, per_channel=True
... )
>>> ratios = compute_ratios(stats)
>>> # Ratios are calculated per-channel automatically