Skip to content

fix(rfdetr): honor --show-boxes instead of ignoring it - #2024

Open
Anai-Guo wants to merge 1 commit into
Blaizzy:mainfrom
Anai-Guo:fix-rfdetr-show-boxes
Open

fix(rfdetr): honor --show-boxes instead of ignoring it#2024
Anai-Guo wants to merge 1 commit into
Blaizzy:mainfrom
Anai-Guo:fix-rfdetr-show-boxes

Conversation

@Anai-Guo

Copy link
Copy Markdown
Contributor

Problem

The RF-DETR CLI declares --show-boxes with help="Show bounding boxes and labels (default: on)", but the parsed value is never used. show_boxes as an identifier appears nowhere in mlx_vlm/models/rfdetr/ outside that one add_argument call:

$ grep -rn "show_boxes" mlx_vlm/models/rfdetr/
$          # (no output — only the "--show-boxes" string literal exists)

Two things are wrong, and the file itself supplies the baseline for both:

  1. The value never reaches the annotator. The adjacent --show-fps flag in the very same parser is threaded through (predict_video(..., show_fps=args.show_fps) at generate.py:802). Both sibling backends honor show_boxes too — sam3/generate.py passes args.show_boxes into three call sites, and sam3_1/generate.py threads it down to draw_frame.

  2. The flag could not be turned off even once wired up. It is action="store_true" with default=True, so passing --show-boxes is a no-op and there is no way to get boxes off. sam3_1/generate.py:1002-1003 pairs exactly this flag with a --no-show-boxes dual; the RF-DETR parser only has the positive half.

Net effect: a user following the documented (default: on) wording has no way to render mask-only segment output, which is the one thing the option exists for.

Fix

  • _get_annotator() takes show_boxes: bool = True. When it is off, the default segment chain keeps MaskAnnotator and drops BoxAnnotator/LabelAnnotator — the same meaning sam3/generate.py documents for draw_frame: "If False, draw only mask overlays + contours (no boxes/labels)."
  • A detect chain contains nothing but boxes and labels, so it keeps them regardless. This mirrors sam3's show_boxes=args.show_boxes if args.task == "segment" else True, and avoids rendering an empty overlay.
  • An explicit --annotator chain still wins, since it names the annotators outright.
  • Added --no-show-boxes (dest="show_boxes", action="store_false"), matching sam3_1/generate.py.

The default path is unchanged. With show_boxes=True the chain is the same MaskAnnotator + BoxAnnotator + LabelAnnotator as before, and the two internal _get_annotator(None, ...) calls in predict_video/predict_realtime keep the default.

Verification

mlx is Apple-silicon only, so I exercised the real module on another platform by stubbing mlx alone and importing mlx_vlm/models/rfdetr/generate.py unmodified — sam3/annotators.py is numpy+cv2 only, so the annotator chain under test is the real one, not a mock.

Before the change (3 of the 4 new tests fail):

FAILED test_rfdetr_show_boxes.py::test_segment_chain_drops_boxes_and_labels_when_show_boxes_is_off
FAILED test_rfdetr_show_boxes.py::test_detect_keeps_boxes_because_nothing_else_is_drawn
FAILED test_rfdetr_show_boxes.py::test_cli_can_turn_boxes_off - SystemExit: 2
   __main__.py: error: unrecognized arguments: --no-show-boxes
3 failed, 1 passed

After: 4 passed.

test_show_boxes_defaults_to_on is the one that passes on both sides — it pins the unchanged default chain so this stays a no-op for existing invocations.

Observed chains:

task show_boxes annotator chain
segment True (default) MaskAnnotator, BoxAnnotator, LabelAnnotator
segment False MaskAnnotator
detect either BoxAnnotator, LabelAnnotator

black==26.3.1, isort==5.13.2 and autoflake==2.2.1 (the pinned .pre-commit-config.yaml revisions) leave both files unchanged.

Not in scope

sam3/generate.py declares --show-boxes without default=True, so it defaults to off there and is already honored — I left its semantics alone rather than unifying the two defaults, since that would change existing sam3 output.

🤖 Generated with Claude Code

@Anai-Guo

Copy link
Copy Markdown
Contributor Author

The red test job is not caused by this PR. All 4 failures are the MRoPE mx.split() signature change:

tests/test_rope_utils.py::test_sectioned_precomputed_rotary_fast_path_matches_fallback[sectioned_half_split]
tests/test_rope_utils.py::test_sectioned_precomputed_rotary_fast_path_matches_fallback[sectioned_even_odd]
tests/test_models.py::TestMRoPETrainingVJP::test_precomputed_rotary_vjp_matches_pure_mlx  (2 subcases)

TypeError: split(): incompatible function arguments.
  Invoked with types: mlx.core.array, mlx.core.array, kwargs = { axis: int }

models/rope_utils.py:1364 passes split_indices as an mx.array, which recent mlx no longer accepts. Unrelated branches hit the same two test ids in the same window — e.g. runs 32888401433 (feature/model-registry) and 32916522886 (dev-deepseek-v4-speculative-chunked-prefill) — and the fix-mrope-split-mlx-0322 branch is green, so this looks already handled elsewhere.

This PR touches only models/rfdetr/generate.py and adds tests/test_rfdetr_show_boxes.py; the run reports 4 failed, 2581 passed with the 4 new tests among the passing set. I have not re-triggered the job, since re-running would not change the outcome.

@lucasnewman lucasnewman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks!

@lucasnewman

Copy link
Copy Markdown
Collaborator

@Anai-Guo Need signed commits

@Anai-Guo Anai-Guo closed this Aug 27, 2026
The rfdetr generate CLI parsed --show-boxes but never passed it down, so boxes were always drawn.

Re-created as a single GPG-signed commit; tree is unchanged.
@Anai-Guo
Anai-Guo force-pushed the fix-rfdetr-show-boxes branch from c574cb6 to e82d557 Compare August 27, 2026 07:34
@Anai-Guo Anai-Guo reopened this Aug 27, 2026
@Anai-Guo

Copy link
Copy Markdown
Contributor Author

Also re-signed this one while I was at it (single GPG-signed commit, verified: true, tree unchanged). The reopen notification is just the force-push side effect.

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.

2 participants