Настройка и запрос VlFeat kdtree

Мне удалось заставить работать SIFT в VlFeat, и я хотел бы попробовать сопоставить два набора дескрипторов изображений.

Векторы функций SIFT — это 128-элементные массивы с плавающей точкой, я сохранил списки дескрипторов в std::vectors, как показано в фрагменте ниже:

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«S. Длина извлечения массивов дескрипторов, так что, похоже, данные идут в дерево. Я наметил ключевые точки, и они также выглядят разумно, так что данные довольно нормальные.

Что мне не хватает?

Довольно скудная документация здесь (ссылки на API): http://www.vlfeat.org/api/kdtree.html

0

Решение

Что мне не хватает?

Второй аргумент vl_kdforestsearcher_query принимает указатель на VlKDForestNeighbor:

vl_size
vl_kdforestsearcher_query(
VlKDForestSearcher *self,
VlKDForestNeighbor *neighbors,
vl_size numNeighbors,
void const *query
);

Но здесь вы заявили VlKDForestNeighbor neighbours[2]; а потом прошло &neighbours как 2-й параметр, который не является правильным — ваш компилятор, вероятно, выдал incompatible pointer types предупреждение.

Поскольку вы объявили массив, вы должны вместо этого либо явно передать указатель на 1-го соседа:

int nvisited = vl_kdforestsearcher_query(searcher, &neighbours[0], 2, qrys[i]);

Или, в качестве альтернативы, пусть компилятор сделает это за вас:

int nvisited = vl_kdforestsearcher_query(searcher, neighbours, 2, qrys[i]);

РЕДАКТИРОВАТЬ

Существует действительно вторая (главная) проблема, связанная с тем, как вы строите kd-дерево с помощью ldescriptors.data(),

Здесь вы проходите std::vector<float>* указатель, когда VLFeat ожидает 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;`
1

Другие решения


По вопросам рекламы [email protected]