1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * RobustMatcher.cpp 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Created on: Jun 4, 2014 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Author: eriba 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "RobustMatcher.h" 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <time.h> 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <opencv2/features2d/features2d.hpp> 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerRobustMatcher::~RobustMatcher() 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // TODO Auto-generated destructor stub 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid RobustMatcher::computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints) 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler detector_->detect(image, keypoints); 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid RobustMatcher::computeDescriptors( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors) 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler extractor_->compute(image, keypoints, descriptors); 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint RobustMatcher::ratioTest(std::vector<std::vector<cv::DMatch> > &matches) 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int removed = 0; 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // for all matches 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for ( std::vector<std::vector<cv::DMatch> >::iterator 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator) 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // if 2 NN has been identified 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (matchIterator->size() > 1) 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // check distance ratio 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if ((*matchIterator)[0].distance / (*matchIterator)[1].distance > ratio_) 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matchIterator->clear(); // remove match 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler removed++; 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { // does not have 2 neighbours 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matchIterator->clear(); // remove match 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler removed++; 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return removed; 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid RobustMatcher::symmetryTest( const std::vector<std::vector<cv::DMatch> >& matches1, 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const std::vector<std::vector<cv::DMatch> >& matches2, 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<cv::DMatch>& symMatches ) 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // for all matches image 1 -> image 2 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (std::vector<std::vector<cv::DMatch> >::const_iterator 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matchIterator1 = matches1.begin(); matchIterator1 != matches1.end(); ++matchIterator1) 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // ignore deleted matches 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (matchIterator1->empty() || matchIterator1->size() < 2) 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // for all matches image 2 -> image 1 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (std::vector<std::vector<cv::DMatch> >::const_iterator 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matchIterator2 = matches2.begin(); matchIterator2 != matches2.end(); ++matchIterator2) 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // ignore deleted matches 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (matchIterator2->empty() || matchIterator2->size() < 2) 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Match symmetry test 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if ((*matchIterator1)[0].queryIdx == 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*matchIterator2)[0].trainIdx && 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*matchIterator2)[0].queryIdx == 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*matchIterator1)[0].trainIdx) 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // add symmetrical match 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler symMatches.push_back( 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::DMatch((*matchIterator1)[0].queryIdx, 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*matchIterator1)[0].trainIdx, 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*matchIterator1)[0].distance)); 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; // next match in image 1 -> image 2 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid RobustMatcher::robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches, 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<cv::KeyPoint>& keypoints_frame, const cv::Mat& descriptors_model ) 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 1a. Detection of the ORB features 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler this->computeKeyPoints(frame, keypoints_frame); 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 1b. Extraction of the ORB descriptors 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mat descriptors_frame; 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler this->computeDescriptors(frame, keypoints_frame, descriptors_frame); 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 2. Match the two image descriptors 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<std::vector<cv::DMatch> > matches12, matches21; 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 2a. From image 1 to image 2 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 2b. From image 2 to image 1 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 3. Remove matches for which NN ratio is > than threshold 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // clean image 1 -> image 2 matches 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ratioTest(matches12); 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // clean image 2 -> image 1 matches 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ratioTest(matches21); 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 4. Remove non-symmetrical matches 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler symmetryTest(matches12, matches21, good_matches); 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid RobustMatcher::fastRobustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches, 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<cv::KeyPoint>& keypoints_frame, 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const cv::Mat& descriptors_model ) 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler good_matches.clear(); 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 1a. Detection of the ORB features 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler this->computeKeyPoints(frame, keypoints_frame); 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 1b. Extraction of the ORB descriptors 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mat descriptors_frame; 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler this->computeDescriptors(frame, keypoints_frame, descriptors_frame); 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 2. Match the two image descriptors 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<std::vector<cv::DMatch> > matches; 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matcher_->knnMatch(descriptors_frame, descriptors_model, matches, 2); 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 3. Remove matches for which NN ratio is > than threshold 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ratioTest(matches); 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // 4. Fill good matches container 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for ( std::vector<std::vector<cv::DMatch> >::iterator 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator) 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (!matchIterator->empty()) good_matches.push_back((*matchIterator)[0]); 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 153