Mat RANSAC::compute(std::vector<Mat>& X, std::vector<Mat>& Y){ static int num_points = 5; Mat T = Mat::eye(4, 4, CV_32FC1); Mat best_T = Mat::eye(4, 4, CV_32FC1); int max_inliers = 0; std::srand(unsigned(std::time(0))); std::vector<int> indices; for (int i = 0; i < X.size(); ++i) indices.push_back(i); for (int i = 0; i < m_max_iterations; i++){ //get random points std::random_shuffle(indices.begin(), indices.end(), myrandom); std::vector<Mat> new_X; std::vector<Mat> new_Y; for (int j = 0; j < num_points; ++j){ new_X.push_back(X[indices[j]]); new_Y.push_back(Y[indices[j]]); } //compute T T = getTransformationMatrix(new_X, new_Y); int inliers = countInliers(T, X, Y, m_margin); if (inliers > max_inliers){ best_T = T; max_inliers = inliers; } } static float percentage_outliers = 0; percentage_outliers = (percentage_outliers + (X.size() - max_inliers)* 100.f / X.size()) / 2; printf("Ouliers(Accumulated): %.2f%% Inliers: %i \n", percentage_outliers, max_inliers); return best_T; }
/******************* TO DO ********************* * alignPair: * INPUT: * f1, f2: source feature sets * matches: correspondences between f1 and f2 * Each match in 'matches' contains two feature ids of * Each match in 'matches' contains two feature ids of * matching features, id1 (in f1) and id2 (in f2). * m: motion model * nRANSAC: number of RANSAC iterations * RANSACthresh: RANSAC distance threshold * M: transformation matrix (output) * * OUTPUT: * repeat for nRANSAC iterations: * choose a minimal set of feature matches * estimate the transformation implied by these matches * count the number of inliers * for the transformation with the maximum number of inliers, * compute the least squares motion estimate using the inliers, * and store it in M */ int alignPair(const FeatureSet &f1, const FeatureSet &f2, const vector<FeatureMatch> &matches, MotionModel m, int nRANSAC, double RANSACthresh, CTransform3x3 &M) { // BEGIN TODO // Write this entire method. You need to handle two types of // motion models, pure translations (m == eTranslation) and // full homographies (m == eHomography). However, you should // only have one outer loop to perform the RANSAC code, as // BEGIN TODO // Write this entire method. You need to handle two types of // motion models, pure translations (m == eTranslation) and // full homographies (m == eHomography). However, you should // only have one outer loop to perform the RANSAC code, as // the use of RANSAC is almost identical for both cases. // // Your homography handling code should call ComputeHomography. // This function should also call countInliers and, at the end, // leastSquaresFit. cout << "alignalignalignalign"; cout << f1.size(); cout << '\n'; cout << f2.size(); cout << '\n'; cout << matches.size(); cout << '\n'; int maxInliers = -1; int sz = matches.size(); for (int i = 0; i < nRANSAC; i++) { int n = rand() % sz; FeatureMatch randomMatch = matches.at(n); CTransform3x3 trans; switch (m) { case eTranslate: { Feature first = f1[randomMatch.id1]; Feature second = f2[randomMatch.id2]; float xTranslation = (float)(second.x - first.x); float yTranslation = (float)(second.y - first.y); cout << "Translation: X "; cout << xTranslation; cout << ", Y "; cout << yTranslation; cout << '\n'; trans = CTransform3x3::Translation(xTranslation, yTranslation); break; } case eHomography: { int indices[] = {0, 0, 0, 0}; for (int chooseRand = 0; chooseRand < 4; chooseRand++) { indices[chooseRand] = rand() % sz; for (int p = 0; p < chooseRand; p++) { if (indices[p] = indices[chooseRand]); { indices[chooseRand] = rand() % sz; p--; } } } vector<FeatureMatch> selectedMatches; selectedMatches.resize(4); for (int c = 0; c < 4; c++) { int idx = indices[c]; FeatureMatch fm; fm.id1 = matches.at(idx).id1; fm.id2 = matches.at(idx).id2; selectedMatches.push_back(fm); } trans = ComputeHomography(f1, f2, selectedMatches); break; } } vector<int> inliers; countInliers(f1,f2,matches,m,trans,RANSACthresh,inliers); cout << "Inliers: "; cout << inliers.size(); cout << '\n'; if (inliers.size() > maxInliers) { maxInliers = inliers.size(); M = trans; } } // END TODO return 0; }