//! 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)); } } }
void getMatches(IpVec &ipts1, IpVec &ipts2, IpPairVec &matches) { // Allocate host memory float *lin_descs1 = new float[ipts1.size() * 64]; float *lin_descs2 = new float[ipts2.size() * 64]; int *indices = new int[ipts1.size()]; float *dists = new float[ipts1.size()]; linearizeDescriptors(lin_descs1, ipts1); linearizeDescriptors(lin_descs2, ipts2); // Allocate GPU memory float *d_lin_descs1; float *d_lin_descs2; int *d_indices; float *d_dists; CUDA_SAFE_CALL( cudaMalloc((void **)&d_lin_descs1, ipts1.size() * 64 * sizeof(float)) ); CUDA_SAFE_CALL( cudaMalloc((void **)&d_lin_descs2, ipts2.size() * 64 * sizeof(float)) ); CUDA_SAFE_CALL( cudaMalloc((void **)&d_indices, ipts1.size() * sizeof(int)) ); CUDA_SAFE_CALL( cudaMalloc((void **)&d_dists, ipts1.size() * sizeof(float)) ); CUDA_SAFE_CALL( cudaMemcpy(d_lin_descs1, lin_descs1, ipts1.size() * 64 * sizeof(float), cudaMemcpyHostToDevice) ); CUDA_SAFE_CALL( cudaMemcpy(d_lin_descs2, lin_descs2, ipts2.size() * 64 * sizeof(float), cudaMemcpyHostToDevice) ); prepare_matchSURFKeypointsGPU(0.77f); matchSURFKeypointsGPU(d_indices, d_dists, d_lin_descs1, ipts1.size(), 64 * sizeof(float), d_lin_descs2, ipts2.size(), 64 * sizeof(float), 64); CUDA_SAFE_CALL( cudaMemcpy(indices, d_indices, ipts1.size() * sizeof(int), cudaMemcpyDeviceToHost) ); CUDA_SAFE_CALL( cudaMemcpy(dists, d_dists, ipts1.size() * sizeof(float), cudaMemcpyDeviceToHost) ); for (size_t i = 0; i < ipts1.size(); i++) { if (indices[i] != -1) { Ipoint &ipt1 = ipts1[i]; const Ipoint &match = ipts2[indices[i]]; ipt1.dx = match.x - ipt1.x; ipt1.dy = match.y - ipt1.y; matches.push_back(std::make_pair(ipt1, match)); } } delete[] lin_descs1; delete[] lin_descs2; delete[] indices; delete[] dists; CUDA_SAFE_CALL( cudaFree(d_lin_descs1) ); CUDA_SAFE_CALL( cudaFree(d_lin_descs2) ); CUDA_SAFE_CALL( cudaFree(d_indices) ); CUDA_SAFE_CALL( cudaFree(d_dists) ); }
//! 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; }