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;
}