Skip to content

Fix CXCYWH to XYXY conversion for integer bounding boxes#9322

Merged
zy1git merged 8 commits intopytorch:mainfrom
raimbekovm:fix/cxcywh-to-xyxy-int-conversion
Feb 11, 2026
Merged

Fix CXCYWH to XYXY conversion for integer bounding boxes#9322
zy1git merged 8 commits intopytorch:mainfrom
raimbekovm:fix/cxcywh-to-xyxy-int-conversion

Conversation

@raimbekovm
Copy link
Copy Markdown
Contributor

@raimbekovm raimbekovm commented Dec 31, 2025

Summary

Fixes incorrect _cxcywh_to_xyxy conversion that produced negative coordinates for integer bounding boxes with odd dimensions.

Bug: The function used a "ceil trick" (div(-2, floor).abs()) for integer division, which computed ceil(h/2) instead of matching the float behavior of torchvision.ops.box_convert.

Example:

  • Input: [cx=5, cy=6, w=10, h=13] (CXCYWH, int64)
  • Before: [0, -1, 10, 12]
  • After: [0, 0, 10, 12]

Changes

  1. Fix: Use float arithmetic for integer tensors to match torchvision.ops._box_convert._box_cxcywh_to_xyxy, then convert back to original dtype
  2. Optimization: Avoid double allocation by only cloning when necessary (float conversion already creates a copy)
  3. Test: Added non-regression test with the exact values from the bug report

Fixes #8887

cc @vfdev-5

The _cxcywh_to_xyxy function used an incorrect 'ceil trick' for integer
division that produced negative coordinates for bounding boxes with odd
dimensions. For example, [cx=5, cy=6, w=10, h=13] incorrectly produced
[0, -1, 10, 12] instead of [0, 0, 10, 12].

The fix uses float arithmetic (matching torchvision.ops.box_convert)
and converts back to the original dtype, ensuring correct results for
both integer and floating-point tensors.

Fixes pytorch#8887
@pytorch-bot
Copy link
Copy Markdown

pytorch-bot bot commented Dec 31, 2025

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/vision/9322

Note: Links to docs will display an error until the docs builds have been completed.

✅ You can merge normally! (1 Unrelated Failure)

As of commit f85bb20 with merge base 6940e19 (image):

BROKEN TRUNK - The following job failed but were present on the merge base:

👉 Rebase onto the `viable/strict` branch to avoid these failures

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla
Copy link
Copy Markdown

meta-cla bot commented Dec 31, 2025

Hi @raimbekovm!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla
Copy link
Copy Markdown

meta-cla bot commented Dec 31, 2025

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

Copy link
Copy Markdown
Contributor

@zy1git zy1git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left comments for the test part.

@raimbekovm
Copy link
Copy Markdown
Contributor Author

Thanks for the review! Will update the test name and add the explicit dtype + assertion.

Copy link
Copy Markdown
Contributor

@zy1git zy1git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@raimbekovm Just push a solution which works well for the inplace parameter. Feel free to take a look.


if need_cast:
cxcywh = cxcywh.to(dtype)
if inplace:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part can ensure the inplace parameter works well if inplace is True.

@raimbekovm
Copy link
Copy Markdown
Contributor Author

Thanks @zy1git! I looked through the solution — everything looks correct:

Appreciate your help with this!

Copy link
Copy Markdown
Member

@NicolasHug NicolasHug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @raimbekovm

@zy1git zy1git merged commit 74d1285 into pytorch:main Feb 11, 2026
73 of 80 checks passed
@github-actions
Copy link
Copy Markdown

Hey @zy1git!

You merged this PR, but no labels were added.
The list of valid labels is available at https://github.com/pytorch/vision/blob/main/.github/process_commit.py

raimbekovm added a commit to raimbekovm/vision that referenced this pull request Feb 13, 2026
Use float arithmetic instead of the ceil trick (div(-2, floor).abs_())
to match the fix applied to _cxcywh_to_xyxy in PR pytorch#9322.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect BoundingBoxes format conversion CXCYWH -> XYXY

3 participants