ROI Box via ArUco Marker

This tutorial demonstrates how to find the ROI box parameters using an ArUco marker and how to filter the contents of a bin using it. We are here using the ArUco marker on the Zivid calibration board (7x8 30mm, 300x300mm), and assume the calibration board is placed in the bottom right corner of the bin. The bin size is also assumed known and is used to set the dimensions of the ROI box. This way you can automatically find the ROI parameters in the camera frame.

참고

이 튜토리얼은 데모를 위해 아래 이미지의 장면에 파일 카메라를 사용합니다.

ROI 상자 필터링은 캡처 시간을 줄여줍니다.

카메라 파일은 Sample Data 에서 다운로드할 수 있습니다.

먼저 ArUco 마커가 있는 포인트 클라우드를 캡처합니다.

소스로 이동

source

const auto fileCamera = std::string(ZIVID_SAMPLE_DATA_DIR) + "/BinWithCalibrationBoard.zdf";
const auto loadedFrameWithDiagnostics = Zivid::Frame(fileCamera);

std::cout << "Creating virtual camera using file: " << fileCamera << std::endl;
auto camera = zivid.createFileCamera(loadedFrameWithDiagnostics);

auto settings = loadedFrameWithDiagnostics.settings();

const auto originalFrame = camera.capture2D3D(settings);
auto pointCloud = originalFrame.pointCloud();
소스로 이동

source

string fileCamera = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "/Zivid/BinWithCalibrationBoard.zdf";
var loadedFrameWithDiagnostics = new Zivid.NET.Frame(fileCamera);

Console.WriteLine("Creating virtual camera using file: " + fileCamera);
var camera = zivid.CreateFileCamera(loadedFrameWithDiagnostics);

var settings = loadedFrameWithDiagnostics.Settings;

