1/*
2 * RobustMatcher.cpp
3 *
4 *  Created on: Jun 4, 2014
5 *      Author: eriba
6 */
7
8#include "RobustMatcher.h"
9#include <time.h>
10
11#include <opencv2/features2d/features2d.hpp>
12
13RobustMatcher::~RobustMatcher()
14{
15  // TODO Auto-generated destructor stub
16}
17
18void RobustMatcher::computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints)
19{
20  detector_->detect(image, keypoints);
21}
22
23void RobustMatcher::computeDescriptors( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors)
24{
25  extractor_->compute(image, keypoints, descriptors);
26}
27
28int RobustMatcher::ratioTest(std::vector<std::vector<cv::DMatch> > &matches)
29{
30  int removed = 0;
31  // for all matches
32  for ( std::vector<std::vector<cv::DMatch> >::iterator
33        matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator)
34  {
35    // if 2 NN has been identified
36    if (matchIterator->size() > 1)
37    {
38      // check distance ratio
39      if ((*matchIterator)[0].distance / (*matchIterator)[1].distance > ratio_)
40      {
41        matchIterator->clear(); // remove match
42        removed++;
43      }
44    }
45    else
46    { // does not have 2 neighbours
47      matchIterator->clear(); // remove match
48      removed++;
49    }
50  }
51  return removed;
52}
53
54void RobustMatcher::symmetryTest( const std::vector<std::vector<cv::DMatch> >& matches1,
55                     const std::vector<std::vector<cv::DMatch> >& matches2,
56                     std::vector<cv::DMatch>& symMatches )
57{
58
59  // for all matches image 1 -> image 2
60   for (std::vector<std::vector<cv::DMatch> >::const_iterator
61       matchIterator1 = matches1.begin(); matchIterator1 != matches1.end(); ++matchIterator1)
62   {
63
64      // ignore deleted matches
65      if (matchIterator1->empty() || matchIterator1->size() < 2)
66         continue;
67
68      // for all matches image 2 -> image 1
69      for (std::vector<std::vector<cv::DMatch> >::const_iterator
70          matchIterator2 = matches2.begin(); matchIterator2 != matches2.end(); ++matchIterator2)
71      {
72        // ignore deleted matches
73        if (matchIterator2->empty() || matchIterator2->size() < 2)
74           continue;
75
76        // Match symmetry test
77        if ((*matchIterator1)[0].queryIdx ==
78            (*matchIterator2)[0].trainIdx &&
79            (*matchIterator2)[0].queryIdx ==
80            (*matchIterator1)[0].trainIdx)
81        {
82            // add symmetrical match
83            symMatches.push_back(
84              cv::DMatch((*matchIterator1)[0].queryIdx,
85                         (*matchIterator1)[0].trainIdx,
86                         (*matchIterator1)[0].distance));
87            break; // next match in image 1 -> image 2
88        }
89      }
90   }
91
92}
93
94void RobustMatcher::robustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
95              std::vector<cv::KeyPoint>& keypoints_frame, const cv::Mat& descriptors_model )
96{
97
98  // 1a. Detection of the ORB features
99  this->computeKeyPoints(frame, keypoints_frame);
100
101  // 1b. Extraction of the ORB descriptors
102  cv::Mat descriptors_frame;
103  this->computeDescriptors(frame, keypoints_frame, descriptors_frame);
104
105  // 2. Match the two image descriptors
106  std::vector<std::vector<cv::DMatch> > matches12, matches21;
107
108  // 2a. From image 1 to image 2
109  matcher_->knnMatch(descriptors_frame, descriptors_model, matches12, 2); // return 2 nearest neighbours
110
111  // 2b. From image 2 to image 1
112  matcher_->knnMatch(descriptors_model, descriptors_frame, matches21, 2); // return 2 nearest neighbours
113
114  // 3. Remove matches for which NN ratio is > than threshold
115  // clean image 1 -> image 2 matches
116  ratioTest(matches12);
117  // clean image 2 -> image 1 matches
118  ratioTest(matches21);
119
120  // 4. Remove non-symmetrical matches
121  symmetryTest(matches12, matches21, good_matches);
122
123}
124
125void RobustMatcher::fastRobustMatch( const cv::Mat& frame, std::vector<cv::DMatch>& good_matches,
126                                 std::vector<cv::KeyPoint>& keypoints_frame,
127                                 const cv::Mat& descriptors_model )
128{
129  good_matches.clear();
130
131  // 1a. Detection of the ORB features
132  this->computeKeyPoints(frame, keypoints_frame);
133
134  // 1b. Extraction of the ORB descriptors
135  cv::Mat descriptors_frame;
136  this->computeDescriptors(frame, keypoints_frame, descriptors_frame);
137
138  // 2. Match the two image descriptors
139  std::vector<std::vector<cv::DMatch> > matches;
140  matcher_->knnMatch(descriptors_frame, descriptors_model, matches, 2);
141
142  // 3. Remove matches for which NN ratio is > than threshold
143  ratioTest(matches);
144
145  // 4. Fill good matches container
146  for ( std::vector<std::vector<cv::DMatch> >::iterator
147         matchIterator= matches.begin(); matchIterator!= matches.end(); ++matchIterator)
148  {
149    if (!matchIterator->empty()) good_matches.push_back((*matchIterator)[0]);
150  }
151
152}
153