Skip to content

[Feature]: Geometry-aware dispatch to stop the recurring "silent AABB" bug class #2318

Description

@kounelisagis

Search before asking

  • I have searched the issues and discussions and found no similar feature request.

Feature Description

What: A small geometry-aware dispatch layer so detection ops use the geometry each detection actually carries (mask / OBB / box) instead of silently falling back to the axis-aligned xyxy.

Why: Several recent fixes are the same bug in different functions: code grabs detections.xyxy and forgets the real geometry lives in data["xyxyxyxy"] (OBB) or mask. Because xyxy is always present, the wrong answer is the silent default:

Same root cause each time: Detections holds several geometries at once and xyxy is just a derived envelope, so every consumer re-implements "which geometry is the real one?" and forgetting it fails silently. The next geometry-aware function will hit it again.

How: Centralize the dispatch into a few batched helpers and route call sites through them instead of reaching for xyxy. No data-model change, keeps the vectorized design, backward compatible. Migration can be incremental, then deprecate the ad-hoc paths.

Proposed helpers (batched, no per-detection loops):

Rollout can be incremental and each step is independent / backward compatible: (1) consolidate the duplicated move_detections (pure dedup, no behavior change), (2) the read-only detection_iou / detection_area dispatch, (3) the contract test.

A first pass suggests more call sites in the same class worth investigating: get_anchors_coordinates (and therefore LineZone / PolygonZone) reads anchors off the envelope rather than the rotated body, as_coco and as_pascal_voc have no is_obb option and drop the rotation on export, with_nmm merges to the union envelope while keeping one input's data["xyxyxyxy"], and DetectionsSmoother averages xyxy without smoothing the oriented corners.

Example Usage

# one dispatch per op, instead of every function re-deriving it
def detection_area(det):
    if det.mask is not None:        return det.mask.sum(axis=(1, 2))
    if "xyxyxyxy" in det.data:      return _shoelace(det.data["xyxyxyxy"])
    return box_area(det.xyxy)

# same shape for detection_iou (mask / OBB / box), plus a geometry-complete
# move_detections that shifts every geometry field together (what #2427/#2430 forgot)

# and a contract test so the class is loud, not silent:
assert op(obb) != op(aabb_of(obb))   # an op must tell an OBB from its envelope

Are you willing to submit a PR?

  • Yes I'd like to help by submitting a PR!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions