前言

什么是关键点?
关键点定义: 关键点也称为兴趣点,它是2D图像、3D点云或曲面模型上,可以通过定义检测标准来获取的具有稳定性区别性的点集。

关键点的意义?
加快后续识别、追踪等数据的处理速度

具备该意义原因?
关键点的数量相比于原始点云或图像的数据量小很多,它与局部特征描述子结合在一起,组成关键点描述子,常用来形成原始数据的紧凑表示,而不失代表性与描述性。

SIFT关键点检测

SIFT(Scale-invaiant feature transform)尺度不变特征变换。最初用于图像处理领域的一种描述,可以在图像中检测出关键点,是一种局部特征描述子,后来引入3D点云领域用于关键点的检测。

在PCL中类 SIFTKeypoint 是将二维图像中的 SIFT 算子调整后移植到 3D 空间的 SIFT算子的实现。输入为带有 XYZ 坐标值和强度的点云 , 输出为点云中的 SIFT 关键点。

Code

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/keypoints/sift_keypoint.h>//sift 关键点 检测 模块
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>

SIFT关键点提取 必须包含 sift_keypoint.h 文件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /*从pcd文件中读取点云*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointXYZ>);//声明读取的点云

    std::string filename= "/home/jone/slam_learn/pcl/sift_keypoint_extraction/pig.pcd"; //pcd文件路径
    // 读取点云
    if(pcl::io::loadPCDFile(filename,*cloud_xyz)==-1)
    {
        //文件没有打开
        std::cout << "Was not able to open file:" <<filename<<std::endl ;
        return 0;
    }

从pcd文件中读取点云

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    //设置 sift 相关参数
    const float    min_scale = 0.01;             //设置尺度空间中最小尺度的标准偏差          
    const int      n_octaves = 6;               //设置高斯金字塔组(octave)的数目            
    const int      n_scales_per_octave = 4;     //设置每组(octave)计算的尺度  
    const float    min_contrast = 0.01;          //设置限制关键点检测的阈值

下面会有setScales()函数 ,用到前3个参数 ,指定搜索关键点的尺度范围

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/***** 进行sift关键点检测  *****/
    /*  创建sift关键点检测对象  */
    pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;

    pcl::PointCloud<pcl::PointWithScale> result; //声明存放结果的点云

    sift.setInputCloud(cloud_xyz);//设置输入点云

    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ> ());//声明一个Kd-tree

    /*上面创建的一个空的kd树对象,并把它传递给sift检测对象*/
    sift.setSearchMethod(tree);

    /*指定搜索关键点的尺度范围*/
    sift.setScales(min_scale, n_octaves, n_scales_per_octave);

    /*设置限制关键点检测的阈值ֵ*/
    sift.setMinimumContrast(min_contrast);

    /*执行sift关键点检测,保存结果在result*/
    sift.compute(result);
    /*****************************/

本节重点部分:进行sift关键点检测
1、创建sift关键点检测对象
2、声明存放结果的点云
3、设置输入点云
4、声明一个Kd-tree
5、上面创建的一个空的kd树对象,并把它传递给sift检测对象
6、指定搜索关键点的尺度范围
7、设置限制关键点检测的阈值ֵ
8、执行sift关键点检测
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_temp (new pcl::PointCloud<pcl::PointXYZ>);//声明一个点云 用于存放 检测结果
    /*将点类型pcl::PointWithScale的数据转换为点类型pcl::PointXYZ的数据*/
    copyPointCloud(result, *cloud_temp);//转换结果点的类型

将点类型pcl::PointWithScale的数据转换为点类型pcl::PointXYZ的数据
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    //可视化输入点云和关键点
    pcl::visualization::PCLVisualizer viewer("Sift keypoint");
    viewer.setBackgroundColor( 255, 255, 255 );
    viewer.addPointCloud(cloud_xyz, "cloud");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0,0,0,"cloud");
    viewer.addPointCloud(cloud_temp, "keypoints");
    viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 9, "keypoints");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0,0,255,"keypoints");    

    while(!viewer.wasStopped ())
    {
        viewer.spinOnce ();
    }

可视化输入点云和关键点

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CMakeLists.txt

# 声明要求的 cmake 最低版本
cmake_minimum_required(VERSION 2.8 )
# 声明工程名称
project(sift_keypoint_extraction)
# 添加c++ 11 标准支持
set(CMAKE_CXX_FLAGS "-std=c++11")
# 寻找PCL的库
find_package(PCL REQUIRED COMPONENT common io visualization filters features keypoints)
link_directories(${PCL_LIBRARY_DIRS})
# 添加头文件
include_directories(${PCL_INCLUDE_DIRS})
add_definitions( ${PCL_DEFINITIONS} )
#添加一个可执行程序
add_executable(sift_keypoint_extraction sift_keypoint_extraction.cpp)
#链接PCL 库
target_link_libraries(sift_keypoint_extraction ${PCL_LIBRARIES})

注意:find_package() 要包含 keypoints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Result


其中蓝色的就是检测到的 SIFT关键点