基础知识(六)KD-Tree快速最近邻搜索

flann库是比较常用的k近邻搜索库,支持n维数据点的快速搜索,同时许多开源库也都是用这个,比如opencv,还有点云处理的库PCL。因为opencv也可以调用这个库,所以我直接用opencv进行调用。如果不想要引入opencv库,可以网上下载flann,然后调用里面的c++源码。调用flann需要包含头文件:flann.hpp。在此直接贴个调用这个库,进行快速最近邻快速搜索的函数:

//输入n个数据点vec_hogs,搜索点hog的最近邻,返回最近邻的索引
int	 getNearIndex(vector<vector<float>>  vec_hogs,std::vector<float> hog)
{
//把n个数据点转为flann参数矩阵形式
	int n_feature=hog.size();//特征维数
	cv::Mat brow_mat(vec_hogs.size(),n_feature,CV_32FC1);//把数据点存为矩阵,其中,M(i,j)表示第i个点的第j维数据
	for (int i=0;i<vec_hogs.size();i++)
	{
		vector<float>&brow_vec=vec_hogs[i];
		for (int j=0;j<brow_vec.size();j++)
		{
			brow_mat.at<float>(i,j)=brow_vec[j];
		}
	}
//建立kd树
	flann::Index knn( brow_mat,cv::flann::KDTreeIndexParams());
//把数据点hog转换成矩阵  ,矩阵大小为1行, n_feature列,
//如果你要同时搜索m个数据点的最近邻点,那么矩阵为m行,n_feature列
	cv::Mat ser(1,n_feature,CV_32FC1);
	for (int i=0;i<hog.size();i++)
	{
		ser.at<float>(0,i)=hog[i];
	}
//搜索
	int num_knn=1;//这个参数是用于设置搜索最邻近点的个数的,因为我只要搜索一个最近的点,所以设置为1
	cv::Mat nearest_index_result;
	cv::Mat nearest_dist_result;
	knn.knnSearch(ser,nearest_index_result,nearest_dist_result,num_knn);   
//获取结果,返回的nearest_index_result、nearest_dist_result矩阵的大小为(ser.rows,num_knn),因为我这里指搜索一个数据点的一个最近邻点,所以返回的
//矩阵大小为(1,1)
	float  nearest_dist=nearest_dist_result.at<float>(0,0);
	int nearest_index=nearest_index_result.at<int>(0,0);

	return nearest_index;
}

最后我发现flann不仅可以构建快速最近邻搜索树,而且还有保存树、读取树的API接口函数。之前搞三角网格曲面,交互的时候,因为有的三角网格模型点非常多,需要经常用到kd-tree,但是如果我把kd-tree构建完后,然后进行某个功能的使用,是用完后,为了避免内存浪费,当然要把它删了。可是我某一时刻要使用另外的一个功能,又要用到kd-tree,这样每次都重复构建kd-tree,感觉好麻烦,这个时候我们就可以用flann的树索引保存的方法,来实现了,废话不多说……

构建kd-tree,并保存。然后通过读取的方式,构建kd树,实现调用方法如下:

//输入n个数据点vec_hogs,搜索点hog的最近邻,返回最近邻的索引
int	 getNearIndex(vector<vector<float>>  vec_hogs,std::vector<float> hog)
{
//把n个数据点转为flann参数矩阵形式
	int n_feature=hog.size();//特征维数
	cv::Mat brow_mat(vec_hogs.size(),n_feature,CV_32FC1);//把数据点存为矩阵,其中,M(i,j)表示第i个点的第j维数据
	for (int i=0;i<vec_hogs.size();i++)
	{
		vector<float>&brow_vec=vec_hogs[i];
		for (int j=0;j<brow_vec.size();j++)
		{
			brow_mat.at<float>(i,j)=brow_vec[j];
		}
	}
//建立kd树
	flann::Index knn( brow_mat,cv::flann::KDTreeIndexParams());
	//把构建树的索引保存下来
	knn.save("kd_treed.fln");

//把数据点hog转换成矩阵  ,矩阵大小为1行, n_feature列,
//如果你要同时搜索m个数据点的最近邻点,那么矩阵为m行,n_feature列
	cv::Mat ser(1,n_feature,CV_32FC1);
	for (int i=0;i<hog.size();i++)
	{
		ser.at<float>(0,i)=hog[i];
	}
//搜索
	int num_knn=1;//这个参数是用于设置搜索最邻近点的个数的,因为我只要搜索一个最近的点,所以设置为1
	cv::Mat nearest_index_result;
	cv::Mat nearest_dist_result;

//直接读取文件 kd_treed.fln,这样可以避免有的时候需要重复搜索最近邻点,而需要重复构建kd树
	//第一个参数必须是原有数据,第二个参数调用函数cv::flann::SavedIndexParams()加载索引
	cv::flann::Index flann_index(brow_mat,cv::flann::SavedIndexParams("kd_treed.fln"));
	//搜索最近邻点
	flann_index.knnSearch(ser,nearest_index_result,nearest_dist_result,num_knn);   

//获取结果,返回的nearest_index_result、nearest_dist_result矩阵的大小为(ser.rows,num_knn),因为我这里指搜索一个数据点的一个最近邻点,所以返回的
//矩阵大小为(1,1)
	float  nearest_dist=nearest_dist_result.at<float>(0,0);
	int nearest_index=nearest_index_result.at<int>(0,0);
	return nearest_index;
}
本文地址: http://blog.csdn.net/hjimce/article/details/47297241     作者:hjimce     联系qq:1393852684    更多资源请关注我的博客:http://blog.csdn.net/hjimce                原创文章,版权所有,转载请保留本行信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值