OpenCV K-d树实现之FLANN (Fast Library for Approximate Nearest Neighbors) 算法实现及解析

k-d树搜索最近点,在opencv中使用FLANN算法,其包含:

1:建树   2.查询

程序见下:

#include "kdtree.h"
#include <iostream>
#include <iomanip> 
#include "cv.h"
#include "highgui.h"  
#include <fstream>
#include "cv.h"
#include "highgui.h"  
#include <vector>    // <vector > STL头文件
#include <stdio.h>
#include "opencv2/objdetect/objdetect.hpp"  
#include "opencv2/features2d/features2d.hpp"  
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/calib3d/calib3d.hpp"  
#include "opencv2/imgproc/imgproc_c.h"
#include <iostream> 


#define EXAMPLAR_NUM 700
#define EXAMPLAR_DIM 3
/****系统可以搜索660个3维点云中的最近点****/
/************保存CvMat型矩阵****************************
输入参数:&VecString:n个点云容器
输出参数:*Matri:转换成对应的3*n矩阵
*************************************************************/
void SaveCvmatToTXT(const CvMat*Matri, const char* filename)
{
std::ofstream  file(filename);  //保存文件


for (int i = 0; i<Matri->rows; i++)
{
for (int j = 0; j<Matri->cols; j++)
{
file << "    " << cvmGet(Matri, i, j);
}
file << std::endl;
}
file.close();
}
/***********读取txt文档保存CvMat型矩阵****************************
输入参数:&VecString:n个点云容器
输出参数:*Matri:转换成对应的3*n矩阵
***************************************************************/
void ReadTxtToCvmat(CvMat*Matri, const char* filename)
{
std::ifstream  file(filename);  //保存文件
double temp;
for (int i = 0; i<Matri->rows; i++)
{
for (int j = 0; j<Matri->cols; j++)
{
file >> temp;
cvmSet(Matri, i, j,temp);
}
}
file.close();
}

int main(int argc, char *argv[])
{

cv::Mat target(10, 3, CV_32F);  //目标点云(用之构建k-d树

ReadTxtToCvmat(&(CvMat)target, "data.txt");
std::cout << "target"<<target<< std::endl;

//1)创建查询树 :(此处构建K-d树)


cv::flann::KDTreeIndexParams indexParams(4);//(此参数用来设置构建的数据结构,此处选择K-d树)
cv::flann::Index kdtree(target, indexParams);//此处用target构建k-d树


//2) 查找 :
/*cv::Point3f pt ;
std::cout << "Input target point:" << std::endl;
std::cin >> pt.x  >> pt.y >> pt.z;
std::vector<float> query;
query.push_back(pt.x);
query.push_back(pt.y);
    query.push_back(pt.z);*/  //可用来手动输入单个要搜索的原始点

cv::Mat source= target;    //原始点
cv::Mat neibours(source.rows, source.cols, CV_32F);//存储搜索到的点

int k =1; //number of nearest neighbors 

cv::Mat indices(source.rows, k, CV_32F);   //装载搜索到的对应点的索引(即neibours在target这个矩阵的行数)
cv::Mat dists(source.rows,k,CV_32F);         //搜索到的最近邻的距离
kdtree.knnSearch(source, indices, dists, k, cv::flann::SearchParams(32));


//std::cout << indices.at<int>(9, 0) << std::endl;
//std::cout << dists.at<float>(9,0) << std::endl;
for (int i = 0; i < neibours.rows; i++)
{
neibours.row(i) = target.row(indices.at<int>(i, 0)) + 0;
}

std::cout << "source=" << source << std::endl;
std::cout << "neibours" << neibours << std::endl;
std::cout << "indices=" << indices << std::endl;
std::cout << "dists=" << dists << std::endl;


system("PAUSE");
return 0;
}

实验结果:

技术分享

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。