using (var originalFrame = camera.Capture2D3D(settings))
{
    var pointCloud = originalFrame.PointCloud;
소스로 이동

source

file_camera = get_sample_data_path() / "BinWithCalibrationBoard.zdf"
loaded_frame_with_diagnostics = zivid.Frame(file_camera)

print(f"Creating virtual camera using file: {file_camera}")
camera = app.create_file_camera(loaded_frame_with_diagnostics)

settings = loaded_frame_with_diagnostics.settings

original_frame = camera.capture_2d_3d(settings)
point_cloud = original_frame.point_cloud()

ArUco 마커 프레임의 원점은 ArUco 마커의 중앙에 있습니다.

체커보드 프레임에 상대적인 ROI 상자 크기 및 오른쪽 하단 모서리.

ArUco 마커 프레임과 ROI 상자 크기를 기준으로 ROI 상자의 오른쪽 하단 모서리 위치를 정의합니다. 그런 다음, 길이와 너비에서 빈 가장자리의 너비를 빼서 빈 벽을 제거합니다.

소스로 이동

source

const float roiBoxLength = 545.F;
const float roiBoxWidth = 345.F;
const float roiBoxHeight = 150.F;
// Coordinates are relative to the ArUco marker origin which lies in the center of the ArUco marker.
// Positive x-axis is "East", y-axis is "South" and z-axis is "Down".
const Zivid::PointXYZ roiBoxLowerRightCornerInArUcoFrame{ 240.F, 30.F, 5.F };
const Zivid::PointXYZ roiBoxUpperRightCornerInArUcoFrame{ roiBoxLowerRightCornerInArUcoFrame.x,
                                                          roiBoxLowerRightCornerInArUcoFrame.y - roiBoxWidth,
                                                          roiBoxLowerRightCornerInArUcoFrame.z };
const Zivid::PointXYZ roiBoxLowerLeftCornerInArUcoFrame{ roiBoxLowerRightCornerInArUcoFrame.x - roiBoxLength,
                                                         roiBoxLowerRightCornerInArUcoFrame.y,
                                                         roiBoxLowerRightCornerInArUcoFrame.z };
소스로 이동

source

float roiBoxLength = 545F;
float roiBoxWidth = 345F;
float roiBoxHeight = 150F;
// Coordinates are relative to the checkerboard origin which lies in the intersection between the four checkers
// in the top-left corner of the checkerboard: Positive x-axis is "East", y-axis is "South" and z-axis is "Down"
var roiBoxLowerRightCornerInCheckerboardFrame = new Zivid.NET.PointXYZ
{
    x = 240F,
    y = 30F,
    z = 5F
};
var roiBoxUpperRightCornerInCheckerboardFrame = new Zivid.NET.PointXYZ
{
    x = roiBoxLowerRightCornerInCheckerboardFrame.x,
    y = roiBoxLowerRightCornerInCheckerboardFrame.y - roiBoxWidth,
    z = roiBoxLowerRightCornerInCheckerboardFrame.z
};
var roiBoxLowerLeftCornerInCheckerboardFrame = new Zivid.NET.PointXYZ
{
    x = roiBoxLowerRightCornerInCheckerboardFrame.x - roiBoxLength,
    y = roiBoxLowerRightCornerInCheckerboardFrame.y,
    z = roiBoxLowerRightCornerInCheckerboardFrame.z

};
소스로 이동

source

roi_box_length = 545
roi_box_width = 345
roi_box_height = 150
roi_box_lower_right_corner_in_aruco_frame = np.array([240, 30, 5])
roi_box_upper_right_corner_in_aruco_frame = np.array(
    [
        roi_box_lower_right_corner_in_aruco_frame[0],
        roi_box_lower_right_corner_in_aruco_frame[1] - roi_box_width,
        roi_box_lower_right_corner_in_aruco_frame[2],
    ]
)
roi_box_lower_left_corner_in_aruco_frame = np.array(
    [
        roi_box_lower_right_corner_in_aruco_frame[0] - roi_box_length,
        roi_box_lower_right_corner_in_aruco_frame[1],
        roi_box_lower_right_corner_in_aruco_frame[2],
    ]
)

ROI 상자의 기본 프레임을 정의하는 세 지점을 설정할 수 있습니다.

소스로 이동

source

const Zivid::PointXYZ pointOInArUcoFrame = roiBoxLowerRightCornerInArUcoFrame;
const Zivid::PointXYZ pointAInArUcoFrame = roiBoxUpperRightCornerInArUcoFrame;
const Zivid::PointXYZ pointBInArUcoFrame = roiBoxLowerLeftCornerInArUcoFrame;
소스로 이동

source

var pointOInCheckerboardFrame = roiBoxLowerRightCornerInCheckerboardFrame;
var pointAInCheckerboardFrame = roiBoxUpperRightCornerInCheckerboardFrame;
var pointBInCheckerboardFrame = roiBoxLowerLeftCornerInCheckerboardFrame;
소스로 이동

source

point_o_in_aruco_frame = roi_box_lower_right_corner_in_aruco_frame
point_a_in_aruco_frame = roi_box_upper_right_corner_in_aruco_frame
point_b_in_aruco_frame = roi_box_lower_left_corner_in_aruco_frame

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

소스로 이동

source

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

source

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

source

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

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

소스로 이동

source

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

source

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

source

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

그런 다음 ArUco 마커의 포즈를 추정하여 세 지점을 카메라 기준 프레임으로 변환합니다.

소스로 이동

source

std::cout << "Estimating pose of detected ArUco marker" << std::endl;
const auto cameraToMarkerTransform = detectionResult.detectedMarkers()[0].pose().toMatrix();
std::cout << "Transforming the ROI base frame points to the camera frame" << std::endl;
const auto roiPointsInCameraFrame = transformPoints(
    std::vector<Zivid::PointXYZ>{ pointOInArUcoFrame, pointAInArUcoFrame, pointBInArUcoFrame },
    cameraToMarkerTransform);
소스로 이동

source

Console.WriteLine("Estimating pose of detected ArUco marker");
var cameraToMarkerTransform = new Zivid.NET.Matrix4x4(detectionResult.DetectedMarkers()[0].Pose().ToMatrix());
Console.WriteLine("Transforming the ROI base frame points to the camera frame");
var roiPointsInCameraFrame = TransformPoints(
    new List<Zivid.NET.PointXYZ> { pointOInCheckerboardFrame, pointAInCheckerboardFrame, pointBInCheckerboardFrame },
    cameraToMarkerTransform);
소스로 이동

source

print("Estimating pose of detected ArUco marker")
camera_to_marker_transform = detection_result.detected_markers()[0].pose.to_matrix()
print("Transforming the ROI base frame points to the camera frame")
roi_points_in_camera_frame = _transform_points(
    [point_o_in_aruco_frame, point_a_in_aruco_frame, point_b_in_aruco_frame],
    camera_to_marker_transform,
)

힌트

작동 방식을 궁금하다면 Position, Orientation and Coordinate Transformations 에 대해 자세히 알아보세요.

이제 ROI 상자의 크기와 위치를 기반으로 포인트 클라우드를 필터링할 수 있습니다. 첫 번째 범위는 바닥을 포함하도록 작은 음수 값으로 설정되고 두 번째 범위는 상자의 원하는 높이로 설정됩니다.

소스로 이동

source

const auto roiSettings = Zivid::Settings::RegionOfInterest::Box{
    Zivid::Settings::RegionOfInterest::Box::Enabled::yes,
    Zivid::Settings::RegionOfInterest::Box::PointO{ roiPointsInCameraFrame[0] },
    Zivid::Settings::RegionOfInterest::Box::PointA{ roiPointsInCameraFrame[1] },
    Zivid::Settings::RegionOfInterest::Box::PointB{ roiPointsInCameraFrame[2] },
    Zivid::Settings::RegionOfInterest::Box::Extents{ -10, roiBoxHeight }
};
소스로 이동

source

var roiSettings = new Zivid.NET.Settings.RegionOfInterestGroup.BoxGroup
{
    Enabled = true,
    PointO = roiPointsInCameraFrame[0],
    PointA = roiPointsInCameraFrame[1],
    PointB = roiPointsInCameraFrame[2]
};
roiSettings.Extents = new Zivid.NET.Range<double>(-10, roiBoxHeight);
소스로 이동

source

roi_settings = zivid.Settings.RegionOfInterest.Box(
    enabled=True,
    point_o=roi_points_in_camera_frame[0],
    point_a=roi_points_in_camera_frame[1],
    point_b=roi_points_in_camera_frame[2],
    extents=(-10, roi_box_height),
)

We can now mask the captured point cloud by the ROI and visualize the result.

소스로 이동

source

const auto roiPointCloud = pointCloud.maskedByRegionOfInterest(roiSettings);

std::cout << "Displaying the ROI-filtered point cloud" << std::endl;
visualizeZividPointCloud(roiPointCloud);
소스로 이동

source

using (var roiPointCloud = pointCloud.MaskedByRegionOfInterest(roiSettings))
{
    Console.WriteLine("Displaying the ROI-filtered point cloud");
    VisualizeZividPointCloud(roiPointCloud);
}
소스로 이동

source

roi_point_cloud = point_cloud.masked_by_region_of_interest(roi_settings)
print("Displaying the ROI-filtered point cloud")
display_pointcloud(roi_point_cloud)

체커보드가 있는 빈의 ROI 필터링 및 변환 포인트 클라우드

Finally, we add the ROI box to the capture settings and capture the point cloud with ROI filtering applied directly. This is faster than masking after capture, and lets you save the capture settings with the ROI parameters for reuse without the calibration board.

소스로 이동

source

std::cout << "Adding the ROI box to the capture settings and capturing again" << std::endl;
settings.set(Zivid::Settings::RegionOfInterest{ roiSettings });

const auto roiFrame = camera.capture2D3D(settings);

std::cout << "Displaying the ROI-filtered point cloud from the new capture" << std::endl;
visualizeZividPointCloud(roiFrame.pointCloud());
소스로 이동

source

Console.WriteLine("Adding the ROI box to the capture settings and capturing again");
settings.RegionOfInterest.Box = roiSettings;

using (var roiFrame = camera.Capture2D3D(settings))
{
    Console.WriteLine("Displaying the ROI-filtered point cloud from the new capture");
    VisualizeZividPointCloud(roiFrame);
}
소스로 이동

source

print("Adding the ROI box to the capture settings and capturing again")
settings.region_of_interest.box = roi_settings

roi_frame_point_cloud = camera.capture_2d_3d(settings).point_cloud()
print("Displaying the ROI-filtered point cloud from the new capture")
display_pointcloud(roi_frame_point_cloud)

ROI 상자를 기반으로 포인트 클라우드를 필터링하려면 코드 샘플을 실행할 수 있습니다.

Sample: ROIBoxViaArucoMarker.cpp

./ROIBoxViaArucoMarker

Sample: ROIBoxViaArucoMarker.cs

./ROIBoxViaArucoMarker

Sample: roi_box_via_aruco_marker.py

python roi_box_via_aruco_marker.py

자신의 설정에서 이것을 사용하려면 코드 샘플을 수정하십시오.

  1. 파일 카메라를 실제 카메라 및 설정으로 교체하십시오.

  2. 빈의 오른쪽 하단 모서리에 칼리브레이션 보드를 놓습니다.

  3. ROI 상자 크기를 실제 사용하는 빈의 크기로 수정합니다.

  4. 샘플 실행합니다!

이제 ROI 매개변수로 캡처 설정을 저장하고 칼리브레이션 보드를 제거하고 전체 빈의 설정을 사용할 수 있습니다.

Version History

SDK

Changes

2.18.0

Mask the captured point cloud by the ROI box instead of re-capturing.