SIFT 关键点提取
本节演示如何检测点云的SIFT 关键点。SIFT 即尺度不变特征变换(Scale-invariant feature transform,SIFT) ,最初用于图像处理领域的一种描述。这种描述具有尺度不变性,可以在图像中检测出关键点,是一种局部特征描述。
完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/io.h>
#include <pcl/keypoints/sift_keypoint.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/time.h>using namespace std;int main(int argc, char *argv[])
{pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointXYZRGB>);pcl::io::loadPCDFile (argv[1], *cloud_xyz);const float min_scale = stof(argv[2]); //string turn into digit const int n_octaves = stof(argv[3]); const int n_scales_per_octave = stof(argv[4]); const float min_contrast = stof(argv[5]); pcl::SIFTKeypoint<pcl::PointXYZRGB, pcl::PointWithScale> sift;//创建sift关键点检测对象pcl::PointCloud<pcl::PointWithScale> result;sift.setInputCloud(cloud_xyz);//设置输入点云pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB> ());sift.setSearchMethod(tree);//创建一个空的kd树对象tree,并把它传递给sift检测对象sift.setScales(min_scale, n_octaves, n_scales_per_octave);//指定搜索关键点的尺度范围sift.setMinimumContrast(min_contrast);//设置限制关键点检测的阈值sift.compute(result);//执行sift关键点检测,保存结果在resultpcl::PointCloud<pcl::PointXYZ>::Ptr cloud_temp (new pcl::PointCloud<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,255,0,"keypoints");while(!viewer.wasStopped ()){viewer.spinOnce ();}return 0;}
1、setInputCloud
创建输入点云数据的存储容器,SIFT检测推荐使用pcl::PointXYZRGB类别,
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_xyz (new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::io::loadPCDFile (argv[1], *cloud_xyz);
2、setSIFTfeatures
1.创建SIFT算法估计实例pcl::SIFTKeypoint<x,x> sift
2.设置SIFT 关键点检测对象的相关参数sift.func()
将输入点云引导到算法实例的输入口sift.setInputCloud
sift.setSearchMethod建立一个基于RGB Point的 kdtree空对象,并将其搭载到SIFT算法实例上,作为快速检索的工具载体
setScale用于指定搜索尺度范
sift.setMinimumContrast设置检测下限
pcl::SIFTKeypoint<pcl::PointXYZRGB, pcl::PointWithScale> sift;//创建sift关键点检测对象
pcl::PointCloud<pcl::PointWithScale> result;//设置输出keypoint存储对象
sift.setInputCloud(cloud_xyz);//设置输入点云pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB> ());
sift.setSearchMethod(tree);//创建一个空的kd树对象tree,并把它传递给sift检测对象
sift.setScales(min_scale, n_octaves, n_scales_per_octave);//指定搜索关键点的尺度范围
sift.setMinimumContrast(min_contrast);//设置限制关键点检测的阈值
sift.compute(result);//执行sift关键点检测,保存结果在result
3、GetSIFTkeypoint
将获得result 从 pcl::PointWithScale 转变为pcl::PointXYZ方便打印
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_temp (new pcl::PointCloud<pcl::PointXYZ>);
copyPointCloud(result, *cloud_temp);//将点类型pcl::PointWithScale的数据转换为点类型pcl::PointXYZ的数据
4、Visualize PointCloud&Keypoint
//可视化输入点云和关键点
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");
//将keypoint存储对象输入时tag为keypoint格式
viewer.addPointCloud(cloud_temp, "keypoints");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 9, "keypoints");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0,255,0,"keypoints");
以下为执行结果
若输入cloud模板类型为PointXYZ,执行结果的SIFT特征点个数明显会少很多