前言

什么是关键点?
关键点定义: 关键点也称为兴趣点,它是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慢很多