2015-02-19 7 views
0

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

векторы признаков просеять являются 128 элементов с плавающей точкой массивы, я хранятся списки дескрипторов в std::vector с, как показано на рисунке ниже фрагменте кода:

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

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

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

ответ

1

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

2-й аргумент 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]); 

EDIT

Существует действительно вторая (основная) проблема, связанная с тем, как вы строите 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;` 
+0

Хорошо, я думаю, что это была опечатка в вопросе, это на самом деле ошибки, а не предупреждения. Но расстояния все еще равны ~ 1, inf или nan. Я написали набор для перебора грубой силы, чтобы дважды проверить, не потеряны ли данные по пути, и это работает так, как ожидалось. – Josh

+0

Я отредактировал свой ответ с исправлением основной проблемы. – deltheil

+0

Большое спасибо, это имеет смысл - я думал в режиме Python/np.flatten(). Теперь цифры выглядят разумными. – Josh