Transform via ArUco marker

이 튜토리얼은 ArUco 마커의 포즈를 추정하고 4x4 Homogeneous transformation matrix를 사용하여 포인트 클라우드를 ArUco 마커 좌표계로 변환하는 방법을 보여줍니다.

Zivid calibration board 에는 ArUco 마커가 포함되어 있습니다.

이 튜토리얼은 아래 이미지에 표시된 ArUco 마커의 포인트 클라우드를 사용합니다.

ArUco marker 2D image

Zivid Studio에서 original point cloud 를 열 수 있습니다. 그리고 포인트 클라우드를 확인하십시오.

참고

포인트 클라우드 원본은 Sample Data 에서 다운로드 가능합니다.

이제 깊이 보기에서 Z 범위를 540mm에서 735mm로 수동으로 설정할 수 있습니다. 이를 통해 마커가 약 570mm 거리에 있고 카메라와 마커 프레임 사이에 각도가 있음을 알 수 있습니다.

카메라 좌표계에서의 ArUco 마커

먼저 ArUco 마커의 포인트 클라우드를 로드합니다.

소스로 이동

소스

const auto arucoMarkerFile = std::string(ZIVID_SAMPLE_DATA_DIR) + "/CalibrationBoardInCameraOrigin.zdf";
std::cout << "Reading ZDF frame from file: " << arucoMarkerFile << std::endl;
const auto frame = Zivid::Frame(arucoMarkerFile);
auto pointCloud = frame.pointCloud();
소스로 이동

소스

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

