fix(iou): clamp box extents so a malformed box cannot earn a GIoU bonus - #589
Open
MahathirMohammadShuvo wants to merge 1 commit into
Open
Conversation
_compute_iou_and_enclosing computed box area as (x2 - x1) * (y2 - y1) without clamping, three lines after the intersection is correctly clamped with np.maximum(..., 0). For a box inverted on both axes the two negative extents multiply to a positive area, which inflates the union past the enclosing area and flips GIoU's (enclosing - union) / enclosing penalty into a bonus. Reachable through SORTTracker, whose default XYXYStateEstimator has an unconstrained velocity and whose tracklet has no downstream box clamp. A shrinking track left unmatched for six frames yields the bbox [274.3, 274.3, 125.7, 125.7], which scored GIoU +2.2080 against a real detection versus +0.6400 for a well-formed near-perfect match, outside GIoU's documented [-1, 1] range. It now scores 0.0. Affects GIoU only: IoU and BIoU route through sv.box_iou_batch and never enter this helper, and DIoU and CIoU are byte-identical because a malformed axis already forces the intersection to zero. Results for well-formed boxes are bit-identical, so no benchmark run is required. Extends TestDegenerateInputs, whose inverted-coordinate test previously asserted only shape and finiteness and so passed at GIoU +1.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
_compute_iou_and_enclosingcomputes box area as(x2 - x1) * (y2 - y1)with no clamp — three lines after the intersection is correctly clamped withnp.maximum(..., 0):For a box inverted on both axes the two negative extents multiply to a positive area. That inflates
unionpastenclosing_area, so GIoU's(enclosing - union) / enclosingpenalty term goes negative — a bonus instead of a penalty.Reachable through a shipped tracker
SORTTracker's defaultXYXYStateEstimatorhas an unconstrained velocity (clamp_velocityis a documented no-op — "XYXY-style velocity is unconstrained"), andsort/tracklet.pyhas no downstream box clamp:state_to_bbox()returnskf.state[:4]straight intoself.iou.compute.Four shrinking detections, then six unmatched frames:
The ghost outranks a genuine match, at a score outside GIoU's documented
[-1, 1]. Over 3,000 random malformed pairs the pre-fix maximum was+29.54.Scope
GIoUonly.IoU/BIoUroute throughsv.box_iou_batchand never enter this helper.DIoU/CIoUare byte-identical before and after, because a malformed axis already forcesintersection = 0and they consume onlyiouandenclosing_diagonal_sq.np.maximum(x, 0)returnsxunchanged forx > 0— so no benchmark run is needed.DIoU/CIoUremain unbounded below on malformed input, because the enclosing box is built frommin/maxof the corners, so an inverted box makesCstop enclosing the pair and the distance normaliser collapses ([500,500,0,0]vs[0,0,10,10]→ DIoU-600.25). That is a separate defect in a different term. The docstrings now say so rather than implying it is covered — happy to fold it into this PR if you would prefer.XYXYStateEstimator/XCYCWHStateEstimatorboth have no-opclamp_velocity) and abandoned it: freezing extent velocity changes tracking output on the defaultframe_step=1.0path for BoT-SORT/McByte/C-BIoU, and can freeze the velocity that would recover an inverted box. Fixing the metric covers every producer at once.Tests
TestDegenerateInputs.test_inverted_coords_gives_zero_or_negative_similaritypromised its name but asserted only shape and finiteness, so it passed at GIoU+1.0. It is now split into an exact-value test (all three inversion patterns must equal a well-formed zero-area box) and a sign test acrossIoU/GIoU/DIoU/CIoU/BIoU× 3 patterns, plus aunion <= enclosing_areainvariant.5 assertions fail on
developwithout the source change, includingassert 4000.0 <= 3200.0.ruff checkclean ·ruff formatclean ·mypyclean ·iou.pydoctests 6/6 ·tests/utils+tests/motion165 passed ·tests/corefast subset 607 passed.