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