尺度不變特征轉(zhuǎn)換(Scale-invariant feature transform,SIFT)是David Lowe在1999年發(fā)表悬秉,2004年總結(jié)完善反璃。其應(yīng)用范圍包括物體辨識(shí)鳖孤,機(jī)器人地圖感知與導(dǎo)航存和、3D模型建立骗村、手勢(shì)辨識(shí)、影像追蹤和動(dòng)作對(duì)比枣耀。此算法已經(jīng)申請(qǐng)專利,專利擁有者屬于英屬哥倫比亞大學(xué)庭再。SIFT算法在3D數(shù)據(jù)上的應(yīng)用由Flint等在2007年實(shí)現(xiàn)捞奕。這里所講的提取點(diǎn)云關(guān)鍵點(diǎn)的算法便是由Flint等人實(shí)現(xiàn)的SIFT3D算法。
pcl中sift關(guān)鍵點(diǎn)提取算法如下
#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>//關(guān)鍵點(diǎn)檢測(cè)
using pcl::NormalEstimation;
using pcl::search::KdTree;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
//點(diǎn)云可視化
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特征需要返回強(qiáng)度信息拄轻,改為如下:
}
namespace pcl
{
template<>
struct SIFTKeypointFieldSelector<PointXYZ>
{
inline float
operator () (const PointXYZ &p) const
{
return p.z;
}
};
}
int
main(int argc, char** argv)
{
//加載點(diǎn)云文件
PointCloud::Ptr cloud_src_o(new PointCloud);//原點(diǎn)云颅围,待配準(zhǔn)
pcl::io::loadPCDFile("E:/PointCloud/data/dragon/dragon.pcd", *cloud_src_o);
cout << "原始點(diǎn)云數(shù)量:"<<cloud_src_o->size() << endl;
//PointCloud::Ptr cloud_tgt_o(new PointCloud);//目標(biāo)點(diǎn)云
//pcl::io::loadPCDFile("E:/PointCloud/data/pc_4.pcd", *cloud_tgt_o);
//clock_t start = clock();
//去除NAN點(diǎn)
//std::vector<int> indices_src; //保存去除的點(diǎn)的索引
//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è)定參數(shù)值
const float min_scale = 0.002f; //the standard deviation of the smallest scale in the scale space
const int n_octaves = 3;//尺度空間層數(shù),小、關(guān)鍵點(diǎn)多
const int n_scales_per_octave = 3;//the number of scales to compute within each octave
const float min_contrast = 0.0001f;//根據(jù)點(diǎn)云恨搓,設(shè)置大小院促,越小關(guān)鍵點(diǎn)越多
//sift關(guān)鍵點(diǎn)檢測(cè)
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關(guān)鍵點(diǎn)提取時(shí)間" << (double)(end - start) / CLOCKS_PER_SEC << endl;
cout << "sift關(guān)鍵點(diǎn)數(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關(guān)鍵點(diǎn)
運(yùn)行結(jié)果
對(duì)于sift關(guān)鍵點(diǎn)提取,相對(duì)比較耗時(shí)斧抱。