Main Content

readArucoMarker

Detect and estimate pose for ArUco marker in image

Since R2024a

Description

example

[id,loc] = readArucoMarker(I) detects ArUco markers in the input image I, and returns the locations and IDs associated with the markers.

[id,loc] = readArucoMarker(I,markerFamily) detects ArUco markers of only the specified families, markerFamily.

[id,loc,pose] = readArucoMarker(___,intrinsics,markerSize) returns the poses of the markers with respect to the specified camera intrinsic parameters, intrinsics, and size of the markers, markerSize, in addition to any combination of input arguments from previous syntaxes.

example

[___,detectedFamily,rejections] = readArucoMarker(___) returns the recognized ArUco marker families, detectedFamily, and the xy-locations of rejected ArUco marker candidates, rejections, in addition to any combination of arguments from previous syntaxes.

[___] = readArucoMarker(___,Name=Value) specifies options using one or more name-value arguments. For example, WindowSizeStep=12 sets the number of pixels by which to increment the window size during adaptive thresholding to 12.

Examples

collapse all

Read an image into the workspace.

I = imread("ArUcoMarkersMulti.jpg");

Read the ArUco markers in the image to get their IDs, pixel locations, and marker families.

[ids,locs,detectedFamily] = readArucoMarker(I);

Overlay the marker edges, corners, and IDs on the image for visualization.

numMarkers = length(ids);
for i = 1:numMarkers
  loc = locs(:,:,i);
   
  % Display the marker ID and family
  disp("Detected marker ID, Family: " + ids(i) + ", " + detectedFamily(i))  
 
  % Insert marker edges
  I = insertShape(I,"polygon",{loc},Opacity=1,ShapeColor="green",LineWidth=4);
 
  % Insert marker corners
  markerRadius = 6;
  numCorners = size(loc,1);
  markerPosition = [loc,repmat(markerRadius,numCorners,1)];
  I = insertShape(I,"FilledCircle",markerPosition,ShapeColor="red",Opacity=1);
   
  % Insert marker IDs
  center = mean(loc);
  I = insertText(I,center,ids(i),FontSize=30,BoxOpacity=1);
end
Detected marker ID, Family: 3, DICT_4X4_1000
Detected marker ID, Family: 34, DICT_5X5_1000
Detected marker ID, Family: 84, DICT_6X6_1000
Detected marker ID, Family: 264, DICT_7X7_1000
Detected marker ID, Family: 879, DICT_ARUCO_ORIGINAL

Display the results.

imshow(I)

Read an image that contains ArUco markers into the workspace.

I = imread("ArUcoBoard.jpg");

Load intrinsics of the camera that captured the image.

data = load("camIntrinsicsArucoBoard.mat");
intrinsics = data.intrinsics;

Undistort the image and display it.

[I,camIntrinsics] = undistortFisheyeImage(I,intrinsics);
imshow(I)

Measure the marker size in millimeters.

markerSizeInMM = 25.4;

Specify the marker family for faster performance of readArucoMarker function.

markerFamily = "DICT_6X6_250";

Estimate marker poses.

[ids,locs,poses] = readArucoMarker(I,markerFamily,camIntrinsics,markerSizeInMM);

Overlay estimated poses on the image for visualization.

% Origin and axes vectors for the object coordinate system
worldPoints = [0 0 0; markerSizeInMM/2 0 0; 0 markerSizeInMM/2 0; 0 0 markerSizeInMM/2];

for i = 1:length(poses)
  % Get image coordinates for axes
  imagePoints = world2img(worldPoints,poses(i),camIntrinsics);
 
  axesPoints = [imagePoints(1,:) imagePoints(2,:);
                imagePoints(1,:) imagePoints(3,:);
                imagePoints(1,:) imagePoints(4,:)];
  % Draw colored axes
  I = insertShape(I, "Line", axesPoints, ...
      Color = ["red","green","blue"], LineWidth=10);
end

Display the results.

imshow(I)

Input Arguments

collapse all

Input image, specified as an M-by-N-by-3 truecolor image or an M-by-N grayscale image. The input image must be undistorted.

