1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31
32 #define TEST_NAME "feature/types"
33 #include "util/testing.h"
34
35 #include <unordered_set>
36
37 #include "feature/types.h"
38 #include "util/math.h"
39
40 using namespace colmap;
41
BOOST_AUTO_TEST_CASE(TestFeatureKeypoints)42 BOOST_AUTO_TEST_CASE(TestFeatureKeypoints) {
43 FeatureKeypoint keypoint;
44 BOOST_CHECK_EQUAL(keypoint.x, 0.0f);
45 BOOST_CHECK_EQUAL(keypoint.y, 0.0f);
46 BOOST_CHECK_EQUAL(keypoint.a11, 1.0f);
47 BOOST_CHECK_EQUAL(keypoint.a12, 0.0f);
48 BOOST_CHECK_EQUAL(keypoint.a21, 0.0f);
49 BOOST_CHECK_EQUAL(keypoint.a22, 1.0f);
50
51 FeatureKeypoints keypoints(1);
52 BOOST_CHECK_EQUAL(keypoints.size(), 1);
53 BOOST_CHECK_EQUAL(keypoints[0].x, 0.0f);
54 BOOST_CHECK_EQUAL(keypoints[0].y, 0.0f);
55 BOOST_CHECK_EQUAL(keypoints[0].a11, 1.0f);
56 BOOST_CHECK_EQUAL(keypoints[0].a12, 0.0f);
57 BOOST_CHECK_EQUAL(keypoints[0].a21, 0.0f);
58 BOOST_CHECK_EQUAL(keypoints[0].a22, 1.0f);
59
60 keypoint = FeatureKeypoint(1, 2);
61 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
62 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
63 BOOST_CHECK_EQUAL(keypoint.a11, 1.0f);
64 BOOST_CHECK_EQUAL(keypoint.a12, 0.0f);
65 BOOST_CHECK_EQUAL(keypoint.a21, 0.0f);
66 BOOST_CHECK_EQUAL(keypoint.a22, 1.0f);
67 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 1.0f), 1e-6);
68 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 1.0f), 1e-6);
69 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 1.0f), 1e-6);
70 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - 0.0f), 1e-6);
71 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
72
73 keypoint = FeatureKeypoint(1, 2, 0, 0);
74 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
75 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
76 BOOST_CHECK_EQUAL(keypoint.a11, 0.0f);
77 BOOST_CHECK_EQUAL(keypoint.a12, 0.0f);
78 BOOST_CHECK_EQUAL(keypoint.a21, 0.0f);
79 BOOST_CHECK_EQUAL(keypoint.a22, 0.0f);
80
81 keypoint = FeatureKeypoint(1, 2, 1, 0);
82 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
83 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
84 BOOST_CHECK_EQUAL(keypoint.a11, 1.0f);
85 BOOST_CHECK_EQUAL(keypoint.a12, 0.0f);
86 BOOST_CHECK_EQUAL(keypoint.a21, 0.0f);
87 BOOST_CHECK_EQUAL(keypoint.a22, 1.0f);
88 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 1.0f), 1e-6);
89 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 1.0f), 1e-6);
90 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 1.0f), 1e-6);
91 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - 0.0f), 1e-6);
92 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
93
94 keypoint = FeatureKeypoint(1, 2, 1, M_PI / 2);
95 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
96 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
97 BOOST_CHECK_LT(std::abs(keypoint.a11 - 0.0f), 1e-6);
98 BOOST_CHECK_LT(std::abs(keypoint.a12 - -1.0f), 1e-6);
99 BOOST_CHECK_LT(std::abs(keypoint.a21 - 1.0f), 1e-6);
100 BOOST_CHECK_LT(std::abs(keypoint.a22 - 0.0f), 1e-6);
101 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 1.0f), 1e-6);
102 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 1.0f), 1e-6);
103 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 1.0f), 1e-6);
104 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - M_PI / 2), 1e-6);
105 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
106
107 keypoint = FeatureKeypoint(1, 2, 2, M_PI / 2);
108 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
109 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
110 BOOST_CHECK_LT(std::abs(keypoint.a11 - 0.0f), 1e-6);
111 BOOST_CHECK_LT(std::abs(keypoint.a12 - -2.0f), 1e-6);
112 BOOST_CHECK_LT(std::abs(keypoint.a21 - 2.0f), 1e-6);
113 BOOST_CHECK_LT(std::abs(keypoint.a22 - 0.0f), 1e-6);
114 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2.0f), 1e-6);
115 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2.0f), 1e-6);
116 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 2.0f), 1e-6);
117 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - M_PI / 2), 1e-6);
118 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
119
120 keypoint = FeatureKeypoint(1, 2, 2, M_PI);
121 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
122 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
123 BOOST_CHECK_LT(std::abs(keypoint.a11 - -2.0f), 1e-6);
124 BOOST_CHECK_LT(std::abs(keypoint.a12 - 0.0f), 1e-6);
125 BOOST_CHECK_LT(std::abs(keypoint.a21 - 0.0), 1e-6);
126 BOOST_CHECK_LT(std::abs(keypoint.a22 - -2.0f), 1e-6);
127 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2.0f), 1e-6);
128 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2.0f), 1e-6);
129 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 2.0f), 1e-6);
130 BOOST_CHECK(std::abs(keypoint.ComputeOrientation() - M_PI) < 1e-6 ||
131 std::abs(keypoint.ComputeOrientation() + M_PI) < 1e-6);
132 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
133
134 keypoint = FeatureKeypoint::FromParameters(1, 2, 2, 2, M_PI, 0);
135 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
136 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
137 BOOST_CHECK_LT(std::abs(keypoint.a11 - -2.0f), 1e-6);
138 BOOST_CHECK_LT(std::abs(keypoint.a12 - 0.0f), 1e-6);
139 BOOST_CHECK_LT(std::abs(keypoint.a21 - 0.0), 1e-6);
140 BOOST_CHECK_LT(std::abs(keypoint.a22 - -2.0f), 1e-6);
141 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2.0f), 1e-6);
142 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2.0f), 1e-6);
143 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 2.0f), 1e-6);
144 BOOST_CHECK(std::abs(keypoint.ComputeOrientation() - M_PI) < 1e-6 ||
145 std::abs(keypoint.ComputeOrientation() + M_PI) < 1e-6);
146 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
147
148 keypoint = FeatureKeypoint::FromParameters(1, 2, 2, 3, M_PI, 0);
149 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
150 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
151 BOOST_CHECK_LT(std::abs(keypoint.a11 - -2.0f), 1e-6);
152 BOOST_CHECK_LT(std::abs(keypoint.a12 - 0.0f), 1e-6);
153 BOOST_CHECK_LT(std::abs(keypoint.a21 - 0.0), 1e-6);
154 BOOST_CHECK_LT(std::abs(keypoint.a22 - -3.0f), 1e-6);
155 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2.5f), 1e-6);
156 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2.0f), 1e-6);
157 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 3.0f), 1e-6);
158 BOOST_CHECK(std::abs(keypoint.ComputeOrientation() - M_PI) < 1e-6 ||
159 std::abs(keypoint.ComputeOrientation() + M_PI) < 1e-6);
160 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - 0.0f), 1e-6);
161
162 keypoint = FeatureKeypoint::FromParameters(1, 2, 2, 3, -M_PI / 2, M_PI / 4);
163 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
164 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
165 BOOST_CHECK_LT(std::abs(keypoint.a11 - 0.0f), 1e-6);
166 BOOST_CHECK_LT(std::abs(keypoint.a12 - 2.12132025f), 1e-6);
167 BOOST_CHECK_LT(std::abs(keypoint.a21 - -2.0f), 1e-6);
168 BOOST_CHECK_LT(std::abs(keypoint.a22 - 2.12132025f), 1e-6);
169 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2.5f), 1e-6);
170 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2.0f), 1e-6);
171 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 3.0f), 1e-6);
172 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - -M_PI / 2), 1e-6);
173 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - M_PI / 4), 1e-6);
174
175 keypoint = FeatureKeypoint::FromParameters(1, 2, 2, 3, M_PI / 2, M_PI / 4);
176 BOOST_CHECK_EQUAL(keypoint.x, 1.0f);
177 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
178 BOOST_CHECK_LT(std::abs(keypoint.a11 - 0.0f), 1e-6);
179 BOOST_CHECK_LT(std::abs(keypoint.a12 - -2.12132025f), 1e-6);
180 BOOST_CHECK_LT(std::abs(keypoint.a21 - 2.0f), 1e-6);
181 BOOST_CHECK_LT(std::abs(keypoint.a22 - -2.12132025f), 1e-6);
182 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2.5f), 1e-6);
183 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2.0f), 1e-6);
184 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 3.0f), 1e-6);
185 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - M_PI / 2), 1e-6);
186 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - M_PI / 4), 1e-6);
187
188 keypoint.Rescale(2, 2);
189 BOOST_CHECK_EQUAL(keypoint.x, 2.0f);
190 BOOST_CHECK_EQUAL(keypoint.y, 4.0f);
191 BOOST_CHECK_LT(std::abs(keypoint.a11 - 2 * 0.0f), 1e-6);
192 BOOST_CHECK_LT(std::abs(keypoint.a12 - 2 * -2.12132025f), 1e-6);
193 BOOST_CHECK_LT(std::abs(keypoint.a21 - 2 * 2.0f), 1e-6);
194 BOOST_CHECK_LT(std::abs(keypoint.a22 - 2 * -2.12132025f), 1e-6);
195 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 2 * 2.5f), 1e-6);
196 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2 * 2.0f), 1e-6);
197 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 2 * 3.0f), 1e-6);
198 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - M_PI / 2), 1e-6);
199 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - M_PI / 4), 1e-6);
200
201 keypoint.Rescale(1, 0.5);
202 BOOST_CHECK_EQUAL(keypoint.x, 2.0f);
203 BOOST_CHECK_EQUAL(keypoint.y, 2.0f);
204 BOOST_CHECK_LT(std::abs(keypoint.a11 - 2 * 0.0f), 1e-6);
205 BOOST_CHECK_LT(std::abs(keypoint.a12 - -2.12132025f), 1e-6);
206 BOOST_CHECK_LT(std::abs(keypoint.a21 - 2 * 2.0f), 1e-6);
207 BOOST_CHECK_LT(std::abs(keypoint.a22 - -2.12132025f), 1e-6);
208 BOOST_CHECK_LT(std::abs(keypoint.ComputeScale() - 3.5f), 1e-6);
209 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleX() - 2 * 2.0f), 1e-6);
210 BOOST_CHECK_LT(std::abs(keypoint.ComputeScaleY() - 3.0f), 1e-6);
211 BOOST_CHECK_LT(std::abs(keypoint.ComputeOrientation() - M_PI / 2), 1e-6);
212 BOOST_CHECK_LT(std::abs(keypoint.ComputeShear() - M_PI / 4), 1e-6);
213 }
214
BOOST_AUTO_TEST_CASE(TestFeatureDescriptors)215 BOOST_AUTO_TEST_CASE(TestFeatureDescriptors) {
216 FeatureDescriptors descriptors = FeatureDescriptors::Random(2, 3);
217 BOOST_CHECK_EQUAL(descriptors.rows(), 2);
218 BOOST_CHECK_EQUAL(descriptors.cols(), 3);
219 BOOST_CHECK_EQUAL(descriptors(0, 0), descriptors.data()[0]);
220 BOOST_CHECK_EQUAL(descriptors(0, 1), descriptors.data()[1]);
221 BOOST_CHECK_EQUAL(descriptors(0, 2), descriptors.data()[2]);
222 BOOST_CHECK_EQUAL(descriptors(1, 0), descriptors.data()[3]);
223 BOOST_CHECK_EQUAL(descriptors(1, 1), descriptors.data()[4]);
224 BOOST_CHECK_EQUAL(descriptors(1, 2), descriptors.data()[5]);
225 }
226
BOOST_AUTO_TEST_CASE(TestFeatureMatches)227 BOOST_AUTO_TEST_CASE(TestFeatureMatches) {
228 FeatureMatch match;
229 BOOST_CHECK_EQUAL(match.point2D_idx1, kInvalidPoint2DIdx);
230 BOOST_CHECK_EQUAL(match.point2D_idx2, kInvalidPoint2DIdx);
231 FeatureMatches matches(1);
232 BOOST_CHECK_EQUAL(matches.size(), 1);
233 BOOST_CHECK_EQUAL(matches[0].point2D_idx1, kInvalidPoint2DIdx);
234 BOOST_CHECK_EQUAL(matches[0].point2D_idx2, kInvalidPoint2DIdx);
235 }
236
BOOST_AUTO_TEST_CASE(TestFeatureMatchHashing)237 BOOST_AUTO_TEST_CASE(TestFeatureMatchHashing) {
238 std::unordered_set<std::pair<point2D_t, point2D_t>> set;
239 set.emplace(1, 2);
240 BOOST_CHECK_EQUAL(set.size(), 1);
241 set.emplace(1, 2);
242 BOOST_CHECK_EQUAL(set.size(), 1);
243 BOOST_CHECK_EQUAL(set.count(std::make_pair(0, 0)), 0);
244 BOOST_CHECK_EQUAL(set.count(std::make_pair(1, 2)), 1);
245 BOOST_CHECK_EQUAL(set.count(std::make_pair(2, 1)), 0);
246 set.emplace(2, 1);
247 BOOST_CHECK_EQUAL(set.size(), 2);
248 BOOST_CHECK_EQUAL(set.count(std::make_pair(0, 0)), 0);
249 BOOST_CHECK_EQUAL(set.count(std::make_pair(1, 2)), 1);
250 BOOST_CHECK_EQUAL(set.count(std::make_pair(2, 1)), 1);
251 }
252