00001
00006
00007
00008
00009
00010
00011
00012
00013
00089 #include "kdtree.h"
00090 #include "generic.h"
00091 #include "random.h"
00092 #include "mathop.h"
00093 #include <stdlib.h>
00094
00095 #if defined(_OPENMP)
00096 #include <omp.h>
00097 #endif
00098
00099 #define VL_HEAP_prefix vl_kdforest_search_heap
00100 #define VL_HEAP_type VlKDForestSearchState
00101 #define VL_HEAP_cmp(v,x,y) (v[x].distanceLowerBound - v[y].distanceLowerBound)
00102 #include "heap-def.h"
00103
00104 #define VL_HEAP_prefix vl_kdtree_split_heap
00105 #define VL_HEAP_type VlKDTreeSplitDimension
00106 #define VL_HEAP_cmp(v,x,y) (v[x].variance - v[y].variance)
00107 #include "heap-def.h"
00108
00109 #define VL_HEAP_prefix vl_kdforest_neighbor_heap
00110 #define VL_HEAP_type VlKDForestNeighbor
00111 #define VL_HEAP_cmp(v,x,y) (v[y].distance - v[x].distance)
00112 #include "heap-def.h"
00113
00119 static vl_uindex
00120 vl_kdtree_node_new (VlKDTree * tree, vl_uindex parentIndex)
00121 {
00122 VlKDTreeNode * node = NULL ;
00123 vl_uindex nodeIndex = tree->numUsedNodes ;
00124 tree -> numUsedNodes += 1 ;
00125
00126 assert (tree->numUsedNodes <= tree->numAllocatedNodes) ;
00127
00128 node = tree->nodes + nodeIndex ;
00129 node -> parent = parentIndex ;
00130 node -> lowerChild = 0 ;
00131 node -> upperChild = 0 ;
00132 node -> splitDimension = 0 ;
00133 node -> splitThreshold = 0 ;
00134 return nodeIndex ;
00135 }
00136
00142 VL_INLINE int
00143 vl_kdtree_compare_index_entries (void const * a,
00144 void const * b)
00145 {
00146 double delta =
00147 ((VlKDTreeDataIndexEntry const*)a) -> value -
00148 ((VlKDTreeDataIndexEntry const*)b) -> value ;
00149 if (delta < 0) return -1 ;
00150 if (delta > 0) return +1 ;
00151 return 0 ;
00152 }
00153
00165 static void
00166 vl_kdtree_build_recursively
00167 (VlKDForest * forest,
00168 VlKDTree * tree, vl_uindex nodeIndex,
00169 vl_uindex dataBegin, vl_uindex dataEnd,
00170 unsigned int depth)
00171 {
00172 vl_uindex d, i, medianIndex, splitIndex ;
00173 VlKDTreeNode * node = tree->nodes + nodeIndex ;
00174 VlKDTreeSplitDimension * splitDimension ;
00175
00176
00177 if (dataEnd - dataBegin <= 1) {
00178 if (tree->depth < depth) tree->depth = depth ;
00179 node->lowerChild = - dataBegin - 1;
00180 node->upperChild = - dataEnd - 1 ;
00181 return ;
00182 }
00183
00184
00185 forest->splitHeapNumNodes = 0 ;
00186 for (d = 0 ; d < forest->dimension ; ++ d) {
00187 double mean = 0 ;
00188 double secondMoment = 0 ;
00189 double variance = 0 ;
00190 vl_size numSamples = VL_KDTREE_VARIANCE_EST_NUM_SAMPLES;
00191 vl_bool useAllData = VL_FALSE;
00192
00193 if(dataEnd - dataBegin <= VL_KDTREE_VARIANCE_EST_NUM_SAMPLES) {
00194 useAllData = VL_TRUE;
00195 numSamples = dataEnd - dataBegin;
00196 }
00197
00198 for (i = 0; i < numSamples ; ++ i) {
00199 vl_uint32 sampleIndex;
00200 vl_index di;
00201 double datum ;
00202
00203 if(useAllData == VL_TRUE) {
00204 sampleIndex = (vl_uint32)i;
00205 } else {
00206 sampleIndex = (vl_rand_uint32(forest->rand) % VL_KDTREE_VARIANCE_EST_NUM_SAMPLES);
00207 }
00208 sampleIndex += dataBegin;
00209
00210 di = tree->dataIndex[sampleIndex].index ;
00211
00212 switch(forest->dataType) {
00213 case VL_TYPE_FLOAT: datum = ((float const*)forest->data)
00214 [di * forest->dimension + d] ;
00215 break ;
00216 case VL_TYPE_DOUBLE: datum = ((double const*)forest->data)
00217 [di * forest->dimension + d] ;
00218 break ;
00219 default:
00220 abort() ;
00221 }
00222 mean += datum ;
00223 secondMoment += datum * datum ;
00224 }
00225
00226 mean /= numSamples ;
00227 secondMoment /= numSamples ;
00228 variance = secondMoment - mean * mean ;
00229
00230 if (variance <= 0) continue ;
00231
00232
00233 if (forest->splitHeapNumNodes < forest->splitHeapSize) {
00234 VlKDTreeSplitDimension * splitDimension
00235 = forest->splitHeapArray + forest->splitHeapNumNodes ;
00236 splitDimension->dimension = (unsigned int)d ;
00237 splitDimension->mean = mean ;
00238 splitDimension->variance = variance ;
00239 vl_kdtree_split_heap_push (forest->splitHeapArray, &forest->splitHeapNumNodes) ;
00240 } else {
00241 VlKDTreeSplitDimension * splitDimension = forest->splitHeapArray + 0 ;
00242 if (splitDimension->variance < variance) {
00243 splitDimension->dimension = (unsigned int)d ;
00244 splitDimension->mean = mean ;
00245 splitDimension->variance = variance ;
00246 vl_kdtree_split_heap_update (forest->splitHeapArray, forest->splitHeapNumNodes, 0) ;
00247 }
00248 }
00249 }
00250
00251
00252 if (forest->splitHeapNumNodes == 0) {
00253 node->lowerChild = - dataBegin - 1 ;
00254 node->upperChild = - dataEnd - 1 ;
00255 return ;
00256 }
00257
00258
00259 splitDimension = forest->splitHeapArray
00260 + (vl_rand_uint32(forest->rand) % VL_MIN(forest->splitHeapSize, forest->splitHeapNumNodes)) ;
00261
00262 node->splitDimension = splitDimension->dimension ;
00263
00264
00265 for (i = dataBegin ; i < dataEnd ; ++ i) {
00266 vl_index di = tree->dataIndex[i].index ;
00267 double datum ;
00268 switch (forest->dataType) {
00269 case VL_TYPE_FLOAT: datum = ((float const*)forest->data)
00270 [di * forest->dimension + splitDimension->dimension] ;
00271 break ;
00272 case VL_TYPE_DOUBLE: datum = ((double const*)forest->data)
00273 [di * forest->dimension + splitDimension->dimension] ;
00274 break ;
00275 default:
00276 abort() ;
00277 }
00278 tree->dataIndex [i] .value = datum ;
00279 }
00280 qsort (tree->dataIndex + dataBegin,
00281 dataEnd - dataBegin,
00282 sizeof (VlKDTreeDataIndexEntry),
00283 vl_kdtree_compare_index_entries) ;
00284
00285
00286 switch (forest->thresholdingMethod) {
00287 case VL_KDTREE_MEAN :
00288 node->splitThreshold = splitDimension->mean ;
00289 for (splitIndex = dataBegin ;
00290 splitIndex < dataEnd && tree->dataIndex[splitIndex].value <= node->splitThreshold ;
00291 ++ splitIndex) ;
00292 splitIndex -= 1 ;
00293
00294
00295
00296
00297
00298
00299 if (dataBegin <= splitIndex && splitIndex + 1 < dataEnd) break ;
00300
00301 case VL_KDTREE_MEDIAN :
00302 medianIndex = (dataBegin + dataEnd - 1) / 2 ;
00303 splitIndex = medianIndex ;
00304 node -> splitThreshold = tree->dataIndex[medianIndex].value ;
00305 break ;
00306
00307 default:
00308 abort() ;
00309 }
00310
00311
00312 node->lowerChild = vl_kdtree_node_new (tree, nodeIndex) ;
00313 vl_kdtree_build_recursively (forest, tree, node->lowerChild, dataBegin, splitIndex + 1, depth + 1) ;
00314
00315 node->upperChild = vl_kdtree_node_new (tree, nodeIndex) ;
00316 vl_kdtree_build_recursively (forest, tree, node->upperChild, splitIndex + 1, dataEnd, depth + 1) ;
00317 }
00318
00331 VlKDForest *
00332 vl_kdforest_new (vl_type dataType,
00333 vl_size dimension, vl_size numTrees, VlVectorComparisonType distance)
00334 {
00335 VlKDForest * self = vl_calloc (sizeof(VlKDForest), 1) ;
00336
00337 assert(dataType == VL_TYPE_FLOAT || dataType == VL_TYPE_DOUBLE) ;
00338 assert(dimension >= 1) ;
00339 assert(numTrees >= 1) ;
00340
00341 self -> rand = vl_get_rand () ;
00342 self -> dataType = dataType ;
00343 self -> numData = 0 ;
00344 self -> data = 0 ;
00345 self -> dimension = dimension ;
00346 self -> numTrees = numTrees ;
00347 self -> trees = 0 ;
00348 self -> thresholdingMethod = VL_KDTREE_MEDIAN ;
00349 self -> splitHeapSize = VL_MIN(numTrees, VL_KDTREE_SPLIT_HEAP_SIZE) ;
00350 self -> splitHeapNumNodes = 0 ;
00351 self -> distance = distance;
00352 self -> maxNumNodes = 0 ;
00353 self -> numSearchers = 0 ;
00354 self -> headSearcher = 0 ;
00355
00356 switch (self->dataType) {
00357 case VL_TYPE_FLOAT:
00358 self -> distanceFunction = (void(*)(void))
00359 vl_get_vector_comparison_function_f (distance) ;
00360 break;
00361 case VL_TYPE_DOUBLE :
00362 self -> distanceFunction = (void(*)(void))
00363 vl_get_vector_comparison_function_d (distance) ;
00364 break ;
00365 default :
00366 abort() ;
00367 }
00368
00369 return self ;
00370 }
00371
00387 VlKDForestSearcher *
00388 vl_kdforest_new_searcher (VlKDForest * kdforest)
00389 {
00390 VlKDForestSearcher * self = vl_calloc(sizeof(VlKDForestSearcher), 1);
00391 if(kdforest->numSearchers == 0) {
00392 kdforest->headSearcher = self;
00393 self->previous = NULL;
00394 self->next = NULL;
00395 } else {
00396 VlKDForestSearcher * lastSearcher = kdforest->headSearcher;
00397 while (1) {
00398 if(lastSearcher->next) {
00399 lastSearcher = lastSearcher->next;
00400 } else {
00401 lastSearcher->next = self;
00402 self->previous = lastSearcher;
00403 self->next = NULL;
00404 break;
00405 }
00406 }
00407 }
00408
00409 kdforest->numSearchers++;
00410
00411 self->forest = kdforest;
00412 self->searchHeapArray = vl_malloc (sizeof(VlKDForestSearchState) * kdforest->maxNumNodes) ;
00413 self->searchIdBook = vl_calloc (sizeof(vl_uindex), kdforest->numData) ;
00414 return self ;
00415 }
00416
00422 void
00423 vl_kdforestsearcher_delete (VlKDForestSearcher * self)
00424 {
00425 if (self->previous && self->next) {
00426 self->previous->next = self->next;
00427 self->next->previous = self->previous;
00428 } else if (self->previous && !self->next) {
00429 self->previous->next = NULL;
00430 } else if (!self->previous && self->next) {
00431 self->next->previous = NULL;
00432 self->forest->headSearcher = self->next;
00433 } else {
00434 self->forest->headSearcher = NULL;
00435 }
00436 self->forest->numSearchers -- ;
00437 vl_free(self->searchHeapArray) ;
00438 vl_free(self->searchIdBook) ;
00439 vl_free(self) ;
00440 }
00441
00442 VlKDForestSearcher *
00443 vl_kdforest_get_searcher (VlKDForest const * self, vl_uindex pos)
00444 {
00445 VlKDForestSearcher * lastSearcher = self->headSearcher ;
00446 vl_uindex i ;
00447
00448 for(i = 0; (i < pos) & (lastSearcher != NULL) ; ++i) {
00449 lastSearcher = lastSearcher->next ;
00450 }
00451 return lastSearcher ;
00452 }
00453
00460 void
00461 vl_kdforest_delete (VlKDForest * self)
00462 {
00463 vl_uindex ti ;
00464 VlKDForestSearcher * searcher ;
00465
00466 while ((searcher = vl_kdforest_get_searcher(self, 0))) {
00467 vl_kdforestsearcher_delete(searcher) ;
00468 }
00469
00470 if (self->trees) {
00471 for (ti = 0 ; ti < self->numTrees ; ++ ti) {
00472 if (self->trees[ti]) {
00473 if (self->trees[ti]->nodes) vl_free (self->trees[ti]->nodes) ;
00474 if (self->trees[ti]->dataIndex) vl_free (self->trees[ti]->dataIndex) ;
00475 vl_free (self->trees[ti]) ;
00476 }
00477 }
00478 vl_free (self->trees) ;
00479 }
00480 vl_free (self) ;
00481 }
00482
00490 static void
00491 vl_kdtree_calc_bounds_recursively (VlKDTree * tree,
00492 vl_uindex nodeIndex, double * searchBounds)
00493 {
00494 VlKDTreeNode * node = tree->nodes + nodeIndex ;
00495 vl_uindex i = node->splitDimension ;
00496 double t = node->splitThreshold ;
00497
00498 node->lowerBound = searchBounds [2 * i + 0] ;
00499 node->upperBound = searchBounds [2 * i + 1] ;
00500
00501
00502
00503 if (node->lowerChild > 0) {
00504 searchBounds [2 * i + 1] = t ;
00505 vl_kdtree_calc_bounds_recursively (tree, node->lowerChild, searchBounds) ;
00506 searchBounds [2 * i + 1] = node->upperBound ;
00507 }
00508 if (node->upperChild > 0) {
00509 searchBounds [2 * i + 0] = t ;
00510 vl_kdtree_calc_bounds_recursively (tree, node->upperChild, searchBounds) ;
00511 searchBounds [2 * i + 0] = node->lowerBound ;
00512 }
00513 }
00514
00529 void
00530 vl_kdforest_build (VlKDForest * self, vl_size numData, void const * data)
00531 {
00532 vl_uindex di, ti ;
00533 vl_size maxNumNodes ;
00534 double * searchBounds;
00535
00536 assert(data) ;
00537 assert(numData >= 1) ;
00538
00539
00540 self->data = data ;
00541 self->numData = numData ;
00542 self->trees = vl_malloc (sizeof(VlKDTree*) * self->numTrees) ;
00543 maxNumNodes = 0 ;
00544
00545 for (ti = 0 ; ti < self->numTrees ; ++ ti) {
00546 self->trees[ti] = vl_malloc (sizeof(VlKDTree)) ;
00547 self->trees[ti]->dataIndex = vl_malloc (sizeof(VlKDTreeDataIndexEntry) * self->numData) ;
00548 for (di = 0 ; di < self->numData ; ++ di) {
00549 self->trees[ti]->dataIndex[di].index = di ;
00550 }
00551 self->trees[ti]->numUsedNodes = 0 ;
00552
00553 self->trees[ti]->numAllocatedNodes = 2 * self->numData - 1 ;
00554 self->trees[ti]->nodes = vl_malloc (sizeof(VlKDTreeNode) * self->trees[ti]->numAllocatedNodes) ;
00555 self->trees[ti]->depth = 0 ;
00556 vl_kdtree_build_recursively (self, self->trees[ti],
00557 vl_kdtree_node_new(self->trees[ti], 0), 0,
00558 self->numData, 0) ;
00559 maxNumNodes += self->trees[ti]->numUsedNodes ;
00560 }
00561
00562 searchBounds = vl_malloc(sizeof(double) * 2 * self->dimension);
00563
00564 for (ti = 0 ; ti < self->numTrees ; ++ ti) {
00565 double * iter = searchBounds ;
00566 double * end = iter + 2 * self->dimension ;
00567 while (iter < end) {
00568 *iter++ = - VL_INFINITY_F ;
00569 *iter++ = + VL_INFINITY_F ;
00570 }
00571
00572 vl_kdtree_calc_bounds_recursively (self->trees[ti], 0, searchBounds) ;
00573 }
00574
00575 vl_free(searchBounds);
00576 self -> maxNumNodes = maxNumNodes;
00577 }
00578
00579
00584 vl_uindex
00585 vl_kdforest_query_recursively (VlKDForestSearcher * searcher,
00586 VlKDTree * tree,
00587 vl_uindex nodeIndex,
00588 VlKDForestNeighbor * neighbors,
00589 vl_size numNeighbors,
00590 vl_size * numAddedNeighbors,
00591 double dist,
00592 void const * query)
00593 {
00594
00595 VlKDTreeNode const * node = tree->nodes + nodeIndex ;
00596 vl_uindex i = node->splitDimension ;
00597 vl_index nextChild, saveChild ;
00598 double delta, saveDist ;
00599 double x ;
00600 double x1 = node->lowerBound ;
00601 double x2 = node->splitThreshold ;
00602 double x3 = node->upperBound ;
00603 VlKDForestSearchState * searchState ;
00604
00605 searcher->searchNumRecursions ++ ;
00606
00607 switch (searcher->forest->dataType) {
00608 case VL_TYPE_FLOAT :
00609 x = ((float const*) query)[i] ;
00610 break ;
00611 case VL_TYPE_DOUBLE :
00612 x = ((double const*) query)[i] ;
00613 break ;
00614 default :
00615 abort() ;
00616 }
00617
00618
00619 if (node->lowerChild < 0) {
00620
00621 vl_index begin = - node->lowerChild - 1 ;
00622 vl_index end = - node->upperChild - 1 ;
00623 vl_index iter ;
00624
00625 for (iter = begin ;
00626 iter < end &&
00627 (searcher->forest->searchMaxNumComparisons == 0 ||
00628 searcher->searchNumComparisons < searcher->forest->searchMaxNumComparisons) ;
00629 ++ iter) {
00630
00631 vl_index di = tree->dataIndex [iter].index ;
00632
00633
00634
00635 if (searcher->searchIdBook[di] == searcher->searchId) continue ;
00636 searcher->searchIdBook[di] = searcher->searchId ;
00637
00638
00639 switch (searcher->forest->dataType) {
00640 case VL_TYPE_FLOAT:
00641 dist = ((VlFloatVectorComparisonFunction)searcher->forest->distanceFunction)
00642 (searcher->forest->dimension,
00643 ((float const *)query),
00644 ((float const*)searcher->forest->data) + di * searcher->forest->dimension) ;
00645 break ;
00646 case VL_TYPE_DOUBLE:
00647 dist = ((VlDoubleVectorComparisonFunction)searcher->forest->distanceFunction)
00648 (searcher->forest->dimension,
00649 ((double const *)query),
00650 ((double const*)searcher->forest->data) + di * searcher->forest->dimension) ;
00651 break ;
00652 default:
00653 abort() ;
00654 }
00655 searcher->searchNumComparisons += 1 ;
00656
00657
00658 if (*numAddedNeighbors < numNeighbors) {
00659 VlKDForestNeighbor * newNeighbor = neighbors + *numAddedNeighbors ;
00660 newNeighbor->index = di ;
00661 newNeighbor->distance = dist ;
00662 vl_kdforest_neighbor_heap_push (neighbors, numAddedNeighbors) ;
00663 } else {
00664 VlKDForestNeighbor * largestNeighbor = neighbors + 0 ;
00665 if (largestNeighbor->distance > dist) {
00666 largestNeighbor->index = di ;
00667 largestNeighbor->distance = dist ;
00668 vl_kdforest_neighbor_heap_update (neighbors, *numAddedNeighbors, 0) ;
00669 }
00670 }
00671 }
00672
00673
00674 return nodeIndex ;
00675 }
00676
00677 #if 0
00678 assert (x1 <= x2 && x2 <= x3) ;
00679 assert (node->lowerChild >= 0) ;
00680 assert (node->upperChild >= 0) ;
00681 #endif
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 delta = x - x2 ;
00692 saveDist = dist + delta*delta ;
00693
00694 if (x <= x2) {
00695 nextChild = node->lowerChild ;
00696 saveChild = node->upperChild ;
00697 if (x <= x1) {
00698 delta = x - x1 ;
00699 saveDist -= delta*delta ;
00700 }
00701 } else {
00702 nextChild = node->upperChild ;
00703 saveChild = node->lowerChild ;
00704 if (x > x3) {
00705 delta = x - x3 ;
00706 saveDist -= delta*delta ;
00707 }
00708 }
00709
00710 if (*numAddedNeighbors < numNeighbors || neighbors[0].distance > saveDist) {
00711 searchState = searcher->searchHeapArray + searcher->searchHeapNumNodes ;
00712 searchState->tree = tree ;
00713 searchState->nodeIndex = saveChild ;
00714 searchState->distanceLowerBound = saveDist ;
00715 vl_kdforest_search_heap_push (searcher->searchHeapArray ,
00716 &searcher->searchHeapNumNodes) ;
00717 }
00718
00719 return vl_kdforest_query_recursively (searcher,
00720 tree,
00721 nextChild,
00722 neighbors,
00723 numNeighbors,
00724 numAddedNeighbors,
00725 dist,
00726 query) ;
00727 }
00728
00743 vl_size
00744 vl_kdforest_query (VlKDForest * self,
00745 VlKDForestNeighbor * neighbors,
00746 vl_size numNeighbors,
00747 void const * query)
00748 {
00749 VlKDForestSearcher * searcher = vl_kdforest_get_searcher(self, 0) ;
00750 if (searcher == NULL) {
00751 searcher = vl_kdforest_new_searcher(self) ;
00752 }
00753 return vl_kdforestsearcher_query(searcher,
00754 neighbors,
00755 numNeighbors,
00756 query) ;
00757 }
00758
00773 vl_size
00774 vl_kdforestsearcher_query (VlKDForestSearcher * self,
00775 VlKDForestNeighbor * neighbors,
00776 vl_size numNeighbors,
00777 void const * query)
00778 {
00779
00780 vl_uindex i, ti ;
00781 vl_bool exactSearch = self->forest->searchMaxNumComparisons == 0 ;
00782
00783 VlKDForestSearchState * searchState ;
00784 vl_size numAddedNeighbors = 0 ;
00785
00786 assert (neighbors) ;
00787 assert (numNeighbors > 0) ;
00788 assert (query) ;
00789
00790
00791 self -> searchId += 1 ;
00792 self -> searchNumRecursions = 0 ;
00793
00794 self->searchNumComparisons = 0 ;
00795 self->searchNumSimplifications = 0 ;
00796
00797
00798 self->searchHeapNumNodes = 0 ;
00799 for (ti = 0 ; ti < self->forest->numTrees ; ++ ti) {
00800 searchState = self->searchHeapArray + self->searchHeapNumNodes ;
00801 searchState -> tree = self->forest->trees[ti] ;
00802 searchState -> nodeIndex = 0 ;
00803 searchState -> distanceLowerBound = 0 ;
00804
00805 vl_kdforest_search_heap_push (self->searchHeapArray, &self->searchHeapNumNodes) ;
00806 }
00807
00808
00809 while (exactSearch || self->searchNumComparisons < self->forest->searchMaxNumComparisons)
00810 {
00811
00812 VlKDForestSearchState * searchState ;
00813
00814
00815 if (self->searchHeapNumNodes == 0) {
00816 break ;
00817 }
00818 searchState = self->searchHeapArray +
00819 vl_kdforest_search_heap_pop (self->searchHeapArray, &self->searchHeapNumNodes) ;
00820
00821 if (numAddedNeighbors == numNeighbors &&
00822 neighbors[0].distance < searchState->distanceLowerBound) {
00823 self->searchNumSimplifications ++ ;
00824 break ;
00825 }
00826 vl_kdforest_query_recursively (self,
00827 searchState->tree,
00828 searchState->nodeIndex,
00829 neighbors,
00830 numNeighbors,
00831 &numAddedNeighbors,
00832 searchState->distanceLowerBound,
00833 query) ;
00834 }
00835
00836
00837 for (i = numAddedNeighbors ; i < numNeighbors ; ++ i) {
00838 neighbors[i].index = -1 ;
00839 neighbors[i].distance = VL_NAN_F ;
00840 }
00841
00842 while (numAddedNeighbors) {
00843 vl_kdforest_neighbor_heap_pop (neighbors, &numAddedNeighbors) ;
00844 }
00845
00846 return self->searchNumComparisons ;
00847 }
00848
00869 vl_size
00870 vl_kdforest_query_with_array (VlKDForest * self,
00871 vl_uint32 * indexes,
00872 vl_size numNeighbors,
00873 vl_size numQueries,
00874 void * distances,
00875 void const * queries)
00876 {
00877 vl_size numComparisons = 0;
00878 vl_type dataType = vl_kdforest_get_data_type(self) ;
00879 vl_size dimension = vl_kdforest_get_data_dimension(self) ;
00880
00881 #ifdef _OPENMP
00882 #pragma omp parallel default(shared) num_threads(vl_get_max_threads())
00883 #endif
00884 {
00885 vl_index qi ;
00886 vl_size thisNumComparisons = 0 ;
00887 VlKDForestSearcher * searcher ;
00888 VlKDForestNeighbor * neighbors ;
00889
00890 #ifdef _OPENMP
00891 #pragma omp critical
00892 #endif
00893 {
00894 searcher = vl_kdforest_new_searcher(self) ;
00895 neighbors = vl_calloc (sizeof(VlKDForestNeighbor), numNeighbors) ;
00896 }
00897
00898 #ifdef _OPENMP
00899 #pragma omp for
00900 #endif
00901 for(qi = 0 ; qi < (signed)numQueries; ++ qi) {
00902 switch (dataType) {
00903 case VL_TYPE_FLOAT: {
00904 vl_size ni;
00905 thisNumComparisons += vl_kdforestsearcher_query (searcher, neighbors, numNeighbors,
00906 (float const *) (queries) + qi * dimension) ;
00907 for (ni = 0 ; ni < numNeighbors ; ++ni) {
00908 indexes [qi*numNeighbors + ni] = (vl_uint32) neighbors[ni].index ;
00909 if (distances){
00910 *((float*)distances + qi*numNeighbors + ni) = neighbors[ni].distance ;
00911 }
00912 }
00913 break ;
00914 }
00915 case VL_TYPE_DOUBLE: {
00916 vl_size ni;
00917 thisNumComparisons += vl_kdforestsearcher_query (searcher, neighbors, numNeighbors,
00918 (double const *) (queries) + qi * dimension) ;
00919 for (ni = 0 ; ni < numNeighbors ; ++ni) {
00920 indexes [qi*numNeighbors + ni] = (vl_uint32) neighbors[ni].index ;
00921 if (distances){
00922 *((double*)distances + qi*numNeighbors + ni) = neighbors[ni].distance ;
00923 }
00924 }
00925 break ;
00926 }
00927 default:
00928 abort() ;
00929 }
00930 }
00931
00932 #ifdef _OPENMP
00933 #pragma omp critical
00934 #endif
00935 {
00936 numComparisons += thisNumComparisons ;
00937 vl_kdforestsearcher_delete (searcher) ;
00938 vl_free (neighbors) ;
00939 }
00940 }
00941 return numComparisons ;
00942 }
00943
00951 vl_size
00952 vl_kdforest_get_num_nodes_of_tree (VlKDForest const * self, vl_uindex treeIndex)
00953 {
00954 assert (treeIndex < self->numTrees) ;
00955 return self->trees[treeIndex]->numUsedNodes ;
00956 }
00957
00965 vl_size
00966 vl_kdforest_get_depth_of_tree (VlKDForest const * self, vl_uindex treeIndex)
00967 {
00968 assert (treeIndex < self->numTrees) ;
00969 return self->trees[treeIndex]->depth ;
00970 }
00971
00979 vl_size
00980 vl_kdforest_get_num_trees (VlKDForest const * self)
00981 {
00982 return self->numTrees ;
00983 }
00984
00997 void
00998 vl_kdforest_set_max_num_comparisons (VlKDForest * self, vl_size n)
00999 {
01000 self->searchMaxNumComparisons = n ;
01001 }
01002
01012 vl_size
01013 vl_kdforest_get_max_num_comparisons (VlKDForest * self)
01014 {
01015 return self->searchMaxNumComparisons ;
01016 }
01017
01026 void
01027 vl_kdforest_set_thresholding_method (VlKDForest * self, VlKDTreeThresholdingMethod method)
01028 {
01029 assert(method == VL_KDTREE_MEDIAN || method == VL_KDTREE_MEAN) ;
01030 self->thresholdingMethod = method ;
01031 }
01032
01042 VlKDTreeThresholdingMethod
01043 vl_kdforest_get_thresholding_method (VlKDForest const * self)
01044 {
01045 return self->thresholdingMethod ;
01046 }
01047
01054 vl_size
01055 vl_kdforest_get_data_dimension (VlKDForest const * self)
01056 {
01057 return self->dimension ;
01058 }
01059
01066 vl_type
01067 vl_kdforest_get_data_type (VlKDForest const * self)
01068 {
01069 return self->dataType ;
01070 }
01071
01078 VlKDForest *
01079 vl_kdforestsearcher_get_forest (VlKDForestSearcher const * self)
01080 {
01081 return self->forest;
01082 }