尺度不變特征轉換(Scale-invariant feature transform,SIFT)是David Lowe在1999年發(fā)表,2004年總結完善。其應用范圍包括物體辨識,機器人地圖感知與導航、3D模型建立、手勢辨識、影像追蹤和動作對比。此算法已經申請專利,專利擁有者屬于英屬哥倫比亞大學。SIFT算法在3D數(shù)據(jù)上的應用由Flint等在2007年實現(xiàn)。這里所講的提取點云關鍵點的算法便是由Flint等人實現(xiàn)的SIFT3D算法。
pcl中sift關鍵點提取算法如下
#include <pcl/registration/ia_ransac.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/fpfh.h>
#include <pcl/search/kdtree.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/filter.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <time.h>
#include <pcl/common/io.h>
#include <iostream>
#include <pcl/keypoints/sift_keypoint.h>//關鍵點檢測
using pcl::NormalEstimation;
using pcl::search::KdTree;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
//點云可視化
void visualize_pcd(PointCloud::Ptr pcd_src,
PointCloud::Ptr pcd_tgt)
//PointCloud::Ptr pcd_final)
{
pcl::visualization::PCLVisualizer viewer("registration Viewer");
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h(pcd_src, 0, 255, 0);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> tgt_h(pcd_tgt, 255, 0, 0);
//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> final_h(pcd_final, 0, 0, 255);
viewer.setBackgroundColor(255, 255, 255);
viewer.addPointCloud(pcd_src, src_h, "source cloud");
viewer.addPointCloud(pcd_tgt, tgt_h, "tgt cloud");
//viewer.addPointCloud(pcd_final, final_h, "final cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "tgt cloud");
while (!viewer.wasStopped())
{
viewer.spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
//pcl中sift特征需要返回強度信息,改為如下:
}
namespace pcl
{
template<>
struct SIFTKeypointFieldSelector<PointXYZ>
{
inline float
operator () (const PointXYZ &p) const
{
return p.z;
}
};
}
int
main(int argc, char** argv)
{
//加載點云文件
PointCloud::Ptr cloud_src_o(new PointCloud);//原點云,待配準
pcl::io::loadPCDFile("E:/PointCloud/data/dragon/dragon.pcd", *cloud_src_o);
cout << "原始點云數(shù)量:"<<cloud_src_o->size() << endl;
//PointCloud::Ptr cloud_tgt_o(new PointCloud);//目標點云
//pcl::io::loadPCDFile("E:/PointCloud/data/pc_4.pcd", *cloud_tgt_o);
//clock_t start = clock();
//去除NAN點
//std::vector<int> indices_src; //保存去除的點的索引
//pcl::removeNaNFromPointCloud(*cloud_src_o, *cloud_src_o, indices_src);
//std::cout << "remove *cloud_src_o nan" << cloud_src_o->size()<<endl;
//std::vector<int> indices_tgt;
//pcl::removeNaNFromPointCloud(*cloud_tgt_o, *cloud_tgt_o, indices_tgt);
//std::cout << "remove *cloud_tgt_o nan" << cloud_tgt_o->size()<<endl;
//設定參數(shù)值
const float min_scale = 0.002f; //the standard deviation of the smallest scale in the scale space
const int n_octaves = 3;//尺度空間層數(shù),小、關鍵點多
const int n_scales_per_octave = 3;//the number of scales to compute within each octave
const float min_contrast = 0.0001f;//根據(jù)點云,設置大小,越小關鍵點越多
//sift關鍵點檢測
pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale > sift_src;
pcl::PointCloud<pcl::PointWithScale> result_src;
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_src(new pcl::search::KdTree<pcl::PointXYZ>());
sift_src.setSearchMethod(tree_src);
sift_src.setScales(min_scale, n_octaves, n_scales_per_octave);
sift_src.setMinimumContrast(min_contrast);
sift_src.setInputCloud(cloud_src_o);
sift_src.compute(result_src);
clock_t end = clock();
cout << "sift關鍵點提取時間" << (double)(end - start) / CLOCKS_PER_SEC << endl;
cout << "sift關鍵點數(shù)量" << result_src.size() << endl;
PointCloud::Ptr cloud_src(new PointCloud);
pcl::copyPointCloud(result_src, *cloud_src);
//可視化
visualize_pcd(cloud_src_o, cloud_src);
return (0);
}

sift關鍵點

運行結果
對于sift關鍵點提取,相對比較耗時。