1 // This file is part of OpenMVG, an Open Multiple View Geometry C++ library.
2
3 // Copyright (c) 2012, 2013 Pierre MOULON.
4
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9 #include "openMVG/multiview/solver_resection_kernel.hpp"
10 #include "openMVG/multiview/solver_resection_p3p.hpp"
11 #include "openMVG/multiview/solver_resection_up2p_kukelova.hpp"
12 #include "openMVG/multiview/test_data_sets.hpp"
13
14 #include "testing/testing.h"
15
16 using namespace openMVG;
17
TEST(Resection_Kernel_DLT,Multiview)18 TEST(Resection_Kernel_DLT, Multiview) {
19
20 const int nViews = 3;
21 const int nbPoints = 10;
22 const NViewDataSet d =
23 NRealisticCamerasRing(nViews, nbPoints,
24 nViewDatasetConfigurator(1,1,0,0,5,0)); // Suppose a camera with Unit matrix as K
25
26 // Solve the problem and check that fitted value are good enough
27 for (int nResectionCameraIndex = 0; nResectionCameraIndex < nViews; ++nResectionCameraIndex)
28 {
29 const Mat x = d._x[nResectionCameraIndex];
30 const Mat X = d._X;
31 openMVG::resection::kernel::PoseResectionKernel kernel(x, X);
32
33 std::vector<Mat34> Ps;
34 kernel.Fit({0,1,2,3,4,5}, &Ps);
35 for (Mat::Index i = 0; i < x.cols(); ++i) {
36 EXPECT_NEAR(0.0, kernel.Error(i, Ps[0]), 1e-8);
37 }
38
39 CHECK_EQUAL(1, Ps.size());
40
41 // Check that Projection matrix is near to the GT:
42 Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array()
43 / d.P(nResectionCameraIndex).norm();
44 Mat34 COMPUTED_ProjectionMatrix = Ps[0].array() / Ps[0].norm();
45 EXPECT_MATRIX_NEAR(GT_ProjectionMatrix, COMPUTED_ProjectionMatrix, 1e-8);
46 }
47 }
48
TEST(P3P_Kneip_CVPR11,Multiview)49 TEST(P3P_Kneip_CVPR11, Multiview) {
50
51 const int nViews = 3;
52 const int nbPoints = 3;
53 const NViewDataSet d =
54 NRealisticCamerasRing(nViews, nbPoints,
55 nViewDatasetConfigurator(1,1,0,0,5,0)); // Suppose a camera with Unit matrix as K
56
57 // Solve the problem and check that fitted value are good enough
58 for (int nResectionCameraIndex = 0; nResectionCameraIndex < nViews; ++nResectionCameraIndex)
59 {
60 const Mat x = d._x[nResectionCameraIndex];
61 const Mat bearing_vectors = (d._K[0].inverse() * x.colwise().homogeneous()).colwise().normalized();
62 const Mat X = d._X;
63 openMVG::euclidean_resection::PoseResectionKernel_P3P_Kneip kernel(bearing_vectors, X);
64
65 std::vector<Mat34> Ps;
66 kernel.Fit({0,1,2}, &Ps); // 3 points sample are required, lets take the first three
67
68 bool bFound = false;
69 char index = -1;
70 for (size_t i = 0; i < Ps.size(); ++i) {
71 Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array()
72 / d.P(nResectionCameraIndex).norm();
73 Mat34 COMPUTED_ProjectionMatrix = Ps[i].array() / Ps[i].norm();
74 if ( NormLInfinity(GT_ProjectionMatrix - COMPUTED_ProjectionMatrix) < 1e-8 )
75 {
76 bFound = true;
77 index = i;
78 }
79 }
80 EXPECT_TRUE(bFound);
81
82 // Check that for the found matrix the residual is small
83 for (Mat::Index i = 0; i < x.cols(); ++i) {
84 EXPECT_NEAR(0.0, kernel.Error(i, Ps[index]), 1e-8);
85 }
86 }
87 }
88
TEST(P3P_Ke_CVPR17,Multiview)89 TEST(P3P_Ke_CVPR17, Multiview) {
90
91 const int nViews = 3;
92 const int nbPoints = 3;
93 const NViewDataSet d =
94 NRealisticCamerasRing(nViews, nbPoints,
95 nViewDatasetConfigurator(1,1,0,0,5,0)); // Suppose a camera with Unit matrix as K
96
97
98
99 // Solve the problem and check that fitted value are good enough
100 for (int nResectionCameraIndex = 0; nResectionCameraIndex < nViews; ++nResectionCameraIndex)
101 {
102 const Mat x = d._x[nResectionCameraIndex];
103 const Mat bearing_vectors = (d._K[0].inverse() * x.colwise().homogeneous()).colwise().normalized();
104 const Mat X = d._X;
105 openMVG::euclidean_resection::PoseResectionKernel_P3P_Ke kernel(bearing_vectors, X);
106 std::vector<Mat34> Ps;
107 kernel.Fit({0,1,2}, &Ps); // 3 points sample are required, lets take the first three
108
109 bool bFound = false;
110 char index = -1;
111 for (size_t i = 0; i < Ps.size(); ++i) {
112 Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array()
113 / d.P(nResectionCameraIndex).norm();
114 Mat34 COMPUTED_ProjectionMatrix = Ps[i].array() / Ps[i].norm();
115 if ( NormLInfinity(GT_ProjectionMatrix - COMPUTED_ProjectionMatrix) < 1e-8 )
116 {
117 bFound = true;
118 index = i;
119 }
120 }
121 EXPECT_TRUE(bFound);
122
123 // Check that for the found matrix the residual is small
124 for (Mat::Index i = 0; i < x.cols(); ++i) {
125 EXPECT_NEAR(0.0, kernel.Error(i, Ps[index]), 1e-8);
126 }
127 }
128 }
129
130
TEST(P3P_Nordberg_ECCV18,Multiview)131 TEST(P3P_Nordberg_ECCV18, Multiview) {
132
133 const int nViews = 3;
134 const int nbPoints = 3;
135 const NViewDataSet d =
136 NRealisticCamerasRing(nViews, nbPoints,
137 nViewDatasetConfigurator(1,1,0,0,5,0)); // Suppose a camera with Unit matrix as K
138
139
140
141 // Solve the problem and check that fitted value are good enough
142 for (int nResectionCameraIndex = 0; nResectionCameraIndex < nViews; ++nResectionCameraIndex)
143 {
144 const Mat x = d._x[nResectionCameraIndex];
145 const Mat bearing_vectors = (d._K[0].inverse() * x.colwise().homogeneous()).colwise().normalized();
146 const Mat X = d._X;
147 openMVG::euclidean_resection::PoseResectionKernel_P3P_Nordberg kernel(bearing_vectors, X);
148
149 std::vector<Mat34> Ps;
150 kernel.Fit({0,1,2}, &Ps); // 3 points sample are required, lets take the first three
151
152 bool bFound = false;
153 size_t index = -1;
154 for (size_t i = 0; i < Ps.size(); ++i) {
155 Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array()
156 / d.P(nResectionCameraIndex).norm();
157 Mat34 COMPUTED_ProjectionMatrix = Ps[i].array() / Ps[i].norm();
158 if ( NormLInfinity(GT_ProjectionMatrix - COMPUTED_ProjectionMatrix) < 1e-8 )
159 {
160 bFound = true;
161 index = i;
162 }
163 }
164 EXPECT_TRUE(bFound);
165
166 // Check that for the found matrix the residual is small
167 for (Mat::Index i = 0; i < x.cols(); ++i) {
168 EXPECT_NEAR(0.0, kernel.Error(i, Ps[index]), 1e-8);
169 }
170 }
171 }
172
TEST(UP2PSolver_Kukelova,Multiview)173 TEST(UP2PSolver_Kukelova, Multiview) {
174
175 const int nViews = 6;
176 const int nbPoints = 2;
177 const NViewDataSet d =
178 NRealisticCamerasRing(nViews, nbPoints,
179 nViewDatasetConfigurator(1,1,0,0,5,0)); // Suppose a camera with Unit matrix as K
180
181 // Solve the problem and check that fitted value are good enough
182 for (int nResectionCameraIndex = 0; nResectionCameraIndex < nViews; ++nResectionCameraIndex)
183 {
184 const Mat x = d._x[nResectionCameraIndex];
185 const Mat bearing_vectors = (d._K[0].inverse() * x.colwise().homogeneous()).colwise().normalized();
186 const Mat X = d._X;
187 openMVG::euclidean_resection::PoseResectionKernel_UP2P_Kukelova kernel(bearing_vectors, X);
188
189 std::vector<Mat34> Ps;
190 kernel.Fit({0,1}, &Ps); // 2 points sample are required, lets take the first three
191
192 bool bFound = false;
193 size_t index = -1;
194 for (size_t i = 0; i < Ps.size(); ++i) {
195 const Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array()
196 / d.P(nResectionCameraIndex).norm();
197 const Mat34 COMPUTED_ProjectionMatrix = Ps[i].array() / Ps[i].norm();
198 std::cout << "GT:\n " << GT_ProjectionMatrix << std::endl;
199 std::cout << "Computed:\n " << COMPUTED_ProjectionMatrix << std::endl;
200 if ( NormLInfinity(GT_ProjectionMatrix - COMPUTED_ProjectionMatrix) < 1e-8 )
201 {
202 bFound = true;
203 index = i;
204 }
205 }
206 EXPECT_TRUE(bFound);
207
208 // Check that for the found matrix the residual is small
209 for (Mat::Index i = 0; i < x.cols(); ++i) {
210 EXPECT_NEAR(0.0, kernel.Error(i, Ps[index]), 1e-8);
211 }
212 }
213 }
214
215 /* ************************************************************************* */
main()216 int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
217 /* ************************************************************************* */
218