Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation Error when Creating Charuco Board with Custom Ids

My intention is to create a charuco board object, which supports custom ids. Here is the code snippet being used.

def __init__(self, squaresX=11, squaresY=8, squareLength=0.015, markerLength=0.011,
                 dict=cv2.aruco.DICT_5X5_250, start_id=0):

        self.squaresX = squaresX
        self.squaresY = squaresY
        self.squareLength = squareLength
        self.markerLength = markerLength

        self.aruco_dict = cv2.aruco.getPredefinedDictionary(dict)
        self.start_id = start_id

        num_markers_x = squaresX - 1
        num_markers_y = squaresY - 1
        num_markers = num_markers_x * num_markers_y

        if start_id + num_markers > self.aruco_dict.bytesList.shape[0]:
            raise ValueError(f"Not enough markers in dictionary for board (required: {num_markers})")

        marker_ids = np.arange(start_id, start_id + num_markers, dtype=np.int32).reshape(num_markers_y, num_markers_x)

        self.board = cv2.aruco.CharucoBoard(
            (self.squaresX, self.squaresY),
            self.squareLength,
            self.markerLength,
            self.aruco_dict,
            marker_ids
        )

However when I create self.board, there is a segmentation error (keep in mind when I'm creating the object, I'm using the same arguments as the default arguments to the __init__ method.

cv2.__version__ returns 4.11.0

like image 695
Tommy Llewellyn Avatar asked Dec 14 '25 03:12

Tommy Llewellyn


1 Answers

The problem seems to be: You are providing way too many marker_ids. ChArUco uses one marker per white chessboard square, as is also mentioned in its OpenCV documentation:

ChArUco board is a planar chessboard where the markers are placed inside the white squares of a chessboard.

The pattern you currently seem to employ is: one ID per square corner inside the board (as a 2-d array). The pattern you actually need is: exactly as many marker_ids as there are white squares in the chessboard of the given square count (as a 1-d array).

The following code works for me – it basically fixes the creation of the marker_ids array:

import cv2
import numpy as np

squaresX = 11
squaresY = 8
squareLength = 0.015
markerLength = 0.011
dct = cv2.aruco.DICT_5X5_250
start_id = 0

num_white_squares = (squaresX * squaresY) // 2
marker_ids = np.arange(start_id, start_id + num_white_squares)

board = cv2.aruco.CharucoBoard(
    (squaresX, squaresY),
    squareLength,
    markerLength,
    cv2.aruco.getPredefinedDictionary(dct),
    marker_ids
)
board_image = board.generateImage((1000, 1000), None, 0, 1)

cv2.imshow("charuco", board_image)
cv2.waitKey(0)

This produces (OpenCV 4.12.0): resulting ChArUco board

Using floor/integer division (//) in num_white_squares's calculation seems to be the correct approach:

  • For even-numbered square counts (i.e. with squaresX, squaresY, or both being even), there are always exactly as many black squares as there are white squares. This is reflected by the integer division, which will produce the same result as a regular division in this case.
  • For odd-numbered square counts (i.e. with both squaresX and squaresY being odd), ChArUco boards always seem to have black corners (I tried it with various combinations of values for squaresX and squaresY, and both with the current and the legacy pattern, as chosen by setLegacyPattern()), so the number of white squares will be one less than the number of black squares. This is again reflected by the integer division, which will round down the result in this case.

Side note: I would not use dict as a variable name (I replaced it with dct in my code), as it shadows the name of the built-in dictionary type dict.

like image 185
simon Avatar answered Dec 15 '25 15:12

simon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!