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

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

//输入n个数据点vec_hogs,搜索点hog的最近邻,返回最近邻的索引
int	 getNearIndex(vector>  vec_hogs,std::vector 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&brow_vec=vec_hogs[i];
		for (int j=0;j(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(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(0,0);
	int nearest_index=nearest_index_result.at(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>  vec_hogs,std::vector 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&brow_vec=vec_hogs[i];
		for (int j=0;j(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(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(0,0);
	int nearest_index=nearest_index_result.at(0,0);
	return nearest_index;
}
本文地址: http://blog.csdn.net/hjimce/article/details/47297241     作者:hjimce     联系qq:1393852684    更多资源请关注我的博客:http://blog.csdn.net/hjimce                原创文章,版权所有,转载请保留本行信息

你可能感兴趣的:(基础知识)