Stitch by Transform Tutorial
이 튜토리얼에서는 여러 대의 카메라를 서로 보정한 결과를 사용하는 방법을 설명합니다. 다중 카메라 변환 결과는 한 포인트 클라우드를 다른 포인트 클라우드의 좌표계로 변환하는 데 사용할 수 있는 변환 행렬입니다. 이는 포인트 클라우드를 연결하는 데 매우 유용한 첫 단계입니다.
Prerequisites
이 튜토리얼을 진행하기 전에 Multi-Camera Calibration Tutorial 를 완료해야 합니다.
Load associated transformation matrices and map to point cloud
올바른 변환 행렬을 적용하려면 이를 해당 프레임에 매핑해야 합니다. 카메라 또는 ZDF 파일의 일련 번호를 사용하여 이름이 일치하는 YAML 파일을 찾습니다.
카메라에서 직접 캡처할 때는 카메라의 일련 번호를 읽고 해당 이름의 YAML 파일을 검색한 다음, 변환 행렬을 카메라에 매핑합니다.
반면, ZDF 파일에서 로드할 때는 파일 목록에서 ZDF 파일을 찾아 프레임에서 해당 파일의 일련 번호를 추출해야 합니다. 그런 다음, 동일한 파일 목록에서 해당 일련 번호를 이름으로 사용하는 YAML 파일을 검색합니다. 그런 다음 변환 행렬을 프레임에 매핑합니다. getTransformedPointClouds 에서 변환을 적용하고, 정리되지 않은 포인트 클라우드를 바로 확장합니다.
Zivid::UnorganizedPointCloud getTransformedPointClouds(
Zivid::UnorganizedPointCloud stitchedPointCloud;
Zivid::Matrix4x4 transformationMatrixZivid(yamlFileName);
Zivid::UnorganizedPointCloud currentPointCloud = frame.pointCloud().toUnorganizedPointCloud();
stitchedPointCloud.extend(currentPointCloud.transform(transformationMatrixZivid));
Apply transformation matrix and stitch transformed point cloud with previous point clouds
변환 행렬을 사용하여 캡처를 매핑했습니다. 이제 변환하고 스티칭할 준비가 되었습니다.
캡처한 뒤 transformsMappedToCameras 에서 transform 을 추출할 수 있습니다. 각 캡처마다 정리되지 않은 포인트 클라우드를 변환하고 확장합니다.
for(auto &camera : connectedCameras)
{
if(pathNotProvided)
{
settingsPath = std::string(ZIVID_SAMPLE_DATA_DIR) + "/Settings/" + sanitizedModelName(camera)
+ "_ManufacturingSpecular.yml";
}
std::cout << "Imaging from camera: " << camera.info().serialNumber() << std::endl;
const auto frame = camera.capture2D3D(Zivid::Settings(settingsPath));
const auto unorganizedPointCloud = frame.pointCloud().toUnorganizedPointCloud();
const auto transformationMatrix = transformsMappedToCameras.at(camera.info().serialNumber().toString());
const auto transformedUnorganizedPointCloud = unorganizedPointCloud.transformed(transformationMatrix);
stitchedPointCloud.extend(transformedUnorganizedPointCloud);
}
for camera in connected_cameras:
if args.settings_path is not None:
settings_path = args.settings_path
else:
settings_path = (
get_sample_data_path() / "Settings" / f"{sanitized_model_name(camera)}_ManufacturingSpecular.yml"
)
print(f"Imaging from camera: {camera.info.serial_number}")
frame = camera.capture(zivid.Settings.load(settings_path))
unorganized_point_cloud = frame.point_cloud().to_unorganized_point_cloud()
transformation_matrix = transforms_mapped_to_cameras[camera.info.serial_number]
transformed_unorganized_point_cloud = unorganized_point_cloud.transformed(transformation_matrix)
stitched_point_cloud.extend(transformed_unorganized_point_cloud)
Optional: refine alignment with local point cloud registration
다중 카메라 캘리브레이션에서 얻은 변환 행렬은 완벽한 경우가 드물며, 일반적으로 스티칭된 포인트 클라우드 사이에 작은 잔차 정렬 오차가 남습니다. 이러한 잔차는 변환 기반 사전 정렬 이후 Experimental::Toolbox::localPointCloudRegistration() 을 적용하여 겹치는 포인트 클라우드 간의 정렬을 개선함으로써 줄일 수 있습니다.
다중 카메라 캘리브레이션 기반 사전 정렬 위에 적용되는 이 개선 단계에 대한 설명은 Stitching Workflow 를 참조하세요.
Voxel downsample
시각화하기 전에 스티칭된 포인트 클라우드를 정리합니다.
여기서는 0.5mm의 복셀 크기를 요청합니다. 두 번째 매개변수는 두 대 이상의 카메라가 관련된 경우 유용합니다. 이 경우 픽셀 내에서 다수결 투표를 하는 데 사용할 수 있습니다. 자세한 내용은 Voxel downsample 을 참조하세요.
Visualize
스티칭된 포인트 클라우드를 시각화하기 위해 Visualization::Visualizer 를 사용합니다.
void visualizePointCloud(const Zivid::UnorganizedPointCloud &unorganizedPointCloud)
{
Zivid::Visualization::Visualizer visualizer;
visualizer.showMaximized();
visualizer.show(unorganizedPointCloud);
visualizer.resetToFit();
std::cout << "Running visualizer. Blocking until window closes." << std::endl;
visualizer.run();
}
Save stitched point cloud
마지막으로 선택적으로 포인트 클라우드를 저장할 수 있습니다.
const std::string &fileName = stitchedPointCloudFileName;
std::cout << "Saving " << finalPointCloud.size() << " data points to " << fileName << std::endl;
using PLY = Zivid::Experimental::PointCloudExport::FileFormat::PLY;
const auto colorSpace = Zivid::Experimental::PointCloudExport::ColorSpace::sRGB;
Zivid::Experimental::PointCloudExport::exportUnorganizedPointCloud(
finalPointCloud, PLY{ fileName, PLY::Layout::unordered, colorSpace });