ImFusion SDK 4.3
Marker Detection

Comprehensive guide to marker detection.

+ Collaboration diagram for Marker Detection:

Comprehensive guide to marker detection.

This page provides detailed information and code examples for detecting various types of markers using the MarkerDetection and MarkerConfiguration classes. These tools are essential for computer vision applications such as camera calibration, pose estimation, and augmented reality.

Marker Detection Overview

Marker detection is a fundamental computer vision technique used for camera calibration, pose estimation, and augmented reality applications. The MarkerDetection class provides a unified interface for detecting various types of markers, while the MarkerConfiguration class allows you to configure the specific marker type and parameters.

Applications

Typical Workflow

  1. Configure Marker Type: Set up the appropriate marker configuration
  2. Detect Markers: Process images to find marker corners
  3. Extract Points: Get 2D image points and corresponding 3D object points
  4. Estimate Pose: Calculate camera pose using camera parameters
  5. Validate Results: Check detection quality and pose accuracy

Available Marker Types

The ImFusion SDK supports several marker types, each with different characteristics and use cases:

Chessboard

Charuco Board

ArUco Markers

AprilTag

STag

Circle Board

Basic Marker Detection Usage

Basic Chessboard Detection

The following example demonstrates basic chessboard detection:

#include <ImFusion/Base/SharedImage.h>
#include <ImFusion/Vision/MarkerDetection.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Create marker configuration for chessboard
config.setMarkerType(MarkerConfiguration::Chessboard);
// Configure chessboard parameters
chessboardParams.gridSize = vec2i(9, 7); // 9x7 internal corners
chessboardParams.cellSize = vec2(30, 30); // 30 mm cell size
config.setChessboardParameters(chessboardParams);
// Create marker detector
MarkerDetection detector;
detector.setMarkerConfiguration(config);
// Load and process image
std::unique_ptr<SharedImage> image = loadImage("chessboard.jpg");
bool success = detector.detectMarker(image.get());
if (success) {
// Extract detected points
std::vector<vec3> objectPoints;
std::vector<vec2> imagePoints;
detector.detections(objectPoints, imagePoints);
LOG_INFO("Detected " << imagePoints.size() << " corners");
// Use points for camera calibration or pose estimation
// ...
}
Describes the configuration of a marker calibration target.
Definition MarkerConfiguration.h:17
void setMarkerType(MarkerType type)
Set Marker type.
void setChessboardParameters(const ChessboardInfo &params)
Set Chesssboard parameters.
Generic marker detection class for a wide range of marker types, such as Aruco, Charuco,...
Definition MarkerDetection.h:20
void setMarkerConfiguration(const MarkerConfiguration &markerConfig)
Set marker configuration for the marker detection.
Definition MarkerDetection.h:25
bool detectMarker(const SharedImage *image, SharedImage *detectionImage=nullptr)
Run marker detection on provided image detectionImage is an optional output which must have the same ...
void detections(std::vector< vec3 > &objectPoints, std::vector< vec2 > &imagePoints, std::vector< int > *pointIds=nullptr, std::vector< std::vector< vec2 > > *markerCorners=nullptr, std::vector< int > *markerIds=nullptr) const
Obtain extracted marker parameters.
#define LOG_INFO(...)
Emits a log message of Log::Level::Info, optionally with a category.
Definition Log.h:247
Namespace of the ImFusion SDK.
Definition Assert.h:7
T size(T... args)
Information about a chessboard.
Definition MarkerConfiguration.h:155

Charuco Board Detection

Charuco boards combine the benefits of chessboards and ArUco markers:

#include <ImFusion/Base/SharedImage.h>
#include <ImFusion/Vision/MarkerDetection.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Create marker configuration for Charuco board
config.setMarkerType(MarkerConfiguration::CharucoBoard);
// Configure Charuco board parameters
charucoParams.gridSize = vec2i(9, 7); // 9x7 grid
charucoParams.cellSize = 30.0; // 30 mm cell size
charucoParams.markerSize = 10.0; // 10 mm marker size
charucoParams.dictionary = 0; // ArUco dictionary
charucoParams.minAdjacentMarkers = 2; // Minimum adjacent markers for corner detection
config.setCharucoBoardParameters(charucoParams);
// Create marker detector
MarkerDetection detector;
detector.setMarkerConfiguration(config);
// Enable automatic size hint detection for better performance
// Process image
std::unique_ptr<SharedImage> image = loadImage("charuco_board.jpg");
bool success = detector.detectMarker(image.get());
if (success) {
// Extract detected points and marker information
std::vector<vec3> objectPoints;
std::vector<vec2> imagePoints;
std::vector<int> pointIds;
std::vector<int> markerIds;
detector.detections(objectPoints, imagePoints, &pointIds, &markerCorners, &markerIds);
LOG_INFO("Detected " << imagePoints.size() << " corners");
LOG_INFO("Detected " << markerIds.size() << " markers");
// Use for camera calibration or pose estimation
// ...
}
void setCharucoBoardParameters(const CharucoBoardInfo &params)
Set Charuco parameters.
void setDetectSizeHintAutomatically(bool v)
If set to true and if not all markers were detected during the first time, the marker detection will ...
Definition MarkerDetection.h:90
Information about a Charuco board.
Definition MarkerConfiguration.h:141

ArUco Marker Detection

ArUco markers are ideal for pose estimation and tracking:

#include <ImFusion/Base/SharedImage.h>
#include <ImFusion/Vision/MarkerDetection.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Create marker configuration for ArUco markers
config.setMarkerType(MarkerConfiguration::ArucoMarker);
// Configure ArUco marker parameters
arucoParams.id = 0; // Marker ID to detect
arucoParams.dictionary = 3; // ArUco dictionary
arucoParams.size = 50.0; // 50 mm marker size
arucoParams.T = mat4::Identity(); // Marker pose in world coordinates
config.addArucoMarker(arucoParams);
// Add more markers if needed
arucoParams2.id = 1;
arucoParams2.dictionary = 3;
arucoParams2.size = 50.0;
arucoParams2.T = mat4::Identity();
arucoParams2.T.block<3, 1>(0, 3) = vec3(100.0, 0.0, 0.0); // Translate 100 mm in x direction
config.addArucoMarker(arucoParams2);
// Create marker detector
MarkerDetection detector;
detector.setMarkerConfiguration(config);
// Configure detector parameters for better performance
detectorParams.adaptiveThreshWinSizeMin = 3;
detectorParams.adaptiveThreshWinSizeMax = 23;
detectorParams.minMarkerPerimeterRate = 0.03;
detectorParams.maxMarkerPerimeterRate = 4.0;
detectorParams.cornerRefinementMethod = MarkerConfiguration::DetectorParameters::Subpix;
detectorParams.cornerRefinementWinSize = 5;
// Process image
std::unique_ptr<SharedImage> image = loadImage("aruco_markers.jpg");
bool success = detector.detectMarker(image.get());
if (success) {
// Extract detected markers
std::vector<vec3> objectPoints;
std::vector<vec2> imagePoints;
std::vector<int> pointIds;
std::vector<int> markerIds;
detector.detections(objectPoints, imagePoints, &pointIds, &markerCorners, &markerIds);
LOG_INFO("Detected " << markerIds.size() << " markers");
// Process each detected marker
for (size_t i = 0; i < markerIds.size(); ++i) {
LOG_INFO("Marker ID: " << markerIds[i]);
// Use marker corners for pose estimation
// ...
}
}
void addArucoMarker(const ArucoMarkerInfo &params)
Add Aruco marker with specified parameters.
Information about a single Aruco marker.
Definition MarkerConfiguration.h:99
Detector parameters for Aruco markers, boards and Charuco boards.
Definition MarkerConfiguration.h:38

Pose Estimation

Once markers are detected, you can estimate the camera pose:

#include <ImFusion/Base/SharedImage.h>
#include <ImFusion/Vision/MarkerDetection.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Set up marker detection (using previous examples)
// ... configure marker type and parameters ...
MarkerDetection detector;
detector.setMarkerConfiguration(config);
// Set camera parameters (intrinsic matrix and distortion coefficients)
mat3 K; // Camera intrinsic matrix
vec5 dist; // Distortion coefficients
// ... load or calculate camera parameters ...
detector.setCameraParameters(K, dist);
// Process image
std::unique_ptr<SharedImage> image = loadImage("markers.jpg");
bool success = detector.detectMarker(image.get());
if (success) {
// Estimate camera pose
double reprojectionError;
std::vector<vec2> reprojectedPoints;
mat4 cameraPose = detector.pose(&reprojectionError, &reprojectedPoints);
if (cameraPose != mat4::Zero()) {
LOG_INFO("Camera pose estimated successfully");
LOG_INFO("Reprojection error: " << reprojectionError << " pixels");
// Extract rotation and translation
mat3 rotation = cameraPose.block<3, 3>(0, 0);
vec3 translation = cameraPose.block<3, 1>(0, 3);
LOG_INFO("Translation: [" << translation.x() << ", " << translation.y() << ", " << translation.z() << "]");
// Use pose for augmented reality, robotics, etc.
// ...
} else {
LOG_WARN("Pose estimation failed");
}
}
void setCameraParameters(const mat3 &K, const Eigen::Matrix< double, 5, 1 > &dist)
Set camera parameters.
Definition MarkerDetection.h:52
mat4 pose(double *mre=nullptr, std::vector< vec2 > *reprojectedPoints=nullptr)
Estimate camera pose (i.e.
#define LOG_WARN(...)
Emits a log message of Log::Level::Warning, optionally with a category.
Definition Log.h:252

Marker Generation

The MarkerGenerationAlgorithm class allows you to generate various types of markers for printing and use in calibration or tracking applications.

Basic Marker Generation

Generate a chessboard pattern for camera calibration:

#include <ImFusion/Vision/MarkerGenerationAlgorithm.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Create marker configuration for chessboard
config.setMarkerType(MarkerConfiguration::Chessboard);
// Configure chessboard parameters
chessboardParams.gridSize = vec2i(9, 7); // 9x7 internal corners
chessboardParams.cellSize = vec2(30, 30); // 30 mm cell size
config.setChessboardParameters(chessboardParams);
// Create marker generation algorithm
// Set marker configuration
generator.setMarkerConfig(config);
// Configure generation parameters
generator.p_padding = 50; // 50 pixels padding around the marker
generator.p_dpi = 300; // 300 DPI for high-quality printing
generator.p_outputSVGPath = "chessboard.svg"; // Save as SVG file
// Generate the marker
generator.compute();
Algorithm for creating calibration markers.
Definition MarkerGenerationAlgorithm.h:14
Parameter< std::string > p_outputSVGPath
If set, the generated marker will be saved as SVG to this path.
Definition MarkerGenerationAlgorithm.h:29
Parameter< double > p_dpi
Dots per inch for the marker, used to calculate the size of the marker in pixels.
Definition MarkerGenerationAlgorithm.h:31
Parameter< int > p_padding
Padding in pixels around the marker, useful for printing markers.
Definition MarkerGenerationAlgorithm.h:30
void compute() override
Execute the algorithm.

Charuco Board Generation

Generate a Charuco board for robust calibration:

#include <ImFusion/Vision/MarkerGenerationAlgorithm.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Create marker configuration for Charuco board
config.setMarkerType(MarkerConfiguration::CharucoBoard);
// Configure Charuco board parameters
charucoParams.gridSize = vec2i(9, 7); // 9x7 grid
charucoParams.cellSize = 30.0; // 30 mm cell size
charucoParams.markerSize = 10.0; // 10 mm marker size
charucoParams.dictionary = 0; // ArUco dictionary
charucoParams.minAdjacentMarkers = 2; // Minimum adjacent markers for corner detection
config.setCharucoBoardParameters(charucoParams);
// Create marker generation algorithm
generator.setMarkerConfig(config);
// Configure generation parameters
generator.p_padding = 100; // 100 pixels padding
generator.p_dpi = 600; // 600 DPI for very high quality
generator.p_outputSVGPath = "charuco_board.svg";
// Generate the marker
generator.compute();

Circle Board Generation

Generate a circle board pattern:

#include <ImFusion/Vision/MarkerGenerationAlgorithm.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Create marker configuration for circle board
config.setMarkerType(MarkerConfiguration::CircleBoard);
// Configure circle board parameters
circleParams.gridSize = vec2i(9, 7); // 9x7 grid
circleParams.circleSpacing = 20.0; // 20 mm spacing between circles
circleParams.symmetric = true; // Symmetric pattern
config.setCircleBoardParameters(circleParams);
// Create marker generation algorithm
generator.setMarkerConfig(config);
// Configure generation parameters
generator.p_padding = 75; // 75 pixels padding
generator.p_dpi = 300; // 300 DPI
generator.p_circleDiameter = 8.0; // 8 mm circle diameter
generator.p_outputSVGPath = "circle_board.svg";
// Generate the marker
generator.compute();
void setCircleBoardParameters(const CircleBoardInfo &params)
Set Circle Board parameters.
Parameter< double > p_circleDiameter
0 means automatic diameter based on circle spacing
Definition MarkerGenerationAlgorithm.h:32
Information about a circle board.
Definition MarkerConfiguration.h:163
bool symmetric
Asymmetric grids have an additional line of circles offset by half the circle spacing between every r...
Definition MarkerConfiguration.h:166
double circleSpacing
Spacing between the circle centers.
Definition MarkerConfiguration.h:165

Generation Parameters

The marker generation algorithm provides several parameters to control the output:

DPI and Resolution

Output Formats

Visualization and Debugging

Visualization Example

Create detection visualization for debugging and validation:

#include <ImFusion/Base/SharedImage.h>
#include <ImFusion/Vision/MarkerDetection.h>
#include <ImFusion/Vision/MarkerConfiguration.h>
using namespace ImFusion;
// Set up marker detection
// ... configure marker type and parameters ...
MarkerDetection detector;
detector.setMarkerConfiguration(config);
// Load input image
std::unique_ptr<SharedImage> inputImage = loadImage("markers.jpg");
// Create output image for visualization
auto detectionImage = inputImage->clone();
// Perform detection with visualization
bool success = detector.detectMarker(inputImage.get(), detectionImage.get());
if (success) {
// Save visualization
saveImage(detectionImage.get(), "detection_result.jpg");
// Extract and log detection results
std::vector<vec3> objectPoints;
std::vector<vec2> imagePoints;
std::vector<int> pointIds;
std::vector<int> markerIds;
detector.detections(objectPoints, imagePoints, &pointIds, &markerCorners, &markerIds);
LOG_INFO("Detection Results:");
LOG_INFO(" Total corners detected: " << imagePoints.size());
LOG_INFO(" Total markers detected: " << markerIds.size());
// Log individual marker information
for (size_t i = 0; i < markerIds.size(); ++i) {
LOG_INFO(" Marker " << i << ": ID=" << markerIds[i] << ", Corners=" << markerCorners[i].size());
}
// Log corner information
for (size_t i = 0; i < imagePoints.size(); ++i) {
LOG_INFO(" Corner " << i << ": (" << imagePoints[i].x() << ", " << imagePoints[i].y() << ")");
if (!pointIds.empty()) {
LOG_INFO(" Point ID: " << pointIds[i]);
}
}
}
T empty(T... args)
T get(T... args)

Best Practices

Marker Type Selection Guidelines

Choose the appropriate marker type based on your application:

Camera Calibration

Pose Tracking

Parameter Tuning Guidelines

Size and Scale Parameters

Detection Parameters

Environmental Considerations

Lighting

Motion and Blur

Validation and Quality Control

Reprojection Error

Coverage and Distribution

Troubleshooting

Common Issues and Solutions

No Detection

Poor Detection Accuracy

Slow Performance

False Positives

See also
MarkerDetection class, MarkerConfiguration class
Search Tab / S to search, Esc to close