//! Populate IpPairVec with matched ipts void getMatches(IpVec &ipts1, IpVec &ipts2, IpPairVec &matches) { float dist, d1, d2; Ipoint *match; matches.clear(); for (unsigned int i = 0; i < ipts1.size(); i++) { d1 = d2 = 1000; for (unsigned int j = 0; j < ipts2.size(); j++) { dist = ipts1[i] - ipts2[j]; if (dist < d1) // if this feature matches better than current best { d2 = d1; d1 = dist; match = &ipts2[j]; } else if (dist < d2) // this feature matches better than second best { d2 = dist; } } // If match has a d1:d2 ratio < 0.65 ipoints are a match if (d1 / d2 < 0.65) { // Store the change in position ipts1[i].dx = match->x - ipts1[i].x; ipts1[i].dy = match->y - ipts1[i].y; match->dx = ipts1[i].x -match->x; match->dy = ipts1[i].y -match->y; matches.push_back(std::make_pair(ipts1[i], *match)); } } }
//! Populate IpPairVec with matched ipts using nearest neighbour and RANSAC Score getMatchesRANSAC(IpVec &ipts1, IpVec &ipts2, IpPairVec &matches) { #if RUNSWIFT #else timespec matchings, matchinge, verifys, verifye; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &matchings); #endif float dist, d1, d2; Ipoint *match; float matching_score = 0; matches.clear(); for(unsigned int i = 0; i < ipts1.size(); i++) { ipts1[i].x = ipts1[i].x; d1 = d2 = FLT_MAX; match = &ipts2[0]; // to avoid unitialized warning for(unsigned int j = 0; j < ipts2.size(); j++) { ipts2[j].x = ipts2[j].x; dist = ipts1[i] - ipts2[j]; if(dist<d1) // if this feature matches better than current best { d2 = d1; d1 = dist; match = &ipts2[j]; } else if(dist<d2) // this feature matches better than second best { d2 = dist; } } // If match has a d1:d2 ratio < 0.75 ipoints are a match if(d1/d2 < 0.75) { // Store the match matches.push_back(std::make_pair(ipts1[i], *match)); //Increment the matching score matching_score += 1/d1; } } float best_score = matching_score; float best_b = -1; float best_m = -1; #if RUNSWIFT #else Ipoint::totalNumMatches = matches.size(); //At this point we have the total matches before the final number of matches clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &verifys); #endif if(matches.size()>1){ best_score = 0; for(int i=0; i<ITERATIONS; i++){ //Choose random matches int pos1 = rand() % (int)matches.size(); int pos2 = rand() % (int)matches.size(); while(pos1 == pos2) { //Make sure that both matches are different pos2 = rand() % (int)matches.size(); } //Should generate a positive value float m = (matches.at(pos2).second.x - matches.at(pos1).second.x)/(matches.at(pos2).first.x - matches.at(pos1).first.x); //If a gradient is discarded if (m <= 0){ continue; } //Calculate the translation component float b = matches.at(pos2).second.x - m*matches.at(pos2).first.x; float score = 0; for(int j=0; j<(int)matches.size(); j++){ //Calculate the function x_stored,i = b_s * x_test,i + b_d if( fabs(matches.at(j).second.x - (m*matches.at(j).first.x + b)) < PIXEL_ERROR_MARGIN) score += 1/fabs(matches.at(j).first - matches.at(j).second); } if (score > best_score){ best_score = score; best_b = b; best_m = m; } } } // Now remove all matches who are not within this pixel error margin //if(best_m > 0){ for(int j=0; j<(int)matches.size(); j++){ if( fabs(matches.at(j).second.x - (best_m*matches.at(j).first.x + best_b)) >= PIXEL_ERROR_MARGIN) { matches.erase(matches.begin() + j); j--; } } //} Score score = {best_score, best_m, best_b}; #if RUNSWIFT #else Ipoint::numValidMatches = matches.size(); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &verifye); Ipoint::verificationTime = Ipoint::diffSurf(verifys,verifye).tv_nsec/1000000.0f; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &matchinge); Ipoint::matchingTime = Ipoint::diffSurf(matchings,matchinge).tv_nsec/1000000.0f; #endif return score; }