点云学习-KyePoints-ISS

KeyPoints-ISS

原理

协方差矩阵特征值的物理含义

两变量间的协方差描述了两者变换过程中的总体误差,其描述的是两变量变化趋势的一致性,表征变量之间的相关程度。在需要多个对应值描述个体时,两不同个体间的相关程度就可以用对应值间的相关程度来表征,而不同值之间的相关程度可以通过协方差矩阵来表示。协方差矩阵中的元素表示两对应维度的相关程度,协方差矩阵最大特征值所对应的特征向量指向方差最大的方向,在该方向上数据投影方差的大小即为特征值。方差第二大方向即为第二大特征方向,因为协方差矩阵为实对称矩阵,该方向与第一特征方向垂直。所以可以知道点云数据集对应协方差矩阵的第一特征向量应该是点云分布最离散的方向,第二特征向量对应次离散方向,第三特征与两者垂直。而三者对应的特征值表述的是点云分布在各个方向上的投影长度,可以理解为方向上的分布强度。

协方差矩阵与特征值的详细推导:协方差矩阵有什么意义?

特征点判断

根据点所处位置的几何特征,确定点的属性。基于加权PCA方法计算点对应特征向量,并根据特征向量之间的关系评价点的状态:设点对应特征值从大到小依次是λ1λ2,λ3,如果选择点是角点,其邻域内点集对应特征向量应有:λ1>>λ2>λ3

若选择点是边缘点有:λ1≈λ2>λ3:

由此可判断点的性质。

过程

Python点云数据处理(五)ISS关键点提取 - 知乎 (zhihu.com)

(1)为点云的每个点p_i建立局部坐标系,设定每个点的搜索半径r或k个邻近点。

(2)以搜索半径r或k邻近点建立kd-tree,计算范围内所有点的权值:

(3)计算所有点p_i的协方差矩阵:

(4)计算各个点p_i协方差矩阵的特征值{λi^1,λi2,λ_i3 },按由大到小排列

(5)设置阈值ε1与ε2,满足下式则认为该点为ISS特征点:

算法伪代码

pcl实现

PCL ISS关键点提取点云侠的博客-CSDN博客iss关键点

#include <iostream>
 #include <pcl/io/ply_io.h>
 #include <pcl/point_types.h>
 #include <pcl/common/io.h>
 #include <pcl/keypoints/iss_3d.h>
 #include <pcl/features/normal_3d.h>
 #include <pcl/visualization/pcl_visualizer.h>
 #include <boost/thread/thread.hpp>
 #include <pcl/visualization/cloud_viewer.h>
 ​
 using namespace std;
 ​
 int main(int, char** argv)
 {
     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
     if (pcl::io::loadPLYFile<pcl::PointXYZ>("D:\\code\\LearnPCL\\Data\\apescene1.ply", *cloud) == -1)//D:\\code\\LearnPCL\\Data\\Armadillo.ply
     {
         PCL_ERROR("Could not read file\n");
     }
     cout << "读取点云个数: " << cloud->points.size() << endl;
 ​
     pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss;
     pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZ>());
     pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
 ​
     //-------------------传递索引----------------------------
         //vector <int>(point_indices);
         //pcl::IndicesPtr indices(new vector <int>(point_indices));
     iss.setInputCloud(cloud);
     iss.setSearchMethod(tree);
     iss.setNumberOfThreads(8);     //初始化调度器并设置要使用的线程数
     iss.setSalientRadius(20.0f);  // 设置用于计算协方差矩阵的球邻域半径
     iss.setNonMaxRadius(20.0f);   // 设置非极大值抑制应用算法的半径
     iss.setThreshold21(0.7);     // 设定第二个和第一个特征值之比的上限
     iss.setThreshold32(0.5);     // 设定第三个和第二个特征值之比的上限
     iss.setMinNeighbors(20);       // 在应用非极大值抑制算法时,设置必须找到的最小邻居数
 ​
     iss.compute(*keypoints);
     cout << "ISS_3D points 的提取结果: " << keypoints->points.size() << endl;
     boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D ISS"));
     viewer->setBackgroundColor(255, 255, 255);
     viewer->setWindowName("KeyPoints-ISS");
     pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0.0, 255, 0.0);
     viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud");
     viewer->addPointCloud<pcl::PointXYZ>(keypoints, "key cloud");//特征点
     viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud");
 ​
     viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "key cloud");
     viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "key cloud");
 ​
     while (!viewer->wasStopped())
     {
         viewer->spinOnce(100);
         boost::this_thread::sleep(boost::posix_time::microseconds(100));
     }
 ​
     return 0;
 }
 ​
 ​

结果

以下是点云ISS、3DSC、SAC-IA、ICP的代码示例: 1. ISS 特征提取 ```c++ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss_detector; iss_detector.setSearchMethod(tree); iss_detector.setSalientRadius(6 * resolution); iss_detector.setNonMaxRadius(4 * resolution); iss_detector.setThreshold21(0.975); iss_detector.setThreshold32(0.975); iss_detector.setMinNeighbors(5); iss_detector.setInputCloud(cloud); iss_detector.compute(*keypoints); ``` 2. 3DSC 特征描述 ```c++ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::ShapeContext1980>::Ptr descriptors(new pcl::PointCloud<pcl::ShapeContext1980>); pcl::ShapeContext3DEstimation<pcl::PointXYZ, pcl::ShapeContext1980> desc_est; pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); desc_est.setInputCloud(keypoints); desc_est.setInputNormals(normals); desc_est.setSearchMethod(tree); desc_est.setRadiusSearch(4 * resolution); desc_est.compute(*descriptors); ``` 3. SAC-IA 平面拟合 ```c++ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers(new pcl::PointIndices); pcl::SACSegmentation<pcl::PointXYZ> seg; seg.setOptimizeCoefficients(true); seg.setModelType(pcl::SACMODEL_PLANE); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations(1000); seg.setDistanceThreshold(0.01); seg.setInputCloud(cloud); seg.segment(*inliers, *coefficients); ``` 4. ICP 点云配准 ```c++ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr aligned(new pcl::PointCloud<pcl::PointXYZ>); pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; icp.setInputSource(cloud1); icp.setInputTarget(cloud2); icp.setMaxCorrespondenceDistance(0.05); icp.setMaximumIterations(50); icp.setTransformationEpsilon(1e-8); icp.setEuclideanFitnessEpsilon(1); icp.align(*aligned); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wdmcs

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

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

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

打赏作者

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

抵扣说明:

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

余额充值