bool ImageTransformation::findHomography( const Keypoints& source, const Keypoints& result, const Matches& input, Matches& inliers, cv::Mat& homography) { if (input.size() < 8) return false; std::vector<cv::Point2f> srcPoints, dstPoints; const int pointsCount = input.size(); for (int i=0; i<pointsCount; i++) { srcPoints.push_back(source[input[i].trainIdx].pt); dstPoints.push_back(result[input[i].queryIdx].pt); } std::vector<unsigned char> status; cv::findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3, status); inliers.clear(); for (int i=0; i<pointsCount; i++) { if (status[i]) { inliers.push_back(input[i]); } } return true; }
/* * Find the closest match in db, return as element of matches */ void SemanticDescriptor::findClosestMatch(Database & db, Matches & matches) { SemanticDescriptor bestMatch = (*(db.dDB.begin())).first; //matches.insert((*(db.dDB.begin())).second); SemanticDescriptor compareID; int matchStrength; map<SemanticDescriptor, string>::iterator iter; for (iter = db.dDB.begin(); iter != db.dDB.end(); ++iter) { compareID = iter->first; matchStrength = closerMatch(compareID, bestMatch, db); /* If compareID is a better match, reset matches */ if (matchStrength > 0) if (compareID.coverage(*this, db) >= .5) { matches.clear(); matches.insert(iter->second); bestMatch = compareID; } /* If compareID is an equal match, then add it to the set of matches */ if (matchStrength == 0) if (compareID.coverage(*this, db) >= .5) matches.insert(iter->second); } }
bool HybridTracker::Localize(const Marker& target, const Frame& scene, Matches& out) { vector<cv::DMatch> matches; methods.Match(target.descriptor, scene.descriptor, matches); out.clear(); for(auto& it : matches) { out._targetPts.push_back(target.keys[it.queryIdx]); out._scenePts.push_back(scene.keys[it.trainIdx]); out._error.push_back(it.distance); } return matches.size() > 20; }
void ratioTest(const std::vector<Matches>& knMatches, float maxRatio, Matches& goodMatches) { goodMatches.clear(); for (size_t i=0; i< knMatches.size(); i++) { const cv::DMatch& best = knMatches[i][0]; const cv::DMatch& good = knMatches[i][1]; assert(best.distance <= good.distance); float ratio = (best.distance / good.distance); if (ratio <= maxRatio) { goodMatches.push_back(best); } } }
bool ImageTransformation::findHomography( const Keypoints& source, const Keypoints& result, const Matches& input, Matches& inliers, cv::Mat& homography) { if (input.size() < 4) return false; const int pointsCount = input.size(); const float reprojectionThreshold = 2; //Prepare src and dst points std::vector<cv::Point2f> srcPoints, dstPoints; for (int i = 0; i < pointsCount; i++) { srcPoints.push_back(source[input[i].trainIdx].pt); dstPoints.push_back(result[input[i].queryIdx].pt); } // Find homography using RANSAC algorithm std::vector<unsigned char> status; homography = cv::findHomography(srcPoints, dstPoints, cv::RANSAC, reprojectionThreshold, status); // Warp dstPoints to srcPoints domain using inverted homography transformation std::vector<cv::Point2f> srcReprojected; cv::perspectiveTransform(dstPoints, srcReprojected, homography.inv()); // Pass only matches with low reprojection error (less than reprojectionThreshold value in pixels) inliers.clear(); for (int i = 0; i < pointsCount; i++) { cv::Point2f actual = srcPoints[i]; cv::Point2f expect = srcReprojected[i]; cv::Point2f v = actual - expect; float distanceSquared = v.dot(v); if (/*status[i] && */distanceSquared <= reprojectionThreshold * reprojectionThreshold) { inliers.push_back(input[i]); } } // Test for bad case if (inliers.size() < 4) return false; // Now use only good points to find refined homography: std::vector<cv::Point2f> refinedSrc, refinedDst; for (int i = 0; i < inliers.size(); i++) { refinedSrc.push_back(source[inliers[i].trainIdx].pt); refinedDst.push_back(result[inliers[i].queryIdx].pt); } // Use least squares method to find precise homography cv::Mat homography2 = cv::findHomography(refinedSrc, refinedDst, 0, reprojectionThreshold); // Reproject again: cv::perspectiveTransform(dstPoints, srcReprojected, homography2.inv()); inliers.clear(); for (int i = 0; i < pointsCount; i++) { cv::Point2f actual = srcPoints[i]; cv::Point2f expect = srcReprojected[i]; cv::Point2f v = actual - expect; float distanceSquared = v.dot(v); if (distanceSquared <= reprojectionThreshold * reprojectionThreshold) { inliers.push_back(input[i]); } } homography = homography2; return inliers.size() >= 4; }