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