Blender  V2.93
resect_test.cc
Go to the documentation of this file.
1 // Copyright (c) 2009 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 
22 #include "libmv/logging/logging.h"
23 #include "testing/testing.h"
24 
25 #if 0
26 // Generates all necessary inputs and expected outputs for EuclideanResection.
27 void CreateCameraSystem(const Mat3& KK,
28  const Mat3X& x_image,
29  const Vec& X_distances,
30  const Mat3& R_input,
31  const Vec3& T_input,
32  Mat2X *x_camera,
33  Mat3X *X_world,
34  Mat3 *R_expected,
35  Vec3 *T_expected) {
36  int num_points = x_image.cols();
37 
38  Mat3X x_unit_cam(3, num_points);
39  x_unit_cam = KK.inverse() * x_image;
40 
41  // Create normalized camera coordinates to be used as an input to the PnP
42  // function, instead of using NormalizeColumnVectors(&x_unit_cam).
43  *x_camera = x_unit_cam.block(0, 0, 2, num_points);
44  for (int i = 0; i < num_points; ++i) {
45  x_unit_cam.col(i).normalize();
46  }
47 
48  // Create the 3D points in the camera system.
49  Mat X_camera(3, num_points);
50  for (int i = 0; i < num_points; ++i) {
51  X_camera.col(i) = X_distances(i) * x_unit_cam.col(i);
52  }
53 
54  // Apply the transformation to the camera 3D points
55  Mat translation_matrix(3, num_points);
56  translation_matrix.row(0).setConstant(T_input(0));
57  translation_matrix.row(1).setConstant(T_input(1));
58  translation_matrix.row(2).setConstant(T_input(2));
59 
60  *X_world = R_input * X_camera + translation_matrix;
61 
62  // Create the expected result for comparison.
63  *R_expected = R_input.transpose();
64  *T_expected = *R_expected * (-T_input);
65 };
66 
67 TEST(AbsoluteOrientation, QuaternionSolution) {
68  int num_points = 4;
69  Mat X;
70  Mat Xp;
71  X = 100 * Mat::Random(3, num_points);
72 
73  // Create a random translation and rotation.
74  Mat3 R_input;
75  R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ())
76  * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY())
77  * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
78 
79  Vec3 t_input;
80  t_input.setRandom();
81  t_input = 100 * t_input;
82 
83  Mat translation_matrix(3, num_points);
84  translation_matrix.row(0).setConstant(t_input(0));
85  translation_matrix.row(1).setConstant(t_input(1));
86  translation_matrix.row(2).setConstant(t_input(2));
87 
88  // Create the transformed 3D points Xp as Xp = R * X + t.
89  Xp = R_input * X + translation_matrix;
90 
91  // Output variables.
92  Mat3 R;
93  Vec3 t;
94 
95  AbsoluteOrientation(X, Xp, &R, &t);
96 
97  EXPECT_MATRIX_NEAR(t, t_input, 1e-6);
98  EXPECT_MATRIX_NEAR(R, R_input, 1e-8);
99 }
100 
101 TEST(EuclideanResection, Points4KnownImagePointsRandomTranslationRotation) {
102  // In this test only the translation and rotation are random. The image
103  // points are selected from a real case and are well conditioned.
104  Vec2i image_dimensions;
105  image_dimensions << 1600, 1200;
106 
107  Mat3 KK;
108  KK << 2796, 0, 804,
109  0 , 2796, 641,
110  0, 0, 1;
111 
112  // The real image points.
113  int num_points = 4;
114  Mat3X x_image(3, num_points);
115  x_image << 1164.06, 734.948, 749.599, 430.727,
116  681.386, 844.59, 496.315, 580.775,
117  1, 1, 1, 1;
118 
119 
120  // A vector of the 4 distances to the 3D points.
121  Vec X_distances = 100 * Vec::Random(num_points).array().abs();
122 
123  // Create the random camera motion R and t that resection should recover.
124  Mat3 R_input;
125  R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ())
126  * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY())
127  * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
128 
129  Vec3 T_input;
130  T_input.setRandom();
131  T_input = 100 * T_input;
132 
133  // Create the camera system, also getting the expected result of the
134  // transformation.
135  Mat3 R_expected;
136  Vec3 T_expected;
137  Mat3X X_world;
138  Mat2X x_camera;
139  CreateCameraSystem(KK, x_image, X_distances, R_input, T_input,
140  &x_camera, &X_world, &R_expected, &T_expected);
141 
142  // Finally, run the code under test.
143  Mat3 R_output;
144  Vec3 T_output;
145  EuclideanResection(x_camera, X_world,
146  &R_output, &T_output,
148 
149  EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
150  EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
151 
152  // For now, the EPnP doesn't have a non-linear optimization step and so is
153  // not precise enough with only 4 points.
154  //
155  // TODO(jmichot): Reenable this test when there is nonlinear refinement.
156 # if 0
157  R_output.setIdentity();
158  T_output.setZero();
159 
160  EuclideanResection(x_camera, X_world,
161  &R_output, &T_output,
163 
164  EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
165  EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);*/
166 # endif
167 }
168 
169 // TODO(jmichot): Reduce the code duplication here with the code above.
170 TEST(EuclideanResection, Points6AllRandomInput) {
171  Mat3 KK;
172  KK << 2796, 0, 804,
173  0 , 2796, 641,
174  0, 0, 1;
175 
176  // Create random image points for a 1600x1200 image.
177  int w = 1600;
178  int h = 1200;
179  int num_points = 6;
180  Mat3X x_image(3, num_points);
181  x_image.row(0) = w * Vec::Random(num_points).array().abs();
182  x_image.row(1) = h * Vec::Random(num_points).array().abs();
183  x_image.row(2).setOnes();
184 
185  // Normalized camera coordinates to be used as an input to the PnP function.
186  Mat2X x_camera;
187  Vec X_distances = 100 * Vec::Random(num_points).array().abs();
188 
189  // Create the random camera motion R and t that resection should recover.
190  Mat3 R_input;
191  R_input = Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ())
192  * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitY())
193  * Eigen::AngleAxisd(rand(), Eigen::Vector3d::UnitZ());
194 
195  Vec3 T_input;
196  T_input.setRandom();
197  T_input = 100 * T_input;
198 
199  // Create the camera system.
200  Mat3 R_expected;
201  Vec3 T_expected;
202  Mat3X X_world;
203  CreateCameraSystem(KK, x_image, X_distances, R_input, T_input,
204  &x_camera, &X_world, &R_expected, &T_expected);
205 
206  // Test each of the resection methods.
207  {
208  Mat3 R_output;
209  Vec3 T_output;
210  EuclideanResection(x_camera, X_world,
211  &R_output, &T_output,
213  EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
214  EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
215  }
216  {
217  Mat3 R_output;
218  Vec3 T_output;
219  EuclideanResection(x_camera, X_world,
220  &R_output, &T_output,
222  EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
223  EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
224  }
225  {
226  Mat3 R_output;
227  Vec3 T_output;
228  EuclideanResection(x_image, X_world, KK,
229  &R_output, &T_output);
230  EXPECT_MATRIX_NEAR(T_output, T_expected, 1e-5);
231  EXPECT_MATRIX_NEAR(R_output, R_expected, 1e-7);
232  }
233 }
234 #endif
@ TEST
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
#define X
Definition: GeomUtils.cpp:213
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static void CreateCameraSystem(const Mat3 &KK, const Mat3X &x_image, const Vec &X_distances, const Mat3 &R_input, const Vec3 &T_input, Mat2X *x_camera, Mat3X *X_world, Mat3 *R_expected, Vec3 *T_expected)
float[3][3] Mat3
Definition: gpu_matrix.cc:43
#define R
VecMat::Vec2< int > Vec2i
Definition: Geom.h:33
bool EuclideanResection(const Mat2X &x_camera, const Mat3X &X_world, Mat3 *R, Vec3 *t, ResectionMethod method)
void AbsoluteOrientation(const Mat3X &X, const Mat3X &Xp, Mat3 *R, Vec3 *t)
Eigen::VectorXd Vec
Definition: numeric.h:61
Eigen::MatrixXd Mat
Definition: numeric.h:60
Eigen::Vector3d Vec3
Definition: numeric.h:106
Eigen::Matrix< double, 3, Eigen::Dynamic > Mat3X
Definition: numeric.h:92
Eigen::Matrix< double, 2, Eigen::Dynamic > Mat2X
Definition: numeric.h:91