通过棋盘格定义的ROI盒
本教程演示了如何使用 Zivid calibration board box 定义 ROI 盒的参数以及如何使用它进行过滤。我们假设标定板放置在料箱的右下角。 料箱大小也假定为已知,该数据用于设置ROI盒的尺寸。这样你就可以自动找到相机坐标系中的ROI参数了。
备注
本教程使用了一个档案相机(file camera)对下图中的场景进行演示。
首先,我们需要捕获棋盘格的点云。
const auto fileCamera = std::string(ZIVID_SAMPLE_DATA_DIR) + "/BinWithCalibrationBoard.zfc";
std::cout << "Creating virtual camera using file: " << fileCamera << std::endl;
auto camera = zivid.createFileCamera(fileCamera);
auto settings = Zivid::Settings{ Zivid::Settings::Acquisitions{ Zivid::Settings::Acquisition{} } };
const auto originalFrame = camera.capture(settings);
auto pointCloud = originalFrame.pointCloud();
string fileCamera = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "/Zivid/BinWithCalibrationBoard.zfc";
Console.WriteLine("Creating virtual camera using file: " + fileCamera);
var camera = zivid.CreateFileCamera(fileCamera);
var settings = new Zivid.NET.Settings
{
Acquisitions = { new Zivid.NET.Settings.Acquisition { } }
};
var originalFrame = camera.Capture(settings);
var pointCloud = originalFrame.PointCloud;
file_camera = get_sample_data_path() / "BinWithCalibrationBoard.zfc"
print(f"Creating virtual camera using file: {file_camera}")
camera = app.create_file_camera(file_camera)
settings = zivid.Settings([zivid.Settings.Acquisition()])
original_frame = camera.capture(settings)
point_cloud = original_frame.point_cloud()
棋盘格坐标系的原点位于棋盘格左上角的四个格子之间的交叉点。
我们定义了ROI盒右下角相对于棋盘坐标系的位置,以及ROI盒尺寸。然后我们从长度和宽度中减去箱边缘的宽度以移除箱壁。
// 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"
const Zivid::PointXYZ roiBoxLowerRightCornerInCheckerboardFrame{ 240.F, 260.F, 5.F };
const Zivid::PointXYZ roiBoxUpperRightCornerInCheckerboardFrame{ roiBoxLowerRightCornerInCheckerboardFrame.x,
roiBoxLowerRightCornerInCheckerboardFrame.y
- roiBoxWidth,
roiBoxLowerRightCornerInCheckerboardFrame.z };
const Zivid::PointXYZ roiBoxLowerLeftCornerInCheckerboardFrame{ roiBoxLowerRightCornerInCheckerboardFrame.x
- roiBoxLength,
roiBoxLowerRightCornerInCheckerboardFrame.y,
roiBoxLowerRightCornerInCheckerboardFrame.z };
const float roiBoxLength = 545.F;
const float roiBoxWidth = 345.F;
const float roiBoxHeight = 150.F;
// 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 = 260F,
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
};
float roiBoxLength = 545F;
float roiBoxWidth = 345F;
float roiBoxHeight = 150F;
roi_box_lower_right_corner = np.array([240, 260, 0.5])
roi_box_upper_right_corner = np.array(
[
roi_box_lower_right_corner[0],
roi_box_lower_right_corner[1] - roi_box_width,
roi_box_lower_right_corner[2],
]
)
roi_box_lower_left_corner = np.array(
[
roi_box_lower_right_corner[0] - roi_box_length,
roi_box_lower_right_corner[1],
roi_box_lower_right_corner[2],
]
)
roi_box_length = 545
roi_box_width = 345
roi_box_height = 150
然后可以设置定义ROI盒基坐标系的三个点。
const Zivid::PointXYZ pointOInCheckerboardFrame = roiBoxLowerRightCornerInCheckerboardFrame;
const Zivid::PointXYZ pointAInCheckerboardFrame = roiBoxUpperRightCornerInCheckerboardFrame;
const Zivid::PointXYZ pointBInCheckerboardFrame = roiBoxLowerLeftCornerInCheckerboardFrame;
var pointOInCheckerboardFrame = roiBoxLowerRightCornerInCheckerboardFrame;
var pointAInCheckerboardFrame = roiBoxUpperRightCornerInCheckerboardFrame;
var pointBInCheckerboardFrame = roiBoxLowerLeftCornerInCheckerboardFrame;
point_o_in_checkerboard_frame = roi_box_lower_right_corner
point_a_in_checkerboard_frame = roi_box_upper_right_corner
point_b_in_checkerboard_frame = roi_box_lower_left_corner
然后我们需要估计棋盘格的位姿,将这三个点转换到相机参考系。
std::cout << "Detecting and estimating pose of the Zivid checkerboard in the camera frame" << std::endl;
const auto detectionResult = Zivid::Calibration::detectCalibrationBoard(originalFrame);
const auto transformCameraToCheckerboard = detectionResult.pose().toMatrix();
std::cout << "Transforming the ROI base frame points to the camera frame" << std::endl;
const auto roiPointsInCameraFrame = transformPoints(
std::vector<Zivid::PointXYZ>{
pointOInCheckerboardFrame, pointAInCheckerboardFrame, pointBInCheckerboardFrame },
transformCameraToCheckerboard);
Console.WriteLine("Detecting and estimating pose of the Zivid checkerboard in the camera frame");
var detectionResult = Detector.DetectCalibrationBoard(originalFrame);
var cameraToCheckerboardTransform = new Zivid.NET.Matrix4x4(detectionResult.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 },
cameraToCheckerboardTransform);
print("Detecting and estimating pose of the Zivid checkerboard in the camera frame")
detection_result = zivid.calibration.detect_feature_points(original_frame)
camera_to_checkerboard_transform = detection_result.pose().to_matrix()
print("Transforming the ROI base frame points to the camera frame")
roi_points_in_camera_frame = _transform_points(
[point_o_in_checkerboard_frame, point_a_in_checkerboard_frame, point_b_in_checkerboard_frame],
camera_to_checkerboard_transform,
)
提示
详细了解 位置、方向和坐标变换 来了解其工作原理。
现在我们可以根据ROI盒的大小和位置过滤点云。将第一个范围(extent)设置为一个较小的负数值来避免过滤掉底板,第二个范围(extent)设置为所需的盒子高度。
settings.set(Zivid::Settings::RegionOfInterest{
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 } });
settings.RegionOfInterest.Box.Enabled = true;
settings.RegionOfInterest.Box.PointO = roiPointsInCameraFrame[0];
settings.RegionOfInterest.Box.PointA = roiPointsInCameraFrame[1];
settings.RegionOfInterest.Box.PointB = roiPointsInCameraFrame[2];
settings.RegionOfInterest.Box.Extents = new Zivid.NET.Range<double>(-10, roiBoxHeight);
settings.region_of_interest.box.enabled = True
settings.region_of_interest.box.point_o = roi_points_in_camera_frame[0]
settings.region_of_interest.box.point_a = roi_points_in_camera_frame[1]
settings.region_of_interest.box.point_b = roi_points_in_camera_frame[2]
settings.region_of_interest.box.extents = (-10, roi_box_height)
最后,我们进行新的捕获并可视化过滤后的点云。
const auto roiFrame = camera.capture(settings);
std::cout << "Displaying the ROI-filtered point cloud" << std::endl;
visualizeZividPointCloud(roiFrame);
var roiFrame = camera.Capture(settings);
Console.WriteLine("Displaying the ROI-filtered point cloud");
VisualizeZividPointCloud(roiFrame);
roi_point_cloud = camera.capture(settings).point_cloud()
print("Displaying the ROI-filtered point cloud")
display_pointcloud(roi_point_cloud.copy_data("xyz"), roi_point_cloud.copy_data("rgba")[:, :, :3])
如需要根据ROI盒过滤点云,您可以运行我们的代码示例。
./ROIBoxViaCheckerboard
./ROIBoxViaCheckerboard
示例: roi_box_via_checkerboard.py
python roi_box_via_checkerboard.py
小技巧
如果您希望在自己的设置中使用它,您可以自行修改代码示例:
用您的实际相机和设置替换档案相机。
将棋盘格放在料箱的右下角。
将ROI盒尺寸修改为您的料箱的尺寸。
运行示例!
您现在可以保存包含了ROI参数的捕获设置了,然后拿走棋盘格并在整个料箱上使用该设置。