using (var frame = new Zivid.NET.Frame(calibrationBoardFile))
{
    var pointCloud = frame.PointCloud;
소스로 이동

소스

data_file = get_sample_data_path() / "CalibrationBoardInCameraOrigin.zdf"
print(f"Reading ZDF frame from file: {data_file}")

frame = zivid.Frame(data_file)
point_cloud = frame.point_cloud()

그런 다음 ArUco 마커를 구성합니다.

소스로 이동

소스

std::cout << "Configuring ArUco marker" << std::endl;
const auto markerDictionary = Zivid::Calibration::MarkerDictionary::aruco4x4_50;
std::vector<int> markerId = { 1 };
소스로 이동

소스

Console.WriteLine("Configuring ArUco marker");
var markerDictionary = Zivid.NET.MarkerDictionary.Aruco4x4_50;
var markerId = new List<int> { 1 };
소스로 이동

소스

print("Configuring ArUco marker")
marker_dictionary = zivid.calibration.MarkerDictionary.aruco4x4_50
marker_id = [1]

그런 다음 ArUco 마커를 감지합니다.

소스로 이동

소스

std::cout << "Detecting ArUco marker" << std::endl;
const auto detectionResult = Zivid::Calibration::detectMarkers(frame, markerId, markerDictionary);
소스로 이동

소스

Console.WriteLine("Detecting ArUco marker");
var detectionResult = Detector.DetectMarkers(frame, markerId, markerDictionary);
소스로 이동

소스

print("Detecting ArUco marker")
detection_result = zivid.calibration.detect_markers(frame, marker_id, marker_dictionary)

ArUco 마커의 포즈를 추정합니다.

소스로 이동

소스

std::cout << "Estimating pose of detected ArUco marker" << std::endl;
const auto transformCameraToMarker = detectionResult.detectedMarkers()[0].pose().toMatrix();
소스로 이동

소스

Console.WriteLine("Estimating pose of detected ArUco marker");
var cameraToMarkerTransform = new Zivid.NET.Matrix4x4(detectionResult.DetectedMarkers()[0].Pose().ToMatrix());
소스로 이동

소스

print("Estimating pose of detected ArUco marker")
transform_camera_to_marker = detection_result.detected_markers()[0].pose.to_matrix()

포인트 클라우드를 변환하기 전에 변환 행렬을 반전하여 ArUco 마커 좌표계에서 카메라의 포즈를 구합니다.

소스로 이동

소스

std::cout << "Camera pose in ArUco marker frame:" << std::endl;
const auto markerToCameraTransform = transformCameraToMarker.inverse();
소스로 이동

소스

Console.WriteLine("Camera pose in ArUco marker frame:");
var markerToCameraTransform = cameraToMarkerTransform.Inverse();
소스로 이동

소스

print("Camera pose in ArUco marker frame:")
transform_marker_to_camera = np.linalg.inv(transform_camera_to_marker)

변환 후 포즈를 YAML 파일로 저장합니다.

소스로 이동

소스

const auto transformFile = "ArUcoMarkerToCameraTransform.yaml";
std::cout << "Saving a YAML file with Inverted ArUco marker pose to file: " << transformFile << std::endl;
markerToCameraTransform.save(transformFile);
소스로 이동

소스

var transformFile = "ArUcoMarkerToCameraTransform.yaml";
Console.WriteLine("Saving a YAML file with Inverted ArUco marker pose to file: " + transformFile);
markerToCameraTransform.Save(transformFile);
소스로 이동

소스

transform_file = Path("ArUcoMarkerToCameraTransform.yaml")
print("Saving a YAML file with Inverted ArUco marker pose to file: ")
assert_affine_matrix_and_save(transform_marker_to_camera, transform_file)

YAML 파일의 내용은 다음과 같습니다.

__version__:
    serializer: 1
    data: 1
FloatMatrix:
    Data:
        [
            [0.978564, 0.0506282, 0.1996225, 21.54072],
            [-0.04527659, -0.892707, 0.4483572, -208.0268],
            [0.2009039, -0.4477845, -0.8712788, 547.6984],

그 후, 포인트 클라우드를 ArUco 마커 좌표계로 변환합니다.

소스로 이동

소스

std::cout << "Transforming point cloud from camera frame to ArUco marker frame" << std::endl;
pointCloud.transform(markerToCameraTransform);
소스로 이동

소스

Console.WriteLine("Transforming point cloud from camera frame to ArUco marker frame");
pointCloud.Transform(markerToCameraTransform);
소스로 이동

소스

print("Transforming point cloud from camera frame to ArUco marker frame")
point_cloud.transform(transform_marker_to_camera)

변환된 포인트 클라우드를 저장하기 전에 OpenCV 2D 이미지 형식으로 변환하고 감지된 ArUco 마커를 그릴 수 있습니다.

소스로 이동

소스

std::cout << "Converting to OpenCV image format" << std::endl;
const auto bgraImage = pointCloudToColorBGRA_SRGB(pointCloud);
std::cout << "Displaying detected ArUco marker" << std::endl;
const auto bgr = drawDetectedMarker(bgraImage, detectionResult);
displayBGR(bgr, "ArucoMarkerDetected");
소스로 이동

소스

print("Converting to OpenCV image format")
bgra_image = point_cloud.copy_data("bgra")
print("Displaying detected ArUco marker")
bgr = _draw_detected_marker(bgra_image, detection_result)
display_bgr(bgr, "ArucoMarkerDetected")

여기서 우리는 표시될 이미지를 볼 수 있고, 체커보드의 좌표계가 어디에 있는지 관찰할 수 있습니다.

aruco marker

마지막으로 변환된 포인트 클라우드를 디스크에 저장합니다.

소스로 이동

소스

const auto arucoMarkerTransformedFile = "CalibrationBoardInArucoMarkerOrigin.zdf";
std::cout << "Saving transformed point cloud to file: " << arucoMarkerTransformedFile << std::endl;
frame.save(arucoMarkerTransformedFile);
소스로 이동

소스

var arucoMarkerTransformedFile = "CalibrationBoardInArucoMarkerOrigin.zdf";
Console.WriteLine("Saving transformed point cloud to file: " + arucoMarkerTransformedFile);
frame.Save(arucoMarkerTransformedFile);
소스로 이동

소스

aruco_marker_transformed_file = "CalibrationBoardInArucoMarkerOrigin.zdf"
print(f"Saving transformed point cloud to file: {aruco_marker_transformed_file}")
frame.save(aruco_marker_transformed_file)

힌트

자세한 내용은 Position, Orientation and Coordinate Transformations 에서 확인 가능합니다.

이제 Zivid Studio에서 transformed point cloud 를 열 수 있습니다. 그리고 포인트 클라우드를 확인하십시오.

참고

변환된 포인트 클라우드에는 시점 원점이 부적합하므로 Zivid Studio에서 축소하여 데이터를 찾습니다.

이제 깊이 보기에서 Z 범위를 -35mm에서 1mm로 수동으로 설정할 수 있습니다. 이렇게 하면 칼리브레이션 보드와 그 옆에 있는 개체를 제외한 모든 데이터를 필터링할 수 있습니다. 이를 통해 칼리브레이션 보드 전체에 동일한 Z 값이 있음을 알 수 있으며 색상 그라디언트에서 값이 0인지 확인할 수 있습니다. 이는 포인트 클라우드의 원점이 ArUco 마커에 있음을 의미합니다.

카메라 좌표계에서의 ArUco 마커

포인트 클라우드를 ArUco 마커 좌표계로 변환하려면 코드 샘플을 실행하세요.

Sample: TransformPointCloudViaArucoMarker.cpp

./TransformPointCloudViaArucoMarker

Sample: TransformPointCloudViaArucoMarker.cs

./TransformPointCloudViaArucoMarker

Sample: transform_point_cloud_via_aruco_marker.py

python transform_point_cloud_via_aruco_marker.py

이것을 자신의 설정에 사용하려면 코드 샘플을 수정하세요.

  1. ZDF 파일을 실제 카메라와 설정으로 바꾸세요.

  2. 장면에 ArUco 마커를 놓습니다.

  3. 샘플을 실행해 보세요!