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