Opencv+Kdtree在C++和Python下的使用

12 篇文章 0 订阅
9 篇文章 0 订阅
Opencv+Kdtree在C++和Python下的使用
      最近有个项目使用到Opencv下的flann模块,该模块主要在数据的搜索,搜索速度还算可以,就研究它在C++和Python下的使用方法,关于kdtree的搜索原理,请自行百度.
      Kdtree主要有Tree的加载树和建立树,其中建树主要的场景为:数据第一次初始化及更新;加载则为程序重启时,不需要读取数据重新建树,而节省了时间.

      C++下

      建树

cv::flann::Index Kdtree;
Kdtree.build(Input_Mat,cv::flann::KDTreeIndexParams(1),cvflann::FLANN_DIST_EUCLIDEAN);
    其中: cv::flann::KDTreeIndexParams(1)为建立树的个数,这里选择树的个数为1,源码中默认的为4棵树.需要注意的是,如果建立的树越多,则消耗的时间越长.
    cvflann::FLANN_DIST_EUCLIDEAN:建树时使用欧式距离,Opencv支持的距离类型有限.支持的数据类型如下:
  FLANN_DIST_EUCLIDEAN = 1,
  FLANN_DIST_L2 = 1,
  FLANN_DIST_MANHATTAN = 2,
  FLANN_DIST_L1 = 2,
  FLANN_DIST_MINKOWSKI = 3,
  FLANN_DIST_MAX   = 4,
  FLANN_DIST_HIST_INTERSECT   = 5,
  FLANN_DIST_HELLINGER = 6,
  FLANN_DIST_CHI_SQUARE = 7,
  FLANN_DIST_CS         = 7,
  FLANN_DIST_KULLBACK_LEIBLER  = 8,
  FLANN_DIST_KL                = 8,
  FLANN_DIST_HAMMING          = 9,
    Kdtree建立完毕后,为了以后使用方便,可以将树的模型保存到本地.
Kdtree.save("tree.mat");
cv::FileStorage storage("tree.yml", cv::FileStorage::WRITE);
storage << "kdtree" << Input_Mat;
storage.release();
    将树的模型及输入矩阵保存到本地后,如果后续Input_Mat的数据没有改变,当程序再次启动时,就可以直接从本地加载,加载通过load()函数.

   加载树

   首先,看一下load()函数的原型:
load(InputArray features, const String& filename);
   对应的使用为:
    cv::FileStorage fs("tree.yml", cv::FileStorage::READ);
    fs["kdtree"] >> ClusterCenters;
    fs.release();
    Kdtree.load(ClusterCenters,"tree.mat");

   搜索

    前面的建树或加载树,都是为了搜索时使用的,搜索通过knnSearch
void knnSearch(InputArray query, OutputArray indices,
                   OutputArray dists, int knn, const SearchParams& params=SearchParams());
    query:要查询的矩阵,它的数据类型必须与Input_Mat的类型一致.
    indices:输出的结果的索引
    dists:输出结果对应的距离值,该值为欧式距离的平方.
    knn:索引的top N
    SearchParams:搜索的节点树,如果值为-1,则在树的所有节点进行搜索.
Kdtree.knnSearch(ClusterMembers, matches, distances, 1, cv::flann::SearchParams(-1));
   至此,C++下的Kdtree的建立,加载,搜索完毕,是不是感觉很简单.python下的流程与C++下的是一致的.

Python

kdtree=cv2.flann.Index()//定义flann
input_mat=np.float32(np.random.randn(10,4))//输入矩阵
search_mat=np.float32(np.random.randn(1,4))//检索矩阵
FLANN_INDEX_KDTREE=1//使用kdtree,使用不同的算法如下
    其它的算法定义如下:
    FLANN_INDEX_LINEAR = 0,
    FLANN_INDEX_KDTREE = 1,
    FLANN_INDEX_KMEANS = 2,
    FLANN_INDEX_COMPOSITE = 3,
    FLANN_INDEX_KDTREE_SINGLE = 4,
    FLANN_INDEX_HIERARCHICAL = 5,
    FLANN_INDEX_LSH = 6,
    FLANN_INDEX_SAVED = 254,
    FLANN_INDEX_AUTOTUNED = 255,  
#从本地加载模型
params=dict(algorithm=FLANN_INDEX_KDTREE,trees=1)
def read_yml():
    fs = cv2.FileStorage("tree.yml", cv2.FILE_STORAGE_READ)
    fn = fs.getNode("tree")
    print(fn.mat())
#建树
kdtree.build(input_mat,params)
print("build tree success")
#检索
indices, dists=kdtree.knnSearch(search_mat,2,params=-1)
print("search kdtree")
#输出检索结果
print(indices)
print(np.sqrt(dists))
#使用numpy下的欧式距离验证结果是否正确
print((np.linalg.norm(input_mat-search_mat,axis=1)))
#模型
保存到本地
f=cv2.FileStorage("tree.yml",cv2.FILE_STORAGE_WRITE)
f.write("tree",input_mat)
f.release()   







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值