Data Types: single | double | int16 | uint8 | uint16

ArUco marker families, specified as a character vector, string scalar, vector of strings, or cell array of character vectors. Each element must be one of the valid ArUco marker families listed in the table. Specifying a family can reduce the run time of the function by restricting its search. Use this argument to improve the execution time when you know the marker family in the image. Be default, the function searches for:

[ "DICT_ARUCO_ORIGINAL","DICT_4X4_1000","DICT_5X5_1000","DICT_6X6_1000", "DICT_7X7_1000"].

FamilyMarker Size (bits)Number of Markers in FamilyMinimum Hamming Distance Between Markers (bits)
"DICT_ARUCO_ORIGINAL"5-by-510243
"DICT_4X4_50"4-by-4504
"DICT_4X4_100"1003
"DICT_4X4_250"2502
"DICT_4X4_1000"10002
"DICT_5X5_50"5-by-5508
"DICT_5X5_100"1007
"DICT_5X5_250"2506
"DICT_5X5_1000"10005
"DICT_6X6_50"6-by-65013
"DICT_6X6_100"10012
"DICT_6X6_250"25011
"DICT_6X6_1000"10009
"DICT_7X7_50"7-by-75019
"DICT_7X7_100"25018
"DICT_7X7_250"25017
"DICT_7X7_1000"100014

Data Types: char | string | cell

Camera intrinsic parameters, specified as a cameraIntrinsics object.

Size of the marker in world units (such as millimeters), specified as a positive scalar. The function defines the size of the markers as the length of one side of the square marker.

Name-Value Arguments

Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the argument name and Value is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Example: readArucoMarker(I,WindowSizeStep=12) sets the number of pixels by which to increment the window size during adaptive thresholding to 12.

Adaptive Thresholding Arguments

collapse all

Window size range, in pixels, specified as a two-element vector of the form [min max]. The elements set the minimum and maximum size, respectively, for the windows used for adaptive thresholding. Each value n in the range represents an n-by-n square window. Each element of this argument must be a positive integer greater than or equal to 3. The function determines the local window threshold by calculating the average pixel value obtained from the sum of its surrounding pixels. Increase the max value when using ArUco markers that are larger than 400-by-400 pixels.

Window step size, in pixels, specified as a positive integer. The function uses the window step size for adaptive thresholding, but stays within the range set by the WindowSizeRange argument. The function starts at the minimum size of the range, and then increments the window size by the value of WindowSizeStep, until it reaches the maximum range value. If the window size is too small and a marker is large, the function might not detect that marker. This can occur when the window overlaps with the marker border. If the window size is large and a marker is small, the function might detect the marker, but the difference in size can negatively impact processing speed.

Contour Filtering Arguments

collapse all

Range for marker boundary perimeter length, specified as a two-element vector of the form [min max]. The elements set the minimum and maximum size for the perimeter length of detected markers. Specify each element as a value normalized to the maximum dimension of the image. Reduce the range if a rejected marker completely encloses a valid marker.

Maximum polygonal approximation error, specified as a positive scalar. The function utilizes the Douglas-Peucker algorithm to apply a polygonal approximation to each marker candidate, accepting only those that closely resemble a square shape. The value of the SquarenessTolerance is relative to the candidate marker length (in pixels). Decrease this value to filter false corner detections in occluded markers. Increase this value to detect marker candidates in highly distorted images.

Bit Extraction Arguments

collapse all

Number of border bits in the marker, specified as a positive integer. By default, the marker boundary contains one bit. If the function does not detect a marker candidate, first ensure that you have correctly set the markerFamily, then follow one of these two steps:

  • If you used the generateArucoMarker function to generate the marker image, then ensure this name-value argument value is set to the same value as NumBorderBits of the generateArucoMarker function.

  • If you did not use the generateArucoMarker function, then check the ArUco marker manufacturer manual to get the correct value for the number of border bits to use.

Resolution of the decoder to use in the bit extraction step, in pixels, specified as a positive integer. This value sets the number of pixels, per bit, to use in the obtained image after correcting perspective distortion. Increase this value to improve the accuracy with which the function reads marker IDs at the expense of runtime speed.

