Skip to content

fix: prevent crashes when previewing dense ChArUco boards#979

Merged
mprib merged 5 commits into
mainfrom
fix/charuco-dense-board-preview
May 29, 2026
Merged

fix: prevent crashes when previewing dense ChArUco boards#979
mprib merged 5 commits into
mainfrom
fix/charuco-dense-board-preview

Conversation

@mprib
Copy link
Copy Markdown
Owner

@mprib mprib commented May 29, 2026

Closes #978.

A dense ChArUco board (many squares, or a small dictionary pool) crashed the board preview. There were two separate crashes that looked alike.

What was wrong

  1. Render resolution. OpenCV's generateImage refuses to draw the board at certain output sizes, and which sizes fail is hard to predict, so there is no single safe size to pick. This is the crash the issue reporter hit.
  2. Dictionary capacity. A board can need more ArUco markers than its dictionary pool holds, which crashes the render at any size. The reporter's board did not hit this (238 markers under a 250 pool), but a denser board would.

The fix

  • board_img renders at the requested size and, if OpenCV rejects it, nudges the size up a pixel and retries until it works, with a bounded retry count.
  • The preview now renders high and downscales with INTER_AREA for a cleaner thumbnail.
  • The dictionary pool auto-fits to the smallest nested pool that covers the board, applied when a board is saved or loaded, so a hand-edited config is corrected on open and an edited board is corrected on save.
  • A board that needs more markers than any pool in its family can hold raises a DictionaryCapacityError. In the GUI this never persists or displays a broken board: the spinboxes revert to the last valid board with a warning dialog.

Testing

Ten tests in tests/test_charuco.py cover the render retry across known failure sizes, the pool auto-fit (grow, shrink, no-op, passthrough, over-capacity), persistence round-trips, and the project-open repro through the real repository-to-preview path. basedpyright and ruff are clean on the changed files.

mprib added 5 commits May 29, 2026 12:30
A board with many squares could crash the preview in two separate ways.

First, OpenCV refuses to draw the board at certain output sizes, and
which sizes fail is hard to predict, so picking one fixed size is not
safe. The board now renders at the requested size and, if OpenCV rejects
it, bumps the size up by a pixel and tries again until it works.

Second, a board can need more markers than its dictionary holds, which
also crashes the render. The dictionary now resizes itself to the
smallest one that still covers the board, applied whenever the board is
saved or loaded. If a board needs more markers than any dictionary in
the family can hold, the GUI warns and reverts to the last valid board
instead of crashing.
The preview test converts a rendered board to a QPixmap, which is
screen-backed. On headless CI runners without a window server the native
platform plugin returns a null pixmap, so the test failed on macOS. The
offscreen plugin has a raster backend that works headlessly on every
platform; setting it before any QApplication is created fixes the false
negative while keeping the test exercising the real preview path.
The offscreen-platform approach didn't hold: with loadfile distribution a
worker creates a QApplication for an earlier GUI test before this module is
imported, so setting the platform here came too late and macOS still produced
a null pixmap.

The #978 crash was an exception in the preview path, so a clean return is the
real regression guard. QPixmap is screen-backed and comes back null on headless
runners, which is not the bug under test, so this no longer asserts on its
contents. That the render produces real pixels is already covered at the domain
level by the hand-edited-board test that calls board_img directly.
The test drove the preview's QPixmap conversion, but a QPixmap is backed by
the windowing system and comes back empty on headless CI runners, so it
failed on macOS for an environment reason rather than a real defect. The only
honest assertion left would have been "the call did not raise," which is weak
enough to read as coverage theater.

The #978 crash itself lived in board_img and the dictionary fit, and both are
still covered by the domain tests. What this test uniquely touched was the
display-only conversion glue, which is not worth a windowing dependency in CI.
@mprib mprib merged commit 70700fe into main May 29, 2026
3 checks passed
@mprib mprib deleted the fix/charuco-dense-board-preview branch June 2, 2026 16:50
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.

GUI issue: cv2.error in generateImageMarker when generating UI preview for large ChArUco boards

1 participant