Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/features2d/test/test_descriptors_invariance.impl.hpp
16356 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html
4
5
#include "test_invariance_utils.hpp"
6
7
namespace opencv_test { namespace {
8
9
#define SHOW_DEBUG_LOG 1
10
11
typedef tuple<std::string, Ptr<FeatureDetector>, Ptr<DescriptorExtractor>, float>
12
String_FeatureDetector_DescriptorExtractor_Float_t;
13
14
15
static
16
void rotateKeyPoints(const vector<KeyPoint>& src, const Mat& H, float angle, vector<KeyPoint>& dst)
17
{
18
// suppose that H is rotation given from rotateImage() and angle has value passed to rotateImage()
19
vector<Point2f> srcCenters, dstCenters;
20
KeyPoint::convert(src, srcCenters);
21
22
perspectiveTransform(srcCenters, dstCenters, H);
23
24
dst = src;
25
for(size_t i = 0; i < dst.size(); i++)
26
{
27
dst[i].pt = dstCenters[i];
28
float dstAngle = src[i].angle + angle;
29
if(dstAngle >= 360.f)
30
dstAngle -= 360.f;
31
dst[i].angle = dstAngle;
32
}
33
}
34
35
class DescriptorInvariance : public TestWithParam<String_FeatureDetector_DescriptorExtractor_Float_t>
36
{
37
protected:
38
virtual void SetUp() {
39
// Read test data
40
const std::string filename = cvtest::TS::ptr()->get_data_path() + get<0>(GetParam());
41
image0 = imread(filename);
42
ASSERT_FALSE(image0.empty()) << "couldn't read input image";
43
44
featureDetector = get<1>(GetParam());
45
descriptorExtractor = get<2>(GetParam());
46
minInliersRatio = get<3>(GetParam());
47
}
48
49
Ptr<FeatureDetector> featureDetector;
50
Ptr<DescriptorExtractor> descriptorExtractor;
51
float minInliersRatio;
52
Mat image0;
53
};
54
55
typedef DescriptorInvariance DescriptorScaleInvariance;
56
typedef DescriptorInvariance DescriptorRotationInvariance;
57
58
TEST_P(DescriptorRotationInvariance, rotation)
59
{
60
Mat image1, mask1;
61
const int borderSize = 16;
62
Mat mask0(image0.size(), CV_8UC1, Scalar(0));
63
mask0(Rect(borderSize, borderSize, mask0.cols - 2*borderSize, mask0.rows - 2*borderSize)).setTo(Scalar(255));
64
65
vector<KeyPoint> keypoints0;
66
Mat descriptors0;
67
featureDetector->detect(image0, keypoints0, mask0);
68
std::cout << "Keypoints: " << keypoints0.size() << std::endl;
69
EXPECT_GE(keypoints0.size(), 15u);
70
descriptorExtractor->compute(image0, keypoints0, descriptors0);
71
72
BFMatcher bfmatcher(descriptorExtractor->defaultNorm());
73
74
const float minIntersectRatio = 0.5f;
75
const int maxAngle = 360, angleStep = 15;
76
for(int angle = 0; angle < maxAngle; angle += angleStep)
77
{
78
Mat H = rotateImage(image0, mask0, static_cast<float>(angle), image1, mask1);
79
80
vector<KeyPoint> keypoints1;
81
rotateKeyPoints(keypoints0, H, static_cast<float>(angle), keypoints1);
82
Mat descriptors1;
83
descriptorExtractor->compute(image1, keypoints1, descriptors1);
84
85
vector<DMatch> descMatches;
86
bfmatcher.match(descriptors0, descriptors1, descMatches);
87
88
int descInliersCount = 0;
89
for(size_t m = 0; m < descMatches.size(); m++)
90
{
91
const KeyPoint& transformed_p0 = keypoints1[descMatches[m].queryIdx];
92
const KeyPoint& p1 = keypoints1[descMatches[m].trainIdx];
93
if(calcIntersectRatio(transformed_p0.pt, 0.5f * transformed_p0.size,
94
p1.pt, 0.5f * p1.size) >= minIntersectRatio)
95
{
96
descInliersCount++;
97
}
98
}
99
100
float descInliersRatio = static_cast<float>(descInliersCount) / keypoints0.size();
101
EXPECT_GE(descInliersRatio, minInliersRatio);
102
#if SHOW_DEBUG_LOG
103
std::cout
104
<< "angle = " << angle
105
<< ", inliers = " << descInliersCount
106
<< ", descInliersRatio = " << static_cast<float>(descInliersCount) / keypoints0.size()
107
<< std::endl;
108
#endif
109
}
110
}
111
112
113
TEST_P(DescriptorScaleInvariance, scale)
114
{
115
vector<KeyPoint> keypoints0;
116
featureDetector->detect(image0, keypoints0);
117
std::cout << "Keypoints: " << keypoints0.size() << std::endl;
118
EXPECT_GE(keypoints0.size(), 15u);
119
Mat descriptors0;
120
descriptorExtractor->compute(image0, keypoints0, descriptors0);
121
122
BFMatcher bfmatcher(descriptorExtractor->defaultNorm());
123
for(int scaleIdx = 1; scaleIdx <= 3; scaleIdx++)
124
{
125
float scale = 1.f + scaleIdx * 0.5f;
126
127
Mat image1;
128
resize(image0, image1, Size(), 1./scale, 1./scale, INTER_LINEAR_EXACT);
129
130
vector<KeyPoint> keypoints1;
131
scaleKeyPoints(keypoints0, keypoints1, 1.0f/scale);
132
Mat descriptors1;
133
descriptorExtractor->compute(image1, keypoints1, descriptors1);
134
135
vector<DMatch> descMatches;
136
bfmatcher.match(descriptors0, descriptors1, descMatches);
137
138
const float minIntersectRatio = 0.5f;
139
int descInliersCount = 0;
140
for(size_t m = 0; m < descMatches.size(); m++)
141
{
142
const KeyPoint& transformed_p0 = keypoints0[descMatches[m].queryIdx];
143
const KeyPoint& p1 = keypoints0[descMatches[m].trainIdx];
144
if(calcIntersectRatio(transformed_p0.pt, 0.5f * transformed_p0.size,
145
p1.pt, 0.5f * p1.size) >= minIntersectRatio)
146
{
147
descInliersCount++;
148
}
149
}
150
151
float descInliersRatio = static_cast<float>(descInliersCount) / keypoints0.size();
152
EXPECT_GE(descInliersRatio, minInliersRatio);
153
#if SHOW_DEBUG_LOG
154
std::cout
155
<< "scale = " << scale
156
<< ", inliers = " << descInliersCount
157
<< ", descInliersRatio = " << static_cast<float>(descInliersCount) / keypoints0.size()
158
<< std::endl;
159
#endif
160
}
161
}
162
163
#undef SHOW_DEBUG_LOG
164
}} // namespace
165
166
namespace std {
167
using namespace opencv_test;
168
static inline void PrintTo(const String_FeatureDetector_DescriptorExtractor_Float_t& v, std::ostream* os)
169
{
170
*os << "(\"" << get<0>(v)
171
<< "\", " << get<3>(v)
172
<< ")";
173
}
174
} // namespace
175
176