VlFeat kdtree设置和查询
VlFeat kdtree setup and query
我已经设法使 VlFeat 的 SIFT 实现正常工作,我想尝试匹配两组图像描述符。
SIFT 的特征向量是 128 个元素的浮点数组,我将描述符列表存储在 std::vector
s 中,如下面的代码片段所示:
std::vector<std::vector<float> > ldescriptors = leftImage->descriptors;
std::vector<std::vector<float> > rdescriptors = rightImage->descriptors;
/* KDTree, L1 comparison metric, dimension 128, 1 tree, L1 metric */
VlKDForest* forest = vl_kdforest_new(VL_TYPE_FLOAT, 128, 1, VlDistanceL1);
/* Build the tree from the left descriptors */
vl_kdforest_build(forest, ldescriptors.size(), ldescriptors.data());
/* Searcher object */
VlKDForestSearcher* searcher = vl_kdforest_new_searcher(forest);
VlKDForestNeighbor neighbours[2];
/* Query the first ten points for now */
for(int i=0; i < 10; i++){
int nvisited = vl_kdforestsearcher_query(searcher, &neighbours, 2, rdescriptors[i].data());
cout << nvisited << neighbours[0].distance << neighbours[1].distance;
}
据我所知应该可行,但我得出的所有距离都是 nan
的。描述符数组的长度 checkout 因此似乎确实有数据进入树中。我已经绘制了关键点,它们看起来也很合理,所以数据相当合理。
我错过了什么?
这里的文档相当稀疏(链接到 API):http://www.vlfeat.org/api/kdtree.html
What am I missing?
vl_kdforestsearcher_query
的第二个参数接受指向 VlKDForestNeighbor
的指针:
vl_size
vl_kdforestsearcher_query(
VlKDForestSearcher *self,
VlKDForestNeighbor *neighbors,
vl_size numNeighbors,
void const *query
);
但您在这里声明了 VlKDForestNeighbor neighbours[2];
,然后将 &neighbours
作为第二个参数传递,这是不正确的 - 您的编译器可能发出了 incompatible pointer types
警告。
既然你声明了一个数组,你必须做的是显式传递一个指向第一个邻居的指针:
int nvisited = vl_kdforestsearcher_query(searcher, &neighbours[0], 2, qrys[i]);
或者让编译器为您完成:
int nvisited = vl_kdforestsearcher_query(searcher, neighbours, 2, qrys[i]);
编辑
确实存在第二个(主要)问题,与您使用 ldescriptors.data()
构建 kd 树的方式有关。
当 VLFeat 需要一个 float *
包含所有数据点的连续数组时,您在这里传递一个 std::vector<float>*
指针,并按行主顺序排列。所以你可以做的是以这种格式复制你的数据:
float *data = new float[128*ldescriptors.size()];
for (unsigned int i = 0; i < ldescriptors.size(); i++)
std::copy(ldescriptors[i].begin(), ldescriptors[i].end(), data + 128*i);
vl_kdforest_build(forest, ldescriptors.size(), data);
// ...
// then, right after `vl_kdforest_delete(forest);`
// do a `delete[] data;`
我已经设法使 VlFeat 的 SIFT 实现正常工作,我想尝试匹配两组图像描述符。
SIFT 的特征向量是 128 个元素的浮点数组,我将描述符列表存储在 std::vector
s 中,如下面的代码片段所示:
std::vector<std::vector<float> > ldescriptors = leftImage->descriptors;
std::vector<std::vector<float> > rdescriptors = rightImage->descriptors;
/* KDTree, L1 comparison metric, dimension 128, 1 tree, L1 metric */
VlKDForest* forest = vl_kdforest_new(VL_TYPE_FLOAT, 128, 1, VlDistanceL1);
/* Build the tree from the left descriptors */
vl_kdforest_build(forest, ldescriptors.size(), ldescriptors.data());
/* Searcher object */
VlKDForestSearcher* searcher = vl_kdforest_new_searcher(forest);
VlKDForestNeighbor neighbours[2];
/* Query the first ten points for now */
for(int i=0; i < 10; i++){
int nvisited = vl_kdforestsearcher_query(searcher, &neighbours, 2, rdescriptors[i].data());
cout << nvisited << neighbours[0].distance << neighbours[1].distance;
}
据我所知应该可行,但我得出的所有距离都是 nan
的。描述符数组的长度 checkout 因此似乎确实有数据进入树中。我已经绘制了关键点,它们看起来也很合理,所以数据相当合理。
我错过了什么?
这里的文档相当稀疏(链接到 API):http://www.vlfeat.org/api/kdtree.html
What am I missing?
vl_kdforestsearcher_query
的第二个参数接受指向 VlKDForestNeighbor
的指针:
vl_size
vl_kdforestsearcher_query(
VlKDForestSearcher *self,
VlKDForestNeighbor *neighbors,
vl_size numNeighbors,
void const *query
);
但您在这里声明了 VlKDForestNeighbor neighbours[2];
,然后将 &neighbours
作为第二个参数传递,这是不正确的 - 您的编译器可能发出了 incompatible pointer types
警告。
既然你声明了一个数组,你必须做的是显式传递一个指向第一个邻居的指针:
int nvisited = vl_kdforestsearcher_query(searcher, &neighbours[0], 2, qrys[i]);
或者让编译器为您完成:
int nvisited = vl_kdforestsearcher_query(searcher, neighbours, 2, qrys[i]);
编辑
确实存在第二个(主要)问题,与您使用 ldescriptors.data()
构建 kd 树的方式有关。
当 VLFeat 需要一个 float *
包含所有数据点的连续数组时,您在这里传递一个 std::vector<float>*
指针,并按行主顺序排列。所以你可以做的是以这种格式复制你的数据:
float *data = new float[128*ldescriptors.size()];
for (unsigned int i = 0; i < ldescriptors.size(); i++)
std::copy(ldescriptors[i].begin(), ldescriptors[i].end(), data + 128*i);
vl_kdforest_build(forest, ldescriptors.size(), data);
// ...
// then, right after `vl_kdforest_delete(forest);`
// do a `delete[] data;`