vtkIterativeClosestPointTransform使用整理

vtkIterativeClosestPointTransform

ICP 算法的实现。

使用迭代最近点 (ICP) 算法匹配两个表面。该算法的核心是将一个表面中的每个顶点与另一个表面的最近表面点进行匹配,然后应用变换来修改一个表面以最佳匹配另一个表面(在最小二乘意义上)。这必须进行迭代才能获得表面的正确收敛。

注意
使用 vtkTransformPolyDataFilter 将生成的 ICP 变换应用于您的数据。您也可以将其设置为演员的用户变换。

此类在内部使用 vtkLandmarkTransform 来计算最佳拟合。使用 GetLandmarkTransform 成员获取指向该变换的指针并设置其参数。例如,您可以通过检查 vtkLandmarkTransform 文档中的 SetMode 成员来限制解决方案的自由度数(即刚体、相似性等)。

  1. 设置源点云和目标点云

    • 使用 SetSource 方法设置源点云。
    • 使用 SetTarget 方法设置目标点云。
  2. 配置算法参数

    • MaximumNumberOfIterations:设置/获取最大迭代次数。默认值为 50。
    • CheckMeanDistance:强制算法检查两次迭代之间的平均距离。
    • MaximumMeanDistance: 设置/获取两次迭代之间的最大平均距离。如果平均距离低于此值,则收敛停止。默认值为 0.01。
    • MeanDistanceMode: 指定平均距离模式。此模式表示如何计算平均距离。RMS 模式是最近点距离平方和的平均值的平方根。绝对值模式是最近点距离绝对值和的平均值。默认值为 VTK_ICP_MODE_RMS.
    • MaximumNumberOfLandmarks:设置/获取数据集中采样的地标的最大数量。如果数据集很密集,则通常不需要所有点来计算 ICP 变换。默认值为 200。
    • SetStartByMatchingCentroids:通过将源质心转换为目标质心来启动该过程。默认为关闭。
    • LandmarkTransform:获取内部地标变换。使用它来约束解决方案的自由度数量(即刚体、相似性等)。
  3. 执行变换

    • 调用 Update 方法执行 ICP 算法。

示例代码

以下是一个简单的示例,展示如何使用 vtkIterativeClosestPointTransform 进行点云配准:

#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkIterativeClosestPointTransform.h>
#include <vtkPoints.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTransformFilter.h>

int main() {
    // 创建源点云
    vtkSmartPointer<vtkPoints> sourcePoints = vtkSmartPointer<vtkPoints>::New();
    sourcePoints->InsertNextPoint(0.0, 0.0, 0.0);
    sourcePoints->InsertNextPoint(1.0, 0.0, 0.0);
    sourcePoints->InsertNextPoint(0.0, 1.0, 0.0);

    vtkSmartPointer<vtkPolyData> source = vtkSmartPointer<vtkPolyData>::New();
    source->SetPoints(sourcePoints);

    // 创建目标点云
    vtkSmartPointer<vtkPoints> targetPoints = vtkSmartPointer<vtkPoints>::New();
    targetPoints->InsertNextPoint(1.0, 1.0, 0.0);
    targetPoints->InsertNextPoint(2.0, 1.0, 0.0);
    targetPoints->InsertNextPoint(1.0, 2.0, 0.0);

    vtkSmartPointer<vtkPolyData> target = vtkSmartPointer<vtkPolyData>::New();
    target->SetPoints(targetPoints);

    // 创建 ICP 变换
    vtkSmartPointer<vtkIterativeClosestPointTransform> icp = vtkSmartPointer<vtkIterativeClosestPointTransform>::New();
    icp->SetSource(source);
    icp->SetTarget(target);
    icp->SetMaximumNumberOfIterations(50);
    icp->StartByMatchingCentroidsOn();
    icp->Update();

    // 获取变换矩阵
    vtkSmartPointer<vtkMatrix4x4> matrix = icp->GetMatrix();

    // 应用变换
    vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
    transformFilter->SetInputData(source);
    transformFilter->SetTransform(icp);
    transformFilter->Update();

    // 创建渲染器和窗口
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);

    // 创建源点云的 Actor
    vtkSmartPointer<vtkPolyDataMapper> sourceMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    sourceMapper->SetInputData(source);
    vtkSmartPointer<vtkActor> sourceActor = vtkSmartPointer<vtkActor>::New();
    sourceActor->SetMapper(sourceMapper);
    sourceActor->GetProperty()->SetColor(1.0, 0.0, 0.0); // 红色

    // 创建变换后的源点云的 Actor
    vtkSmartPointer<vtkPolyDataMapper> transformedSourceMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    transformedSourceMapper->SetInputConnection(transformFilter->GetOutputPort());
    vtkSmartPointer<vtkActor> transformedSourceActor = vtkSmartPointer<vtkActor>::New();
    transformedSourceActor->SetMapper(transformedSourceMapper);
    transformedSourceActor->GetProperty()->SetColor(0.0, 1.0, 0.0); // 绿色

    // 创建目标点云的 Actor
    vtkSmartPointer<vtkPolyDataMapper> targetMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    targetMapper->SetInputData(target);
    vtkSmartPointer<vtkActor> targetActor = vtkSmartPointer<vtkActor>::New();
    targetActor->SetMapper(targetMapper);
    targetActor->GetProperty()->SetColor(0.0, 0.0, 1.0); // 蓝色

    // 添加 Actor 到渲染器
    renderer->AddActor(sourceActor);
    renderer->AddActor(transformedSourceActor);
    renderer->AddActor(targetActor);
    renderer->SetBackground(1.0, 1.0, 1.0); // 白色背景

    // 渲染
    renderWindow->Render();
    renderWindowInteractor->Start();

    return 0;
}

