Blender V4.3
homography_test.cc
Go to the documentation of this file.
1// Copyright (c) 2011 libmv authors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to
5// deal in the Software without restriction, including without limitation the
6// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7// sell copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19// IN THE SOFTWARE.
20
24#include "testing/testing.h"
25
26namespace {
27using namespace libmv;
28
29namespace {
30
31// Check whether homography transform M actually transforms
32// given vectors x1 to x2. Used to check validness of a reconstructed
33// homography matrix.
34// TODO(sergey): Consider using this in all tests since possible homography
35// matrix is not fixed to a single value and different-looking matrices
36// might actually crrespond to the same exact transform.
37void CheckHomography2DTransform(const Mat3& H, const Mat& x1, const Mat& x2) {
38 for (int i = 0; i < x2.cols(); ++i) {
39 Vec3 x2_expected = x2.col(i);
40 Vec3 x2_observed = H * x1.col(i);
41 x2_observed /= x2_observed(2);
42 EXPECT_MATRIX_NEAR(x2_expected, x2_observed, 1e-8);
43 }
44}
45
46} // namespace
47
48TEST(Homography2DTest, Rotation45AndTranslationXY) {
49 Mat x1(3, 4);
50 // clang-format off
51 x1 << 0, 1, 0, 5,
52 0, 0, 2, 3,
53 1, 1, 1, 1;
54 // clang-format on
55
56 double angle = 45.0;
57 Mat3 m;
58 // clang-format off
59 m << cos(angle), -sin(angle), -2,
60 sin(angle), cos(angle), 5,
61 0, 0, 1;
62 // clang-format on
63
64 Mat x2 = x1;
65 // Transform point from ground truth matrix
66 for (int i = 0; i < x2.cols(); ++i) {
67 x2.col(i) = m * x1.col(i);
68 }
69
70 Mat3 homography_mat;
71 EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));
72 VLOG(1) << "Mat Homography2D ";
73 VLOG(1) << homography_mat;
74 VLOG(1) << "Mat GT ";
75 VLOG(1) << m;
76 EXPECT_MATRIX_NEAR(homography_mat, m, 1e-8);
77}
78
79TEST(Homography2DTest, AffineGeneral4) {
80 // TODO(julien) find why it doesn't work with 4 points!!!
81 Mat x1(3, 4);
82 // clang-format off
83 x1 << 0, 1, 0, 2,
84 0, 0, 1, 2,
85 1, 1, 1, 1;
86 // clang-format on
87 Mat3 m;
88 // clang-format off
89 m << 3, -1, 4,
90 6, -2, -3,
91 0, 0, 1;
92 // clang-format on
93
94 Mat x2 = x1;
95 for (int i = 0; i < x2.cols(); ++i) {
96 x2.col(i) = m * x1.col(i);
97 }
98
99 Mat3 homography_mat;
100 EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));
101 VLOG(1) << "Mat Homography2D";
102 VLOG(1) << homography_mat;
103 CheckHomography2DTransform(homography_mat, x1, x2);
104
105 // Test with euclidean coordinates
106 Mat eX1, eX2;
107 HomogeneousToEuclidean(x1, &eX1);
108 HomogeneousToEuclidean(x2, &eX2);
109 homography_mat.setIdentity();
110 EXPECT_TRUE(Homography2DFromCorrespondencesLinear(eX1, eX2, &homography_mat));
111
112 VLOG(1) << "Mat Homography2D ";
113 VLOG(1) << homography_mat;
114 CheckHomography2DTransform(homography_mat, x1, x2);
115}
116
117TEST(Homography2DTest, AffineGeneral5) {
118 Mat x1(3, 5);
119 // clang-format off
120 x1 << 0, 1, 0, 2, 5,
121 0, 0, 1, 2, 2,
122 1, 1, 1, 1, 1;
123 // clang-format on
124 Mat3 m;
125 // clang-format off
126 m << 3, -1, 4,
127 6, -2, -3,
128 0, 0, 1;
129 // clang-format on
130
131 Mat x2 = x1;
132 for (int i = 0; i < x2.cols(); ++i) {
133 x2.col(i) = m * x1.col(i);
134 }
135
136 Mat3 homography_mat;
137 EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));
138
139 VLOG(1) << "Mat Homography2D ";
140 VLOG(1) << homography_mat;
141 EXPECT_MATRIX_NEAR(homography_mat, m, 1e-8);
142
143 // Test with euclidean coordinates
144 Mat eX1, eX2;
145 HomogeneousToEuclidean(x1, &eX1);
146 HomogeneousToEuclidean(x2, &eX2);
147 homography_mat.setIdentity();
148 EXPECT_TRUE(Homography2DFromCorrespondencesLinear(eX1, eX2, &homography_mat));
149
150 VLOG(1) << "Mat Homography2D ";
151 VLOG(1) << homography_mat;
152 EXPECT_MATRIX_NEAR(homography_mat, m, 1e-8);
153}
154
155TEST(Homography2DTest, HomographyGeneral) {
156 Mat x1(3, 4);
157 // clang-format off
158 x1 << 0, 1, 0, 5,
159 0, 0, 2, 3,
160 1, 1, 1, 1;
161 // clang-format on
162 Mat3 m;
163 // clang-format off
164 m << 3, -1, 4,
165 6, -2, -3,
166 1, -3, 1;
167 // clang-format on
168
169 Mat x2 = x1;
170 for (int i = 0; i < x2.cols(); ++i) {
171 x2.col(i) = m * x1.col(i);
172 }
173
174 Mat3 homography_mat;
175 EXPECT_TRUE(Homography2DFromCorrespondencesLinear(x1, x2, &homography_mat));
176
177 VLOG(1) << "Mat Homography2D ";
178 VLOG(1) << homography_mat;
179 EXPECT_MATRIX_NEAR(homography_mat, m, 1e-8);
180}
181
182TEST(Homography3DTest, RotationAndTranslationXYZ) {
183 Mat x1(4, 5);
184 // clang-format off
185 x1 << 0, 0, 1, 5, 2,
186 0, 1, 2, 3, 5,
187 0, 2, 0, 1, 5,
188 1, 1, 1, 1, 1;
189 // clang-format on
190 Mat4 M;
191 M.setIdentity();
192 /*
193 M = AngleAxisd(45.0, Vector3f::UnitZ())
194 * AngleAxisd(25.0, Vector3f::UnitX())
195 * AngleAxisd(5.0, Vector3f::UnitZ());*/
196
197 // Rotation on x + translation
198 double angle = 45.0;
199 Mat4 rot;
200 // clang-format off
201 rot << 1, 0, 0, 1,
202 0, cos(angle), -sin(angle), 3,
203 0, sin(angle), cos(angle), -2,
204 0, 0, 0, 1;
205 // clang-format on
206 M *= rot;
207 // Rotation on y
208 angle = 25.0;
209 // clang-format off
210 rot << cos(angle), 0, sin(angle), 0,
211 0, 1, 0, 0,
212 -sin(angle), 0, cos(angle), 0,
213 0, 0, 0, 1;
214 // clang-format on
215 M *= rot;
216 // Rotation on z
217 angle = 5.0;
218 // clang-format off
219 rot << cos(angle), -sin(angle), 0, 0,
220 sin(angle), cos(angle), 0, 0,
221 0, 0, 1, 0,
222 0, 0, 0, 1;
223 // clang-format on
224 M *= rot;
225 Mat x2 = x1;
226 for (int i = 0; i < x2.cols(); ++i) {
227 x2.col(i) = M * x1.col(i);
228 }
229
230 Mat4 homography_mat;
231 EXPECT_TRUE(Homography3DFromCorrespondencesLinear(x1, x2, &homography_mat));
232
233 VLOG(1) << "Mat Homography3D " << homography_mat;
234 VLOG(1) << "Mat GT " << M;
235 EXPECT_MATRIX_NEAR(homography_mat, M, 1e-8);
236}
237
238TEST(Homography3DTest, AffineGeneral) {
239 Mat x1(4, 5);
240 // clang-format off
241 x1 << 0, 0, 1, 5, 2,
242 0, 1, 2, 3, 5,
243 0, 2, 0, 1, 5,
244 1, 1, 1, 1, 1;
245 // clang-format on
246 Mat4 m;
247 // clang-format off
248 m << 3, -1, 4, 1,
249 6, -2, -3, -6,
250 1, 0, 1, 2,
251 0, 0, 0, 1;
252 // clang-format on
253
254 Mat x2 = x1;
255 for (int i = 0; i < x2.cols(); ++i) {
256 x2.col(i) = m * x1.col(i);
257 }
258
259 Mat4 homography_mat;
260 EXPECT_TRUE(Homography3DFromCorrespondencesLinear(x1, x2, &homography_mat));
261 VLOG(1) << "Mat Homography3D ";
262 VLOG(1) << homography_mat;
263 EXPECT_MATRIX_NEAR(homography_mat, m, 1e-8);
264}
265
266TEST(Homography3DTest, HomographyGeneral) {
267 Mat x1(4, 5);
268 // clang-format off
269 x1 << 0, 0, 1, 5, 2,
270 0, 1, 2, 3, 5,
271 0, 2, 0, 1, 5,
272 1, 1, 1, 1, 1;
273 // clang-format on
274 Mat4 m;
275 // clang-format off
276 m << 3, -1, 4, 1,
277 6, -2, -3, -6,
278 1, 0, 1, 2,
279 -3, 1, 0, 1;
280 // clang-format on
281
282 Mat x2 = x1;
283 for (int i = 0; i < x2.cols(); ++i) {
284 x2.col(i) = m * x1.col(i);
285 }
286
287 Mat4 homography_mat;
288 EXPECT_TRUE(Homography3DFromCorrespondencesLinear(x1, x2, &homography_mat));
289 VLOG(1) << "Mat Homography3D";
290 VLOG(1) << homography_mat;
291 EXPECT_MATRIX_NEAR(homography_mat, m, 1e-8);
292}
293
294} // namespace
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
#define rot(x, k)
float[3][3] Mat3
Definition gpu_matrix.cc:28
#define VLOG(severity)
Definition log.h:34
ccl_device_inline float3 cos(float3 v)
#define M
#define H(x, y, z)
T sin(const AngleRadianBase< T > &a)
TEST(PolynomialCameraIntrinsics2, ApplyOnFocalCenter)
void HomogeneousToEuclidean(const Mat &H, Mat *X)
Eigen::MatrixXd Mat
Definition numeric.h:60
bool Homography2DFromCorrespondencesLinear(const Mat &x1, const Mat &x2, Mat3 *H, double expected_precision)
Eigen::Vector3d Vec3
Definition numeric.h:106
bool Homography3DFromCorrespondencesLinear(const Mat &x1, const Mat &x2, Mat4 *H, double expected_precision)