PCL ICP配准【点到面】(Registration_ICP)

PCL专栏目录及须知

点到点的ICP算法同点到面的ICP算法基本原理相同。只是点对点是计算源点云的点到目标点云相应点对之间的距离,点对面是计算源点云的点到目标点云相应点对所在平面之间的距离。

ICP算法解释

1.解释

ICP算法的基本思想是通过迭代的方式寻找两个点云之间的最佳刚体变换,使得它们之间的对应点之间的距离最小化。点到面的ICP算法在计算对应点之间的距离时,计算目标点云的每个点到参考点云的所在局部平面的距离,从而提高配准的准确性。

区别如下图所示:

使用点到平面(point-plane)误差度量的迭代最近点ICP算法已被证明比使用点到点(point-point)误差度量的算法收敛得更快

2.关键函数

(1)为终止条件设置最小转换差异,即最优点对距离的阈值(本值一般都设很小)

registration.setTransformationEpsilon(1e-10);							// 为终止条件设置最小转换差异

(2)设置对应点对之间的最大距离,即pcl::registration::CorrespondenceEstimation调用determineCorrespondences(*correspondences, dis)时的dis的值。

registration.setMaxCorrespondenceDistance(1.5);							// 设置对应点对之间的最大距离

(3)设置收敛条件是均方误差和小于阈值, 停止迭代;

registration.setEuclideanFitnessEpsilon(0.01);

(4)最大迭代次数

registration.setMaximumIterations(500);

3.完整代码

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

void cloudNormal(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointNormal>::Ptr& cloud_normals)
{
    pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;//OMP加速
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    n.setNumberOfThreads(8);
    n.setInputCloud(cloud);
    n.setSearchMethod(tree);
    n.setKSearch(10);
    n.compute(*normals);
    pcl::concatenateFields(*cloud, *normals, *cloud_normals);       // 拼接点云及法向量
}

int main()
{
    /****************ICP配准********************/
    pcl::PointCloud<pcl::PointXYZ>::Ptr source(new pcl::PointCloud<pcl::PointXYZ>);			// 源点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr target(new pcl::PointCloud<pcl::PointXYZ>);			// 目标点云
    pcl::io::loadPCDFile("D:/code/csdn/data/person2.pcd", *source);
    pcl::io::loadPCDFile("D:/code/csdn/data/person3.pcd", *target);
    pcl::PointCloud<pcl::PointNormal>::Ptr result(new pcl::PointCloud<pcl::PointNormal>);			// 目标点云转换后的结果

    // ICP配准
    // 计算点云法向量
    pcl::PointCloud<pcl::PointNormal>::Ptr sourceNormals(new pcl::PointCloud<pcl::PointNormal>);
    pcl::PointCloud<pcl::PointNormal>::Ptr targetNormals(new pcl::PointCloud<pcl::PointNormal>);
    cloudNormal(source, sourceNormals);
    cloudNormal(target, targetNormals);

    pcl::IterativeClosestPointWithNormals<pcl::PointNormal, pcl::PointNormal> registration;
    registration.setInputSource(sourceNormals);
    registration.setInputTarget(targetNormals);
    registration.setTransformationEpsilon(1e-10);                       // 为终止条件设置最小转换差异
    registration.setMaxCorrespondenceDistance(1.5);                     // 设置对应点对之间的最大距离(此值对配准结果影响较大)。
    registration.setEuclideanFitnessEpsilon(0.01);                      // 设置收敛条件是均方误差和小于阈值, 停止迭代;
    //registration.setUseSymmetricObjective(false);                       // 设置为true则变为另一个算法
    registration.setMaximumIterations(500);                             // 最大迭代次数
    registration.align(*result);

    std::cout << "点对匹配分数:" << registration.getFitnessScore() << std::endl;
    std::cout << "刚体变换矩阵:" << registration.getFinalTransformation() << std::endl;

    /****************展示********************/
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("ICP"));
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(target, 255, 0, 0);		// 目标点云
    viewer->addPointCloud<pcl::PointXYZ>(target, target_color, "target cloud");
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointNormal>result_color(result, 0, 255, 0);		// 配准结果点云
    viewer->addPointCloud<pcl::PointNormal>(result, result_color, "result cloud");

    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return (0);
}

4.结果展示

(1)待配准点云

(2)配准点云结果

二者完全合并到一起了,所以看起来是一个点云。

​​​​​​​

Python pcl库可以使用ICP算法进行点云配准ICP算法本质上是基于最小二乘法的最优配准方法,它通过选择对应关系点对,计算最优刚体变换的过程来实现配准。在Python pcl库中,可以使用`pcl.registration.ICP`类来进行ICP配准。 首先,需要导入相应的库和模块: ```python import pcl from pcl.registration import icp, TransformationEstimationPointToPlane ``` 然后,可以加载需要配准的点云数据: ```python cloud_source = pcl.load("source_cloud.pcd") cloud_target = pcl.load("target_cloud.pcd") ``` 接下来,创建一个ICP对象,并设置一些参数: ```python icp = icp.IterativeClosestPoint() icp.setMaximumIterations(50) # 设置最大迭代次数 icp.setTransformationEpsilon(1e-8) # 设置收敛精度 icp.setEuclideanFitnessEpsilon(1e-6) # 设置收敛条件 ``` 然后,可以进行配准: ```python icp.setInputSource(cloud_source) icp.setInputTarget(cloud_target) cloud_aligned = pcl.PointCloud() icp.align(cloud_aligned) ``` 最后,可以获取配准后的点云结果: ```python transformation_matrix = icp.getFinalTransformation() ``` 这样,就完成了使用Python pcl库进行ICP配准的过程。请注意,ICP算法配准结果可能受到初始迭代值的影响,因此在实际应用中,需要根据具体情况选择合适的初始值来获得更好的配准结果。 #### 引用[.reference_title] - *1* *2* *3* [PCL中的点云ICP配准(附源代码和数据)](https://blog.csdn.net/qq_29462849/article/details/85080518)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值