Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/stitching/perf/perf_matchers.cpp
16339 views
1
#include "perf_precomp.hpp"
2
#include "opencv2/imgcodecs.hpp"
3
#include "opencv2/opencv_modules.hpp"
4
#include "opencv2/flann.hpp"
5
6
namespace opencv_test
7
{
8
using namespace perf;
9
10
typedef TestBaseWithParam<size_t> FeaturesFinderVec;
11
typedef TestBaseWithParam<string> match;
12
typedef tuple<string, int> matchVector_t;
13
typedef TestBaseWithParam<matchVector_t> matchVector;
14
15
#define NUMBER_IMAGES testing::Values(1, 5, 20)
16
#define SURF_MATCH_CONFIDENCE 0.65f
17
#define ORB_MATCH_CONFIDENCE 0.3f
18
#define WORK_MEGAPIX 0.6
19
20
#ifdef HAVE_OPENCV_XFEATURES2D
21
#define TEST_DETECTORS testing::Values("surf", "orb")
22
#else
23
#define TEST_DETECTORS testing::Values<string>("orb")
24
#endif
25
26
PERF_TEST_P(FeaturesFinderVec, ParallelFeaturesFinder, NUMBER_IMAGES)
27
{
28
Mat img = imread( getDataPath("stitching/a1.png") );
29
vector<Mat> imgs(GetParam(), img);
30
vector<detail::ImageFeatures> features(imgs.size());
31
32
Ptr<detail::FeaturesFinder> featuresFinder = makePtr<detail::OrbFeaturesFinder>();
33
34
TEST_CYCLE()
35
{
36
(*featuresFinder)(imgs, features);
37
}
38
39
SANITY_CHECK_NOTHING();
40
}
41
42
PERF_TEST_P(FeaturesFinderVec, SerialFeaturesFinder, NUMBER_IMAGES)
43
{
44
Mat img = imread( getDataPath("stitching/a1.png") );
45
vector<Mat> imgs(GetParam(), img);
46
vector<detail::ImageFeatures> features(imgs.size());
47
48
Ptr<detail::FeaturesFinder> featuresFinder = makePtr<detail::OrbFeaturesFinder>();
49
50
TEST_CYCLE()
51
{
52
for (size_t i = 0; i < imgs.size(); ++i)
53
(*featuresFinder)(imgs[i], features[i]);
54
}
55
56
SANITY_CHECK_NOTHING();
57
}
58
59
PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
60
{
61
Mat img1, img1_full = imread( getDataPath("stitching/boat1.jpg") );
62
Mat img2, img2_full = imread( getDataPath("stitching/boat2.jpg") );
63
float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
64
float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
65
resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
66
resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
67
68
Ptr<detail::FeaturesFinder> finder;
69
Ptr<detail::FeaturesMatcher> matcher;
70
if (GetParam() == "surf")
71
{
72
finder = makePtr<detail::SurfFeaturesFinder>();
73
matcher = makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
74
}
75
else if (GetParam() == "orb")
76
{
77
finder = makePtr<detail::OrbFeaturesFinder>();
78
matcher = makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE);
79
}
80
else
81
{
82
FAIL() << "Unknown 2D features type: " << GetParam();
83
}
84
85
detail::ImageFeatures features1, features2;
86
(*finder)(img1, features1);
87
(*finder)(img2, features2);
88
89
detail::MatchesInfo pairwise_matches;
90
91
declare.in(features1.descriptors, features2.descriptors);
92
93
while(next())
94
{
95
cvflann::seed_random(42);//for predictive FlannBasedMatcher
96
startTimer();
97
(*matcher)(features1, features2, pairwise_matches);
98
stopTimer();
99
matcher->collectGarbage();
100
}
101
102
Mat dist (pairwise_matches.H, Range::all(), Range(2, 3));
103
Mat R (pairwise_matches.H, Range::all(), Range(0, 2));
104
// separate transform matrix, use lower error on rotations
105
SANITY_CHECK(dist, 1., ERROR_ABSOLUTE);
106
SANITY_CHECK(R, .06, ERROR_ABSOLUTE);
107
}
108
109
PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine(
110
TEST_DETECTORS,
111
testing::Values(2, 4, 8))
112
)
113
{
114
Mat img1, img1_full = imread( getDataPath("stitching/boat1.jpg") );
115
Mat img2, img2_full = imread( getDataPath("stitching/boat2.jpg") );
116
float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
117
float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
118
resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
119
resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
120
121
Ptr<detail::FeaturesFinder> finder;
122
Ptr<detail::FeaturesMatcher> matcher;
123
string detectorName = get<0>(GetParam());
124
int featuresVectorSize = get<1>(GetParam());
125
if (detectorName == "surf")
126
{
127
finder = makePtr<detail::SurfFeaturesFinder>();
128
matcher = makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
129
}
130
else if (detectorName == "orb")
131
{
132
finder = makePtr<detail::OrbFeaturesFinder>();
133
matcher = makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE);
134
}
135
else
136
{
137
FAIL() << "Unknown 2D features type: " << get<0>(GetParam());
138
}
139
140
detail::ImageFeatures features1, features2;
141
(*finder)(img1, features1);
142
(*finder)(img2, features2);
143
vector<detail::ImageFeatures> features;
144
vector<detail::MatchesInfo> pairwise_matches;
145
for(int i = 0; i < featuresVectorSize/2; i++)
146
{
147
features.push_back(features1);
148
features.push_back(features2);
149
}
150
151
declare.time(200);
152
while(next())
153
{
154
cvflann::seed_random(42);//for predictive FlannBasedMatcher
155
startTimer();
156
(*matcher)(features, pairwise_matches);
157
stopTimer();
158
matcher->collectGarbage();
159
}
160
161
size_t matches_count = 0;
162
for (size_t i = 0; i < pairwise_matches.size(); ++i)
163
{
164
if (pairwise_matches[i].src_img_idx < 0)
165
continue;
166
167
EXPECT_GT(pairwise_matches[i].matches.size(), 95u);
168
EXPECT_FALSE(pairwise_matches[i].H.empty());
169
++matches_count;
170
}
171
172
EXPECT_GT(matches_count, 0u);
173
174
SANITY_CHECK_NOTHING();
175
}
176
177
PERF_TEST_P( match, affineBestOf2Nearest, TEST_DETECTORS)
178
{
179
Mat img1, img1_full = imread( getDataPath("stitching/s1.jpg") );
180
Mat img2, img2_full = imread( getDataPath("stitching/s2.jpg") );
181
float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
182
float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
183
resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
184
resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
185
186
Ptr<detail::FeaturesFinder> finder;
187
Ptr<detail::FeaturesMatcher> matcher;
188
if (GetParam() == "surf")
189
{
190
finder = makePtr<detail::SurfFeaturesFinder>();
191
matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, SURF_MATCH_CONFIDENCE);
192
}
193
else if (GetParam() == "orb")
194
{
195
finder = makePtr<detail::OrbFeaturesFinder>();
196
matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, ORB_MATCH_CONFIDENCE);
197
}
198
else
199
{
200
FAIL() << "Unknown 2D features type: " << GetParam();
201
}
202
203
detail::ImageFeatures features1, features2;
204
(*finder)(img1, features1);
205
(*finder)(img2, features2);
206
207
detail::MatchesInfo pairwise_matches;
208
209
declare.in(features1.descriptors, features2.descriptors);
210
211
while(next())
212
{
213
cvflann::seed_random(42);//for predictive FlannBasedMatcher
214
startTimer();
215
(*matcher)(features1, features2, pairwise_matches);
216
stopTimer();
217
matcher->collectGarbage();
218
}
219
220
// separate rotation and translation in transform matrix
221
Mat T (pairwise_matches.H, Range(0, 2), Range(2, 3));
222
Mat R (pairwise_matches.H, Range(0, 2), Range(0, 2));
223
Mat h (pairwise_matches.H, Range(2, 3), Range::all());
224
SANITY_CHECK(T, 5, ERROR_ABSOLUTE); // allow 5 pixels diff in translations
225
SANITY_CHECK(R, .01, ERROR_ABSOLUTE); // rotations must be more precise
226
// last row should be precisely (0, 0, 1) as it is just added for representation in homogeneous
227
// coordinates
228
EXPECT_DOUBLE_EQ(h.at<double>(0), 0.);
229
EXPECT_DOUBLE_EQ(h.at<double>(1), 0.);
230
EXPECT_DOUBLE_EQ(h.at<double>(2), 1.);
231
}
232
233
PERF_TEST_P( matchVector, affineBestOf2NearestVectorFeatures, testing::Combine(
234
TEST_DETECTORS,
235
testing::Values(2, 4, 8))
236
)
237
{
238
Mat img1, img1_full = imread( getDataPath("stitching/s1.jpg") );
239
Mat img2, img2_full = imread( getDataPath("stitching/s2.jpg") );
240
float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
241
float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
242
resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
243
resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
244
245
Ptr<detail::FeaturesFinder> finder;
246
Ptr<detail::FeaturesMatcher> matcher;
247
string detectorName = get<0>(GetParam());
248
int featuresVectorSize = get<1>(GetParam());
249
if (detectorName == "surf")
250
{
251
finder = makePtr<detail::SurfFeaturesFinder>();
252
matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, SURF_MATCH_CONFIDENCE);
253
}
254
else if (detectorName == "orb")
255
{
256
finder = makePtr<detail::OrbFeaturesFinder>();
257
matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, ORB_MATCH_CONFIDENCE);
258
}
259
else
260
{
261
FAIL() << "Unknown 2D features type: " << get<0>(GetParam());
262
}
263
264
detail::ImageFeatures features1, features2;
265
(*finder)(img1, features1);
266
(*finder)(img2, features2);
267
vector<detail::ImageFeatures> features;
268
vector<detail::MatchesInfo> pairwise_matches;
269
for(int i = 0; i < featuresVectorSize/2; i++)
270
{
271
features.push_back(features1);
272
features.push_back(features2);
273
}
274
275
declare.time(200);
276
while(next())
277
{
278
cvflann::seed_random(42);//for predictive FlannBasedMatcher
279
startTimer();
280
(*matcher)(features, pairwise_matches);
281
stopTimer();
282
matcher->collectGarbage();
283
}
284
285
size_t matches_count = 0;
286
for (size_t i = 0; i < pairwise_matches.size(); ++i)
287
{
288
if (pairwise_matches[i].src_img_idx < 0)
289
continue;
290
291
EXPECT_TRUE(pairwise_matches[i].matches.size() > 400);
292
EXPECT_FALSE(pairwise_matches[i].H.empty());
293
++matches_count;
294
}
295
296
EXPECT_TRUE(matches_count > 0);
297
298
SANITY_CHECK_NOTHING();
299
}
300
301
} // namespace
302
303