// Build a kd-tree from a list of elements. All elements must implement // the IKDTreeDomain interface and must have the same dimensionality. KDTree* KDTree_CreateKDTree (ArrayList* exset) { if (ArrayList_Count(exset) == 0) return (NULL); KDTree* cur = KDTree_new0 (); cur->dr = KDTree_GoodCandidate (exset, &cur->splitDim); ArrayList* leftElems = ArrayList_new0 (NULL); ArrayList* rightElems = ArrayList_new0 (NULL); // split the exemplar set into left/right elements relative to the // splitting dimension double bound = IKDTreeDomain_GetDimensionElement (cur->dr, cur->splitDim); int i; for(i=0; i<ArrayList_Count(exset); i++) { IKDTreeDomain* dom = (IKDTreeDomain*) ArrayList_GetItem(exset, i); // ignore the current element if (dom == cur->dr) continue; if (IKDTreeDomain_GetDimensionElement (dom, cur->splitDim) <= bound) { ArrayList_AddItem(leftElems, dom); } else { ArrayList_AddItem(rightElems, dom); } } // recurse cur->left = KDTree_CreateKDTree (leftElems); cur->right = KDTree_CreateKDTree (rightElems); ArrayList_delete(leftElems); ArrayList_delete(rightElems); return (cur); }
ArrayList* MatchKeys_FindMatchesBBF (ArrayList* keys1, ArrayList* keys2) { // TODO: swap so smaller list is searched. ArrayList* al = ArrayList_new0 (NULL); int i; for (i=0; i<ArrayList_Count(keys2); i++) ArrayList_AddItem (al, ArrayList_GetItem(keys2, i)); KDTree* kd = KDTree_CreateKDTree (al); ArrayList_delete(al); ArrayList* matches = ArrayList_new0 (Match_delete); int j; for (j=0; j<ArrayList_Count(keys1); j++) { KeypointN* kp = (KeypointN*) ArrayList_GetItem(keys1, j); ArrayList* kpNNList = (ArrayList*)KDTree_NearestNeighbourListBBF (kd, (IKDTreeDomain*)kp, 2, 40); if (ArrayList_Count(kpNNList) < 2) FatalError ("BUG: less than two neighbours!"); KDTreeBestEntry* be1 = (KDTreeBestEntry*) ArrayList_GetItem(kpNNList, 0); KDTreeBestEntry* be2 = (KDTreeBestEntry*) ArrayList_GetItem(kpNNList, 1); if ((be1->distance / be2->distance) > 0.6) continue; KeypointN* kpN = (KeypointN*)KDTreeBestEntry_Neighbour(be1); ArrayList_AddItem(matches, Match_new (kp, kpN, be1->distance, be2->distance)); /* WriteLine ("(%d,%d) (%d,%d) %d, 2nd: %d", (int)(kp->x + 0.5), (int)(kp->y + 0.5), (int)(kpN->x + 0.5), (int)(kpN->y + 0.5), be1->distance, be2->distance); */ } return (matches); }