解释

  1. 创建点云:分别创建源点云和目标点云,并存储在 vtkPolyData 对象中。
  2. 创建 ICP 变换:实例化 vtkIterativeClosestPointTransform,并设置源点云和目标点云。
  3. 配置 ICP 参数:设置最大迭代次数和是否从质心匹配开始。
  4. 执行变换:调用 Update 方法执行 ICP 算法。
  5. 获取变换矩阵:使用 GetMatrix 方法获取变换矩阵。
  6. 应用变换:使用 vtkTransformFilter 将变换应用到源点云。
  7. 可视化:创建渲染器和窗口,添加源点云、变换后的源点云和目标点云的 Actor,并渲染结果。

通过上述步骤,你可以使用 vtkIterativeClosestPointTransform 进行点云配准,并可视化配准结果。

vtkLandmarkTransform

由两个对应点集指定的线性变换

vtkLandmarkTransform 由两组地标定义,计算出的变换在最小二乘意义上给出了将一个映射到另一个的最佳拟合。索引被视为对应,因此第一组中的点 1 将映射到第二组中的点 1 附近,等等。调用 SetSourceLandmarks 和 SetTargetLandmarks 来指定两组地标,确保它们具有相同数量的点。

警告
每当您添加、减去或设置点时,都必须在 vtkPoints 对象上调用 Modified(),否则转换可能不会更新。

以下是一个基于VTK库实现ICP的简单示例代码,假设已经有两个点云`sourceCloud.vtk`和`targetCloud.vtk`,需要将`sourceCloud`对齐到`targetCloud`: ```cpp #include <vtkSmartPointer.h> #include <vtkIterativeClosestPointTransform.h> #include <vtkLandmarkTransform.h> #include <vtkPolyData.h> #include <vtkPolyDataReader.h> #include <vtkPolyDataWriter.h> #include <vtkPointSource.h> int main(int argc, char* argv[]) { // 读取源点云和目标点云 vtkSmartPointer<vtkPolyDataReader> sourceReader = vtkSmartPointer<vtkPolyDataReader>::New(); sourceReader->SetFileName("sourceCloud.vtk"); sourceReader->Update(); vtkSmartPointer<vtkPolyDataReader> targetReader = vtkSmartPointer<vtkPolyDataReader>::New(); targetReader->SetFileName("targetCloud.vtk"); targetReader->Update(); // ICP变换 vtkSmartPointer<vtkIterativeClosestPointTransform> icp = vtkSmartPointer<vtkIterativeClosestPointTransform>::New(); icp->SetSource(sourceReader->GetOutput()); icp->SetTarget(targetReader->GetOutput()); icp->GetLandmarkTransform()->SetModeToRigidBody(); icp->SetMaximumNumberOfIterations(100); icp->StartByMatchingCentroidsOn(); icp->Update(); // 应用变换到源点云 vtkSmartPointer<vtkPolyData> transformed = vtkSmartPointer<vtkPolyData>::New(); transformed->ShallowCopy(sourceReader->GetOutput()); vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); transform->SetMatrix(icp->GetMatrix()); vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); transformFilter->SetTransform(transform); transformFilter->SetInputData(transformed); transformFilter->Update(); // 输出变换后的点云 vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New(); writer->SetFileName("transformedCloud.vtk"); writer->SetInputData(transformFilter->GetOutput()); writer->Write(); return 0; } ``` 该代码使用`vtkIterativeClosestPointTransform`实现ICP变换,并通过`vtkTransform`将变换应用到源点云上。最后将变换后的点云输出到文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力减肥的小胖子5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值