前言
什么是关键点?
关键点定义: 关键点也称为兴趣点,它是2D图像、3D点云或曲面模型上,可以通过定义检测标准来获取的具有稳定性、区别性的点集。
关键点的意义?
加快后续识别、追踪等数据的处理速度
具备该意义原因?
关键点的数量相比于原始点云或图像的数据量小很多,它与局部特征描述子结合在一起,组成关键点描述子,常用来形成原始数据的紧凑表示,而不失代表性与描述性。
3D Harris 角点检测
角点概念
对于角点,到目前为止还没有明确的数学定义。可以认为角点就是极值点,即在某方面属性特别突出的点。一般的角点检测都是对有具体定义的、或者是能够具体检测出来的兴趣点的检测。这意味着兴趣点可以是角点,是在某些属性上强度最大或者最小的孤立点、线段的终点,或者是曲线上局部曲率最大的点。
Harris算子是常见的特征检测算子,既可以提取角点也可以提取边缘点。与2D Harris角点检测原理不同,3D Harris角点检测利用的是点云法向量的信息。
除此外PCL还提供了
2D Harris角点检测----- 基于点云的强度字段的 harris 关键点检测子。
6D Harris角点检测----- 利用欧氏空间域 XYZ或者强度域来确定候选关键点,或者前两者的交集,即同时满足 XYZ 域和强度域的关键点为候选关键点。
Code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/io.h>
#include <pcl/keypoints/harris_3d.h>//harris
#include <cstdlib>
#include <vector>
#include <pcl/console/parse.h>
harris 关键点提取必须包含 harris_3d.h 文件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//读取pcd文件 作为输入点云
pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud (new pcl::PointCloud<pcl::PointXYZ>);//声明读取的点云 作为输入点云
std::string filename= "/home/jone/slam_learn/pcl/harris_keypoint_extraction/roorm.pcd"; //pcd文件路径
// 读取点云
if(pcl::io::loadPCDFile(filename,*input_cloud)==-1)
{
//文件没有打开
std::cout << "Was not able to open file:" <<filename<<std::endl ;
return 0;
}
读取pcd文件 作为输入点云
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*设置 harris 相关参数*/
const float r_normal = 0.1 ;
const float r_keypoint = 0.1 ;
设置 harris 相关参数
相关参数必须的时这两个,
r_normal 为法线估计的搜索半径,同时也是计算兴趣值的支持区域
r_keypoint 为判断是否为关键点的感兴趣程度的阈值,小于该阈值的点被忽略,大于的则认为是关键点
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pcl::PointCloud<pcl::PointXYZI>::Ptr Harris_keypoints (new pcl::PointCloud<pcl::PointXYZI>);//声明 Harris 关键点 点云
/* 声明Harris 关键点 检测 对象 */
pcl::HarrisKeypoint3D<pcl::PointXYZ,pcl::PointXYZI,pcl::Normal>* harris_detector = new pcl::HarrisKeypoint3D<pcl::PointXYZ,pcl::PointXYZI,pcl::Normal> ;
声明 Harris 关键点 点云
声明Harris 关键点 检测 对象
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*设置相关参数*/
harris_detector->setRadius(r_normal);
harris_detector->setRadiusSearch(r_keypoint);
harris_detector->setNonMaxSupression(true);
对 Harris检测 设置相关参数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*设置输入点云*/
harris_detector->setInputCloud (input_cloud);
设置输入点云,就是从pcd文件中读取的点云
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* 计算关键点 结果返回在 Harris_keypoints 中 */
harris_detector->compute (*Harris_keypoints);
计算关键点 结果返回在 Harris_keypoints 中
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//输出检测到harris 角点 的 个数
std::cout<<"Harris_keypointsg 个数:"<<Harris_keypoints->size()<<std::endl;
输出检测到harris 角点 的 个数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pcl::PCDWriter writer; //声明写pcd文件对象
//将得到的角点 写入pcd 文件中
writer.write<pcl::PointXYZI> ("Harris_keypoints.pcd",*Harris_keypoints,false);
将得到的角点 写入pcd 文件中
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//可视化输入点云和关键点
typedef pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZI> ColorHandlerT3;
pcl::visualization::PCLVisualizer viewer("Harris keypoint");
viewer.setBackgroundColor( 255, 255, 255 );//设置背景
viewer.addPointCloud(input_cloud, "input_cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0,0,0,"input_cloud");
viewer.addPointCloud (Harris_keypoints, ColorHandlerT3 (Harris_keypoints, 0.0, 0.0, 255.0),"Harris_keypoints");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 8, "Harris_keypoints");
viewer.spin ();
将原始点云和 得到的 harris 关键点 可视化
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Result
蓝色的点为Harris关键点
这个的检测速度要比sift慢很多