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
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
00063 keypts.insert(keypts.end(), C.begin(), C.end());
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 if (keypts.size() <= 1){
00076
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
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
00098
00099
00100
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
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
00128 makeLeaf();
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 }else{
00140
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
00214
00215
00216
00217 nodeSqDistPair pThis;
00218 pThis.node = this;
00219 pThis.sqDist = 0.0;
00220 pq.push(pThis);
00221
00222
00223
00224
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
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
00246 nextNode = iter->leftChild;
00247 otherNode = iter->rightChild;
00248 }else{
00249
00250 nextNode = iter->rightChild;
00251 otherNode = iter->leftChild;
00252 }
00253
00254 nodeSqDistPair pairFar = nodeSqDistPair(otherNode, pair);
00255
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
00270
00271
00272 for (int k = 0; k < (int)iter->keypts.size(); k++){
00273 double sqDist = key.sqDist(*iter->keypts[k]);
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
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
00290 key.bestDist.pop_back();
00291 key.bestMatch.pop_back();
00292
00293
00294
00295
00296 break;
00297
00298
00299 }
00300 }
00301 }
00302
00303 }
00304
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
00335
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
00347
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
00360 size_t numOfSets = size /5;
00361
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
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
00372 medians.push_back(computePositionK(temp2, temp2.size() / 2));
00373 }
00374
00375
00376 p = computePositionK(medians, medians.size() / 2);
00377
00378
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
00392
00393
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