1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* matching_test.cpp
*
* Created on: Oct 17, 2010
* Author: ethan
*/
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>
#include <iostream>
using namespace cv;
using std::cout;
using std::cerr;
using std::endl;
using std::vector;
void help(char **av)
{
cerr << "usage: " << av[0] << " im1.jpg im2.jpg"
<< "\n"
<< "This program shows how to use BRIEF descriptor to match points in features2d\n"
<< "It takes in two images, finds keypoints and matches them displaying matches and final homography warped results\n"
<< endl;
}
//Copy (x,y) location of descriptor matches found from KeyPoint data structures into Point2f vectors
void matches2points(const vector<DMatch>& matches, const vector<KeyPoint>& kpts_train,
const vector<KeyPoint>& kpts_query, vector<Point2f>& pts_train, vector<Point2f>& pts_query)
{
pts_train.clear();
pts_query.clear();
pts_train.reserve(matches.size());
pts_query.reserve(matches.size());
for (size_t i = 0; i < matches.size(); i++)
{
const DMatch& match = matches[i];
pts_query.push_back(kpts_query[match.queryIdx].pt);
pts_train.push_back(kpts_train[match.trainIdx].pt);
}
}
double match(const vector<KeyPoint>& kpts_train, const vector<KeyPoint>& kpts_query, DescriptorMatcher& matcher,
const Mat& train, const Mat& query, vector<DMatch>& matches)
{
double t = (double)getTickCount();
matcher.match(query, train, matches); //Using features2d
return ((double)getTickCount() - t) / getTickFrequency();
}
int main(int ac, char ** av)
{
if (ac != 3)
{
help(av);
return 1;
}
string im1_name, im2_name;
im1_name = av[1];
im2_name = av[2];
Mat im1 = imread(im1_name, CV_LOAD_IMAGE_GRAYSCALE);
Mat im2 = imread(im2_name, CV_LOAD_IMAGE_GRAYSCALE);
if (im1.empty() || im2.empty())
{
cerr << "could not open one of the images..." << endl;
return 1;
}
double t = (double)getTickCount();
FastFeatureDetector detector(50);
BriefDescriptorExtractor extractor(32); //this is really 32 x 8 matches since they are binary matches packed into bytes
vector<KeyPoint> kpts_1, kpts_2;
detector.detect(im1, kpts_1);
detector.detect(im2, kpts_2);
t = ((double)getTickCount() - t) / getTickFrequency();
cout << "found " << kpts_1.size() << " keypoints in " << im1_name << endl << "fount " << kpts_2.size()
<< " keypoints in " << im2_name << endl << "took " << t << " seconds." << endl;
Mat desc_1, desc_2;
cout << "computing descriptors..." << endl;
t = (double)getTickCount();
extractor.compute(im1, kpts_1, desc_1);
extractor.compute(im2, kpts_2, desc_2);
t = ((double)getTickCount() - t) / getTickFrequency();
cout << "done computing descriptors... took " << t << " seconds" << endl;
//Do matching with 2 methods using features2d
cout << "matching with BruteForceMatcher<HammingLUT>" << endl;
BruteForceMatcher<HammingLUT> matcher;
vector<DMatch> matches_lut;
float lut_time = match(kpts_1, kpts_2, matcher, desc_1, desc_2, matches_lut);
cout << "done BruteForceMatcher<HammingLUT> matching. took " << lut_time << " seconds" << endl;
cout << "matching with BruteForceMatcher<Hamming>" << endl;
BruteForceMatcher<Hamming> matcher_popcount;
vector<DMatch> matches_popcount;
double pop_time = match(kpts_1, kpts_2, matcher_popcount, desc_1, desc_2, matches_popcount);
cout << "done BruteForceMatcher<Hamming> matching. took " << pop_time << " seconds" << endl;
vector<Point2f> mpts_1, mpts_2;
matches2points(matches_popcount, kpts_1, kpts_2, mpts_1, mpts_2); //Extract a list of the (x,y) location of the matches
vector<uchar> outlier_mask;
Mat H = findHomography(Mat(mpts_2), Mat(mpts_1), outlier_mask, RANSAC, 1);
Mat outimg;
drawMatches(im2, kpts_2, im1, kpts_1, matches_popcount, outimg, Scalar::all(-1), Scalar::all(-1),
reinterpret_cast<const vector<char>&> (outlier_mask));
imshow("matches - popcount - outliers removed", outimg);
Mat warped;
warpPerspective(im2, warped, H, im1.size());
imshow("warped", warped);
imshow("diff", im1 - warped);
waitKey();
return 0;
}