1 
2 // Copyright (c) 2010 libmv authors.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 // IN THE SOFTWARE.
21 
22 // This file is part of OpenMVG, an Open Multiple View Geometry C++ library.
23 
24 // Copyright (c) 2012, 2013 Pierre MOULON.
25 
26 // This Source Code Form is subject to the terms of the Mozilla Public
27 // License, v. 2.0. If a copy of the MPL was not distributed with this
28 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
29 
30 #ifndef OPENMVG_MULTIVIEW_SOLVER_FUNDAMENTAL_KERNEL_HPP
31 #define OPENMVG_MULTIVIEW_SOLVER_FUNDAMENTAL_KERNEL_HPP
32 
33 #include <vector>
34 
35 #include "openMVG/multiview/two_view_kernel.hpp"
36 #include "openMVG/numeric/eigen_alias_definition.hpp"
37 
38 namespace openMVG {
39 namespace fundamental {
40 namespace kernel {
41 
42 
43 /**
44  * Seven-point algorithm for solving for the fundamental matrix from point
45  * correspondences. See page 281 in HZ, though oddly they use a different
46  * equation: \f$det(\alpha F_1 + (1-\alpha)F_2) = 0\f$. Since \f$F_1\f$ and
47  * \f$F2\f$ are projective, there's no need to balance the relative scale.
48  * Instead, here, the simpler equation is solved: \f$det(F_1 + \alpha F_2) =
49  * 0\f$.
50  *
51  * \see http://www.cs.unc.edu/~marc/tutorial/node55.html
52  */
53 struct SevenPointSolver {
54   enum { MINIMUM_SAMPLES = 7 };
55   enum { MAX_MODELS = 3 };
56   static void Solve(const Mat2X &x1, const Mat2X &x2, std::vector<Mat3> *F);
57 };
58 
59 struct EightPointSolver {
60   enum { MINIMUM_SAMPLES = 8 };
61   enum { MAX_MODELS = 1 };
62   static void Solve(const Mat2X &x1, const Mat2X &x2, std::vector<Mat3> *Fs);
63 };
64 
65 /**
66  * Build a 9 x n matrix from point matches, where each row is equivalent to the
67  * equation x'T*F*x = 0 for a single correspondence pair (x', x). The domain of
68  * the matrix is a 9 element vector corresponding to F. In other words, set up
69  * the linear system
70  *
71  *   Af = 0,
72  *
73  * where f is the F matrix as a 9-vector rather than a 3x3 matrix (row
74  * major). If the points are well conditioned and there are 8 or more, then
75  * the nullspace should be rank one. If the nullspace is two dimensional,
76  * then the rank 2 constraint must be enforced to identify the appropriate F
77  * matrix.
78  *
79  * Note that this does not resize the matrix A; it is expected to have the
80  * appropriate size already.
81  */
82 template<typename TMatX, typename TMatA>
EncodeEpipolarEquation(const TMatX & x1,const TMatX & x2,TMatA * A)83 inline void EncodeEpipolarEquation(const TMatX &x1, const TMatX &x2, TMatA *A) {
84   assert(x1.rows() == x2.rows());
85   assert(x1.cols() == x2.cols());
86   assert(x1.rows() == 3);
87   for (typename TMatX::Index i = 0; i < x1.cols(); ++i) {
88     A->row(i) <<
89       x2(0, i) * x1.col(i).transpose(),
90       x2(1, i) * x1.col(i).transpose(),
91       x2(2, i) * x1.col(i).transpose();
92   }
93 }
94 
95 /// Compute SampsonError related to the Fundamental matrix and 2 correspondences
96 struct SampsonError {
97   static double Error(const Mat3 &F, const Vec2 &x, const Vec2 &y);
98 };
99 
100 struct SymmetricEpipolarDistanceError {
101   static double Error(const Mat3 &F, const Vec2 &x, const Vec2 &y);
102 };
103 
104 struct EpipolarDistanceError {
105   static double Error(const Mat3 &F, const Vec2 &x, const Vec2 &y);
106 };
107 
108 //-- Kernel solver for the 8pt Fundamental Matrix Estimation
109 using SevenPointKernel = two_view::kernel::Kernel<SevenPointSolver, SampsonError, Mat3>;
110 
111 //-- Kernel solver for the 8pt Fundamental Matrix Estimation
112 using EightPointKernel = two_view::kernel::Kernel<EightPointSolver, SampsonError, Mat3>;
113 
114 //-- Normalized 7pt kernel -> conditioning from HZ (Algo 11.1) pag 282
115 using NormalizedSevenPointKernel =
116   two_view::kernel::Kernel<
117     two_view::kernel::NormalizedSolver<SevenPointSolver, UnnormalizerT>,
118     SampsonError,
119     Mat3>;
120 
121 //-- Normalized 8pt kernel -> conditioning from HZ (Algo 11.1) pag 282
122 using NormalizedEightPointKernel =
123   two_view::kernel::Kernel<
124     two_view::kernel::NormalizedSolver<EightPointSolver, UnnormalizerT>,
125     SampsonError,
126     Mat3>;
127 
128 }  // namespace kernel
129 }  // namespace fundamental
130 }  // namespace openMVG
131 
132 #endif  // OPENMVG_MULTIVIEW_SOLVER_FUNDAMENTAL_KERNEL_HPP
133