Subpixel Corner Refinement Arguments

collapse all

Subpixel refinement process, specified as a logical 1(true) or 0(false). Set this value to true to enable the subpixel refinement process for the detected marker corner locations. This step is computationally expensive. Enable this process only if the corner locations must be accurate for pose estimation or for camera calibration applications.

Window size of the subpixel refinement process, in pixels, specified as a positive integer. Increasing this value can cause the window area to include a corner of the image. As a result of this proximity, marker corners might move to an incorrect locations.

Maximum number of iterations the subpixel refinement process, specified as a positive integer. The process stops after the specified number of iterations even if it has not achieved the termination tolerance RefinementTolerance.

Termination tolerance, specified as a positive scalar.

Output Arguments

collapse all

Marker IDs, returned as an N-element vector of positive integers.

Locations of the detected markers in the image, returned as a 4-by-2-by-N array. The array contains the xy-locations of the four corners for each detected marker. N is the number of detected markers.

Poses of markers with respect to the camera, returned as an array of rigidtform3d objects. Each object encapsulates the 3-D rigid transformation of a marker in the same world units as the markerSize input argument. The origin of each marker frame is located at the center of the corresponding marker. The planar surface on which the ArUco marker sits defines the XY-plane of the marker frame with the Z-axis pointing out of the marker.

Detected ArUco marker families, returned as a vector of strings.

Locations of the rejected ArUco marker candidates, returned as a 4-by-2-by-P array. The array contains the xy-locations for the four corners of each rejected marker candidate. P is the number of rejected marker candidates.

Tips

  • This function does not account for lens distortion during pose estimation. To estimate poses, the input image must be undistorted. To estimate poses with a camera that has been calibrated using the Scaramuzza model, you can use the virtual pinhole model returned by the undistortFisheyeImage function.

  • Consider the number of markers your application requires, marker length, and Hamming distance when choosing a marker family. The minimum Hamming distance between markers in the same family determines how capable the function is of detecting them and correcting errors. Smaller marker families, in terms of the number of markers in the family, and marker families with more bits have a larger minimum Hamming distance, but the additional bits to extract can make marker detection more difficult. For example, if your application only requires 10 markers, you can use a family of 10 markers for increased error robustness over a family of 1000 markers. In summary:

    • The fewer bits used to encode the ID in the ArUco marker, the greater the distance from the camera that you can detect the marker. The marker family name specifies the number of bits (for example, DICT_4X4_50 has a marker size of 4-by-4, totaling 16 bits).

    • Refer to the full list of ArUco family markers, specified in the markerFamily argument description.

  • Use one or more of these debugging tips:

    • Include a white border (also called a quiet zone) around ArUco markers for proper identification and decoding.

    • The function does not detect markers if the images have been flipped vertically or horizontally.

    • The function does not detect markers if their square shape has been altered as a result of lens distortion. You can undistort images to improve marker detection.

    • If the function does not detect a marker image, and does not return it as a rejected marker candidate, you might need to modify the adaptive thresholding steps. You can do this by adjusting the WindowSizeRange and WindowSizeStep values.

    • If the function does not detect a marker image, but returns it as a rejected candidate, verify or adjust the markerFamily and NumBorderBits values. Also, verify that the image has not been flipped vertically or horizontally.

    • If a detected or rejected marker incorrectly encompasses any surrounding black borders, adjust the MarkerSizeRange value.

    • If the function returns an incorrect marker ID, or if it detects the same marker using two different marker families, increase the ResolutionPerBit value.

Algorithms

When the detection process starts, the function binarizes the input image using adaptive thresholding at different neighborhood window sizes. The function extracts marker rejections on each of the binarized images.

The marker detection algorithm uses these steps:

  1. Perform adaptive thresholding to binarize the image.

  2. Extract and filter contours to detect square-shaped marker candidates.

  3. Remove perspective distortion and extract marker bits to analyze the inner codification of the marker bits.

  4. Perform error correction to identify valid markers.

  5. Optionally, perform subpixel refinement of corner positions.

Version History

Introduced in R2024a