Skip to content

perf(detection): vectorize box_iou_batch_with_jaccard#2359

Open
RubenHaisma wants to merge 1 commit into
roboflow:developfrom
RubenHaisma:perf/vectorize-jaccard-iou
Open

perf(detection): vectorize box_iou_batch_with_jaccard#2359
RubenHaisma wants to merge 1 commit into
roboflow:developfrom
RubenHaisma:perf/vectorize-jaccard-iou

Conversation

@RubenHaisma

Copy link
Copy Markdown
Contributor

Description

box_iou_batch_with_jaccard computed COCO-style Jaccard IoU with a double Python for loop calling a scalar _jaccard helper once per (detection, ground-truth) pair — an O(N·M) per-element pattern in otherwise pure-NumPy code, against AGENTS.md's "vectorized throughout — no Python loops in hot paths" guideline. It is the inner IoU of COCOEvaluator._compute_iou (called once per (image, category) during mAP evaluation) and is also public API (sv.box_iou_batch_with_jaccard).

This replaces the loop with a broadcasted NumPy implementation and drops the now-unused scalar _jaccard.

Correctness (bit-identical)

The far corners are built as x2 = x + w and the union associated as (area_det + area_gt - area_inter) + eps, so the output is bit-identical to the previous per-pair result — verified to max|diff| = 0.0 over 4000 randomized trials including zero/negative-width degenerate boxes and crowd flags. Crowd semantics are preserved (a crowd ground truth uses the detection area as the union). End-to-end COCO mAP results are unchanged: the existing tests/metrics/ suite passes without modification, and the docstring doctest output is unchanged.

Performance

Speedup scales with batch size and is faster even at the smallest sizes (no regression regime):

batch (gt × dt) loop vectorized speedup
5 × 5 26 µs 16 µs ~1.6×
15 × 60 876 µs 33 µs ~27×
50 × 100 4499 µs 68 µs ~66×

Tests

Adds TestBoxIouBatchWithJaccard: parity against an independent per-pair reference across empty / single / busy / degenerate+crowd batches, the crowd union semantics, the empty-input contract, and the is_crowd length guard. ruff check/format clean.

@RubenHaisma RubenHaisma requested a review from SkalskiP as a code owner June 27, 2026 12:53
`box_iou_batch_with_jaccard` computed COCO-style Jaccard IoU with a double
Python `for` loop calling a scalar `_jaccard` helper once per (detection,
ground-truth) pair — an O(N*M) per-element pattern in otherwise pure-NumPy
code. It is the inner IoU of `COCOEvaluator._compute_iou`, called once per
(image, category) during mAP evaluation, and is also public API
(`sv.box_iou_batch_with_jaccard`).

Replace the loop with a broadcasted NumPy implementation and drop the now
unused scalar `_jaccard`. The far corners are built as `x2 = x + w` and the
union is associated as `(area_det + area_gt - area_inter) + eps` so the
result is bit-identical to the previous per-pair output (verified to
`max|diff| = 0` over 4000 randomized trials including zero/negative-width
degenerate boxes and crowd flags). Crowd semantics are preserved: a crowd
ground truth uses the detection area as the union.

Speedup scales with batch size — ~1.6x at 5x5, ~27x at 15x60, ~66x at
50x100 — and is faster even at the smallest sizes, so there is no regime
where it regresses. End-to-end COCO mAP results are unchanged (the existing
metrics suite passes without modification).

Adds `TestBoxIouBatchWithJaccard`: parity against an independent per-pair
reference across empty / single / busy / degenerate+crowd batches, the crowd
union semantics, the empty-input contract, and the `is_crowd` length guard.
@RubenHaisma RubenHaisma force-pushed the perf/vectorize-jaccard-iou branch from 03f5695 to 10fef50 Compare June 27, 2026 13:01
@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82%. Comparing base (09b2199) to head (10fef50).

❌ Your project check has failed because the head coverage (82%) is below the target coverage (95%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@           Coverage Diff           @@
##           develop   #2359   +/-   ##
=======================================
  Coverage       82%     82%           
=======================================
  Files           68      68           
  Lines         9560    9556    -4     
=======================================
- Hits          7881    7878    -3     
+ Misses        1679    1678    -1     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant