Transform via Checkerboard

This tutorial demonstrates how to estimate the pose of the checkerboard and transform a point cloud using a 4x4 homogeneous transformation matrix to the checkerboard coordinate system. This sample also saves a YAML file with the transformation matrix.

Tip

If you are using a Zivid One+ Small camera, the checkerboard might be too large for this application. For that case we have Transform via ArUco marker tutorial.

This tutorial uses the point cloud of a checkerboard displayed in the image below.

calibration board 2D image

We can open the original point cloud in Zivid Studio and inspect it.

Note

The original point cloud is also in Sample Data.

Now, we can manually set the Z Range from 540 mm to 735 mm in the Depth view. This allows us to see that there is an angle between the camera and the checkerboard frame.

calibration board in camera coordinate system

First, we load a point cloud of a checkerboard.

Go to source

source

const auto calibrationBoardFile = std::string(ZIVID_SAMPLE_DATA_DIR) + "/CalibrationBoardInCameraOrigin.zdf";
std::cout << "Reading ZDF frame from file: " << calibrationBoardFile << std::endl;
const auto frame = Zivid::Frame(calibrationBoardFile);
auto pointCloud = frame.pointCloud();
Go to source

source

var calibrationBoardFile = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
               + "/Zivid/CalibrationBoardInCameraOrigin.zdf";
Console.WriteLine("Reading ZDF frame from file: " + calibrationBoardFile);
var frame = new Zivid.NET.Frame(calibrationBoardFile);
var pointCloud = frame.PointCloud;

Then we estimate the pose of the checkerboard.

Go to source

source

std::cout << "Detecting and estimating pose of the Zivid checkerboard in the camera frame" << std::endl;
const auto detectionResult = Zivid::Calibration::detectFeaturePoints(frame.pointCloud());
const auto transformCameraToCheckerboard = detectionResult.pose().toMatrix();
std::cout << transformCameraToCheckerboard << std::endl;
Go to source

source

Console.WriteLine("Detecting and estimating pose of the Zivid checkerboard in the camera frame");
var detectionResult = Detector.DetectFeaturePoints(pointCloud);
var transformCameraToCheckerboard = new Zivid.NET.Matrix4x4(detectionResult.Pose().ToMatrix());
Console.WriteLine(transformCameraToCheckerboard);

Before transforming the point cloud, we invert the transformation matrix in order to get the pose of the camera in the checkerboard coordinate system.

Go to source

source

std::cout << "Camera pose in checkerboard frame:" << std::endl;
const auto transformCheckerboardToCamera = transformCameraToCheckerboard.inverse();
std::cout << transformCheckerboardToCamera << std::endl;
Go to source

source

Console.WriteLine("Camera pose in checkerboard frame:");
var transformCheckerboardToCamera = transformCameraToCheckerboard.Inverse();
Console.WriteLine(transformCheckerboardToCamera);

After transforming we save the pose to a YAML file.

Go to source

source

const auto transformFile = "CheckerboardToCameraTransform.yaml";
std::cout << "Saving a YAML file with Inverted checkerboard pose to file: " << transformFile << std::endl;
transformCheckerboardToCamera.save(transformFile);

This is the content of the YAML file:

__version__:
  serializer: 1
  data: 1
FloatMatrix:
  Data: [
    [9.79164362e-01, 4.36628871e-02, 1.98319763e-01, 1.77465611e+01],
    [5.02591990e-02, 8.94120097e-01, -4.44997996e-01, 4.31194275e+02],
    [-1.96751565e-01, 4.45693552e-01, 8.73296201e-01, -5.47788330e+02],
    [0, 0, 0, 1]]

After that, we transform the point cloud to the checkerboard coordinate system.

Go to source

source

std::cout << "Transforming point cloud from camera frame to Checkerboard frame" << std::endl;
pointCloud.transform(transformCheckerboardToCamera);
Go to source

source

Console.WriteLine("Transforming point cloud from camera frame to Checkerboard frame");
pointCloud.Transform(transformCheckerboardToCamera);

Before saving the transformed point cloud, we convert it to an OpenCV 2D image format and draw the coordinate system and display it.

Go to source

source

std::cout << "Converting to OpenCV image format" << std::endl;
const auto bgrImage = pointCloudToColorBGR(pointCloud);
std::cout << "Visualizing checkerboard with coordinate system" << std::endl;
drawCoordinateSystem(frame, transformCameraToCheckerboard, bgrImage);
displayBGR(bgrImage, "Checkerboard transformation frame");

Here we can see the image that will be displayed and we can observe where the coordinate system of the checkerboard is.

checkerboard coordinate system

Lastly we save the transformed point cloud to disk.

Go to source

source

const auto checkerboardTransformedFile = "CalibrationBoardInCheckerboardOrigin.zdf";
std::cout << "Saving transformed point cloud to file: " << checkerboardTransformedFile << std::endl;
frame.save(checkerboardTransformedFile);
Go to source

source

var checkerboardTransformedFile = "CalibrationBoardInCheckerboardOrigin.zdf";
Console.WriteLine("Saving transformed point cloud to file: " + checkerboardTransformedFile);
frame.Save(checkerboardTransformedFile);

Now we can open the transformed point cloud in Zivid Studio and inspect it.

Note

Zoom out in Zivid Studio to find the data because the viewpoint origin is inadequate for transformed point clouds.

We can now manually set the Z Range from -35 mm to 1 mm in the Depth view. This way we can filter out all data except the calibration board and the object located next to it. This allows us to see that we have the same Z value across the calibration board, and from the color gradient we can check that the value is 0. This means that the origin of the point cloud is on the checkerboard.

calibration board in checkerboard coordinate system