Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

KDTree.cc

Go to the documentation of this file.
00001 #include "KDTree.h"
00002 #include "keypoint.h"
00003 #include "PQueue.h"
00004 #include <iostream>
00005 #include <cmath>
00006 #include <limits>
00007 
00008 using namespace std;
00009 
00010 void KDTree::computeMeans(std::vector< std::vector <double> >& vals){
00011   size_t i, j;
00012   size_t numDimensions = keypts[0]->desc.size();
00013   size_t numKeypoints = keypts.size();
00014   
00015   mean.clear();
00016   
00017   for (i = 0; i < numDimensions; i++){
00018     vector<double> valsElem;
00019     double sum = 0.0f;
00020     for(j = 0; j < numKeypoints; j++){
00021       valsElem.push_back(keypts[j]->desc[i]);
00022       sum += valsElem[j];
00023     }
00024     vals.push_back(valsElem);
00025     mean.push_back((double)sum / (double)numKeypoints);
00026   }
00027   
00028 }
00029 
00030 // This should only be called after computeMeans has been executed
00031 int KDTree::computeVariances(){
00032   
00033   size_t i, j;
00034   size_t numDimensions = keypts[0]->desc.size();
00035   size_t numKeypoints = keypts.size();
00036   
00037   double maxVariance = -1.0f;
00038   size_t    maxVarAxis  = -1u;
00039   
00040   variance.clear();
00041   
00042   for (i = 0; i < numDimensions; i++){
00043     double sumSqDiff = 0.0f;
00044     for(j = 0; j < numKeypoints; j++){
00045       double diff = keypts[j]->desc[i] - mean[i];
00046       sumSqDiff += diff * diff;
00047     }
00048     double v = (double)sumSqDiff / (double)numKeypoints;
00049     if (v > maxVariance){
00050       maxVarAxis = i;
00051       maxVariance = v;
00052     }
00053     variance.push_back(v);
00054   }
00055   
00056   return (int)maxVarAxis;
00057 }
00058 
00059 KDTree::KDTree(const std::vector<keypoint*>& C)
00060   : isLeaf(), keypts(), axis(0), variance(), mean(), median(), leftChild(NULL), rightChild(NULL), height(0)
00061 {
00062   // Make copy of C
00063   keypts.insert(keypts.end(), C.begin(), C.end());
00064   
00065 /*
00066   cout << "# of clusters: " << clusters.size() << endl;
00067   for (int i = 0; i < (int)clusters.size(); i++){
00068     for (int j = 0; j < KEYPOINTDIM; j++){
00069       cout << clusters[i]->aveDesc[j] << "\t";
00070     }
00071     cout << endl << endl;
00072   }
00073 */
00074   
00075   if (keypts.size() <= 1){
00076     // we're done
00077     makeLeaf();
00078   } else {
00079     isLeaf = false;
00080     vector< vector<double> > vals;
00081     computeMeans(vals);
00082     axis = computeVariances();
00083     median = computePositionK(vals[axis], vals[axis].size() / 2);
00084     
00085     // Partition
00086     vector<keypoint*> left, right;
00087     size_t size = vals[axis].size();
00088     for (size_t i = 0; i < size; i++){
00089       if (vals[axis][i] < median){
00090         left.push_back(keypts[i]);
00091       }else{
00092         right.push_back(keypts[i]);
00093       }
00094     }
00095     
00096     if (left.size() == 0 || right.size() == 0){
00097       // We do NOT want this to happen,
00098       // as we end up with all the elements piling to the same side everytime,
00099       // so we create an infinitely deep branch
00100       // Look for next best variance to use
00101       vector<axisVarPair> pairs;
00102       for (int i = 0; i < KEYPOINTDIM; i++){
00103         axisVarPair pair;
00104         pair.axis = i;
00105         pair.variance = variance[i];
00106         pairs.push_back(pair);
00107       }
00108       sort(pairs.begin(), pairs.end());
00109       // Skip the first(best) variance, since it doesn't work
00110       for (int j = 1; j < KEYPOINTDIM; j++){
00111         axis = pairs[j].axis;
00112         median = computePositionK(vals[axis], vals[axis].size() / 2);
00113         left.clear();
00114         right.clear();
00115         for (size_t i = 0; i < size; i++){
00116           if (vals[axis][i] < median){
00117             left.push_back(keypts[i]);
00118           }else{
00119             right.push_back(keypts[i]);
00120           }
00121         }
00122         if (left.size() != 0 && right.size() != 0) break;
00123       }
00124     }
00125     
00126     if (left.size() == 0 || right.size() == 0){
00127       // Cannot partition on ANY axis's median
00128       makeLeaf();
00129 /*
00130       cout << "Unable to partition " << clusters.size() << "!\n";
00131       for (int i = 0; i < (int)clusters.size(); i++){
00132         for (int j = 0; j < KEYPOINTDIM; j++){
00133           cout << clusters[i]->aveDesc[j] << "\t";
00134         }
00135         cout << endl << endl;
00136       }
00137       cout << endl;
00138 */
00139     }else{
00140       // Build subtrees
00141       leftChild = new KDTree(left);
00142       rightChild = new KDTree(right);
00143       
00144       height = 1 + ((leftChild->height > rightChild->height) ? leftChild->height : rightChild->height);
00145     }
00146 
00147   }
00148 }
00149 
00150 KDTree::~KDTree(){
00151   if (leftChild)  delete leftChild;
00152   if (rightChild) delete rightChild;
00153 }
00154 
00155 void KDTree::makeLeaf(){
00156   if (leftChild)  delete leftChild;
00157   if (rightChild) delete rightChild;
00158   leftChild  = NULL;
00159   rightChild = NULL;
00160   isLeaf     = true;
00161   height     = 0;
00162 }
00163 
00164 bool KDTree::isleaf(){
00165   return isLeaf;
00166 }
00167 
00168 
00169 const std::vector<keypoint*>& KDTree::getKeypoints(){
00170   return keypts;
00171 }
00172 
00173 
00174 int KDTree::getAxis(){
00175   return axis;
00176 }
00177 
00178 
00179 double KDTree::getVariance(int x){
00180   return variance[x];
00181 }
00182 
00183 
00184 double KDTree::getMean(int x){
00185   return mean[x];
00186 }
00187 
00188 
00189 double KDTree::getMedian(){
00190   return median;
00191 }
00192 
00193 
00194 KDTree* KDTree::getLeftChild(){
00195   return leftChild;
00196 }
00197 
00198 
00199 KDTree* KDTree::getRightChild(){
00200   return rightChild;
00201 }
00202 
00203 
00204 int KDTree::getHeight(){
00205   return height;
00206 }
00207 
00208 void KDTree::getBestNKeypointMatch(keypoint& key, int maxSearches, int n){
00209   PQueue<nodeSqDistPair> pq;
00210   int count = 0;
00211   bool countStart = false;
00212   
00213   // Want to find at least one leaf node
00214   // maxSearches += height;
00215   
00216   // Initialize pq with single node, no active axes
00217   nodeSqDistPair pThis;
00218   pThis.node = this;
00219   pThis.sqDist = 0.0;
00220   pq.push(pThis);
00221   
00222   // Initialize bestDist, bestCluster
00223 //  vector<double> bestDist;
00224 //  vector<void*>  key.bestMatch;
00225   key.bestMatch.clear();
00226   key.bestDist.clear();
00227   for (int i = 0; i < n; i++){
00228     key.bestDist.push_back(numeric_limits<double>::infinity());
00229     key.bestMatch.push_back(NULL);
00230   }
00231   
00232   while (!countStart || (count < maxSearches && !pq.isEmpty())){
00233   
00234     // Pop out
00235     nodeSqDistPair pair;
00236     pair = pq.pop();
00237     if (pair.sqDist > key.bestDist[n-1]) break;
00238     
00239     KDTree *iter = pair.node;
00240     while (!iter->isLeaf){
00241       
00242       KDTree *nextNode, *otherNode;
00243       
00244       if (key.desc[iter->axis] < iter->median){
00245         // left
00246         nextNode = iter->leftChild;
00247         otherNode = iter->rightChild;
00248       }else{
00249         // right
00250         nextNode = iter->rightChild;
00251         otherNode = iter->leftChild;
00252       }
00253       // iter maintains the same activeAxes
00254       nodeSqDistPair pairFar = nodeSqDistPair(otherNode, pair);
00255       // Recompute distance for pairFar
00256       double oldAxisDist = pairFar.activeDist[iter->axis];
00257       double newAxisDist = std::abs(key.desc[iter->axis] - iter->median);
00258       pairFar.sqDist -= (oldAxisDist * oldAxisDist);
00259       pairFar.sqDist += (newAxisDist * newAxisDist);
00260       pairFar.activeAxes[pair.node->axis] = true;
00261       pairFar.activeDist[pair.node->axis] = newAxisDist;
00262       pq.push(pairFar);
00263       
00264       iter = nextNode;
00265     }
00266     
00267     if (countStart) count++;
00268     countStart = true;
00269     //delete pair;
00270     
00271 // Deal with leaf node now
00272     for (int k = 0; k < (int)iter->keypts.size(); k++){
00273       double sqDist = key.sqDist(*iter->keypts[k]);//0.0;
00274 /*
00275       for (int j = 0; j < KEYPOINTDIM; j++){
00276         double diff = iter->keypts[k]->desc[j] - key.desc[j];
00277         sqDist += (diff * diff);
00278 //          cout << "key.desc[j] = " << key.desc[j]
00279 //               << "\titer->keypts[k]->desc[j] = " << iter->keypts[k]->desc[j]
00280 //               << "\tsqDist = " << sqDist
00281 //               << "\tbestDist = " << bestDist << endl;
00282       }
00283 */
00284 //        cout << count << "----------\n";
00285       for (int ii = 0; ii < n; ii++){
00286         if (sqDist < key.bestDist[ii]){
00287           key.bestDist.insert(key.bestDist.begin() + ii, sqDist);
00288           key.bestMatch.insert(key.bestMatch.begin() + ii, iter->keypts[k]);
00289 //            cout << "Replacing at iteration " << count << endl;
00290           key.bestDist.pop_back();
00291           key.bestMatch.pop_back();
00292 //            for (int jj = 0; jj < (int)bestDist.size(); jj++){
00293 //              cout << bestDist[jj] << "\t";
00294 //            }
00295 //            cout << endl;
00296           break;
00297 //        }else{
00298 //          cout << sqDist << " " << (sqDist < bestDist[ii]) << endl;
00299         }
00300       }
00301     }
00302     
00303   }
00304 //  cout << (!countStart) << (count < maxSearches) << (!pq.isEmpty()) << (!countStart || (count < maxSearches && !pq.isEmpty())) << "Done\n";
00305     
00306 }
00307 
00308 bool operator<(const axisVarPair& p1, const axisVarPair& p2){
00309   return p1.variance < p2.variance;
00310 }
00311 
00312 
00313 
00314 nodeSqDistPair::nodeSqDistPair() :
00315   node(NULL),sqDist(numeric_limits<double>::infinity()),
00316   activeAxes(KEYPOINTDIM, false), activeDist(KEYPOINTDIM, 0.0) {}
00317 
00318 nodeSqDistPair::nodeSqDistPair(KDTree* N, nodeSqDistPair& pair)
00319   : node(N), sqDist(pair.sqDist), 
00320     activeAxes(pair.activeAxes), activeDist(pair.activeDist) {}
00321 
00322 nodeSqDistPair::nodeSqDistPair(const nodeSqDistPair& other) :
00323   node(other.node), sqDist(other.sqDist), activeAxes(other.activeAxes), activeDist(other.activeDist) {}
00324 
00325 nodeSqDistPair& nodeSqDistPair::operator=(const nodeSqDistPair& other) {
00326   node = other.node;
00327   sqDist = other.sqDist;
00328   activeAxes = other.activeAxes;
00329   activeDist = other.activeDist;
00330   return *this;
00331 }
00332 
00333 nodeSqDistPair::~nodeSqDistPair(){
00334 //  if (activeAxes) delete activeAxes;
00335 //  if (activeDist) delete activeDist;
00336 }
00337 
00338 bool nodeSqDistPair::operator<(const nodeSqDistPair& p){
00339   return this->sqDist > p.sqDist;
00340 }
00341 
00342 
00343 
00344 
00345 double computePositionK(std::vector<double> V, size_t posK){
00346 //  cout << "V:      \t"; for (int ii = 0; ii < (int)V.size(); ii++) cout << V[ii] << ", "; cout << endl;
00347 //  cout << "Looking for position " << posK << " in vector of length " << V.size() << "\n";
00348   size_t i;
00349   size_t size = V.size();
00350   double p;
00351   if (size <= posK){
00352     cout << "!size " << size << " >= posK " << posK << endl;
00353   }
00354   if (size <= 5){
00355     sort(V.begin(), V.end());
00356     return V[posK];
00357   }else{
00358     vector<double> medians;
00359     // Step 1: get medians of every set of 5
00360     size_t numOfSets = size /5;
00361 //    cout << "\tnumOfSets = " << numOfSets << endl;
00362     for (i = 0; i < numOfSets; i++){
00363       vector<double> temp;
00364       temp.insert(temp.end(), V.begin() + (5*i), V.begin() + (5*(i+1)));
00365 //      cout << "\ttemp.size() = " << temp.size() << endl;
00366       medians.push_back(computePositionK(temp, 2));
00367     }
00368     if ((size % 5) != 0){
00369       vector<double> temp2;
00370       temp2.insert(temp2.end(), V.begin() + (5*numOfSets), V.end());
00371 //      cout << "\ttemp2.size() = " << temp2.size() << endl;
00372       medians.push_back(computePositionK(temp2, temp2.size() / 2));
00373     }
00374 //    cout << "\t\t"; for (int ii = 0; ii < (int)medians.size(); ii++) cout << medians[ii] << ", "; cout << endl;
00375     // Step 2: find median of medians
00376     p = computePositionK(medians, medians.size() / 2);
00377 //    cout << "\tpivot: " << p << endl;
00378     // Step 3: partition into LESS, EQUAL and GREATER
00379     vector<double> LESS;
00380     vector<double> EQUAL;
00381     vector<double> GREATER;
00382     for (i = 0; i < size; i++){
00383       if (V[i] < p){
00384         LESS.push_back(V[i]);
00385       }else if (V[i] == p){
00386         EQUAL.push_back(p);
00387       }else{
00388         GREATER.push_back(V[i]);
00389       }
00390     }
00391 //    cout << "LESS:   \t"; for (int ii = 0; ii < (int)LESS.size(); ii++) cout << LESS[ii] << ", "; cout << endl;
00392 //    cout << "EQUAL:  \t"; for (int ii = 0; ii < (int)EQUAL.size(); ii++) cout << EQUAL[ii] << ", "; cout << endl;
00393 //    cout << "GREATER:\t"; for (int ii = 0; ii < (int)GREATER.size(); ii++) cout << GREATER[ii] << ", "; cout << endl;
00394     size_t sizeLESS = LESS.size();
00395     size_t sizeEQUALLESS = EQUAL.size() + sizeLESS;
00396     if (sizeLESS > posK){
00397       return computePositionK(LESS, posK);
00398     }else if (sizeEQUALLESS > posK){
00399       return p;
00400     }else{
00401       return computePositionK(GREATER, posK - sizeEQUALLESS);
00402     }
00403   }
00404   
00405   return 0;
00406 }
00407 
00408 void computePositionKExample(){
00409   vector<double> V;
00410   
00411   int numEntries = 200;
00412   
00413   for (int i = 0; i < numEntries; i++){
00414     V.push_back((double)(rand() % numEntries));
00415     cout << V[i] << "\t";
00416   }
00417   cout << endl;
00418   cout << endl;
00419   cout << endl;
00420   
00421   for (int i = 0; i < numEntries; i++){
00422     cout << computePositionK(V, i) << "\t";
00423   }
00424   cout << endl;
00425     
00426   
00427 }
00428 

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:42 2016 by Doxygen 1.6.3