Blender V4.3
two_view_kernel.h
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
21#ifndef LIBMV_MULTIVIEW_TWO_VIEW_KERNEL_H_
22#define LIBMV_MULTIVIEW_TWO_VIEW_KERNEL_H_
23
24#include "libmv/base/vector.h"
28
29namespace libmv {
30namespace two_view {
31namespace kernel {
32
33template <typename Solver, typename Unnormalizer>
35 enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
36 static void Solve(const Mat& x1, const Mat& x2, vector<Mat3>* models) {
37 assert(2 == x1.rows());
38 assert(MINIMUM_SAMPLES <= x1.cols());
39 assert(x1.rows() == x2.rows());
40 assert(x1.cols() == x2.cols());
41
42 // Normalize the data.
43 Mat3 T1, T2;
44 Mat x1_normalized, x2_normalized;
45 NormalizePoints(x1, &x1_normalized, &T1);
46 NormalizePoints(x2, &x2_normalized, &T2);
47
48 Solver::Solve(x1_normalized, x2_normalized, models);
49
50 for (int i = 0; i < models->size(); ++i) {
51 Unnormalizer::Unnormalize(T1, T2, &(*models)[i]);
52 }
53 }
54};
55
56template <typename Solver, typename Unnormalizer>
58 enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
59 static void Solve(const Mat& x1, const Mat& x2, vector<Mat3>* models) {
60 assert(2 == x1.rows());
61 assert(MINIMUM_SAMPLES <= x1.cols());
62 assert(x1.rows() == x2.rows());
63 assert(x1.cols() == x2.cols());
64
65 // Normalize the data.
66 Mat3 T1, T2;
67 Mat x1_normalized, x2_normalized;
68 NormalizeIsotropicPoints(x1, &x1_normalized, &T1);
69 NormalizeIsotropicPoints(x2, &x2_normalized, &T2);
70
71 Solver::Solve(x1_normalized, x2_normalized, models);
72
73 for (int i = 0; i < models->size(); ++i) {
74 Unnormalizer::Unnormalize(T1, T2, &(*models)[i]);
75 }
76 }
77};
78// This is one example (targeted at solvers that operate on correspondences
79// between two views) that shows the "kernel" part of a robust fitting
80// problem:
81//
82// 1. The model; Mat3 in the case of the F or H matrix.
83// 2. The minimum number of samples needed to fit; 7 or 8 (or 4).
84// 3. A way to convert samples to a model.
85// 4. A way to convert a sample and a model to an error.
86//
87// Of particular note is that the kernel does not expose what the samples are.
88// All the robust fitting algorithm sees is that there is some number of
89// samples; it is able to fit subsets of them (via the kernel) and check their
90// error, but can never access the samples themselves.
91//
92// The Kernel objects must follow the following concept so that the robust
93// fitting alogrithm can fit this type of relation:
94//
95// 1. Kernel::Model
96// 2. Kernel::MINIMUM_SAMPLES
97// 3. Kernel::Fit(vector<int>, vector<Kernel::Model> *)
98// 4. Kernel::Error(int, Model) -> error
99//
100// The fit routine must not clear existing entries in the vector of models; it
101// should append new solutions to the end.
102template <typename SolverArg, typename ErrorArg, typename ModelArg = Mat3>
103class Kernel {
104 public:
105 Kernel(const Mat& x1, const Mat& x2) : x1_(x1), x2_(x2) {}
106 typedef SolverArg Solver;
107 typedef ModelArg Model;
108 enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
109 void Fit(const vector<int>& samples, vector<Model>* models) const {
110 Mat x1 = ExtractColumns(x1_, samples);
111 Mat x2 = ExtractColumns(x2_, samples);
112 Solver::Solve(x1, x2, models);
113 }
114 double Error(int sample, const Model& model) const {
115 return ErrorArg::Error(model,
116 static_cast<Vec>(x1_.col(sample)),
117 static_cast<Vec>(x2_.col(sample)));
118 }
119 int NumSamples() const { return x1_.cols(); }
120 static void Solve(const Mat& x1, const Mat& x2, vector<Model>* models) {
121 // By offering this, Kernel types can be passed to templates.
122 Solver::Solve(x1, x2, models);
123 }
124
125 protected:
126 const Mat& x1_;
127 const Mat& x2_;
128};
129
130} // namespace kernel
131} // namespace two_view
132} // namespace libmv
133
134#endif // LIBMV_MULTIVIEW_TWO_VIEW_KERNEL_H_
static void Solve(const Mat &x1, const Mat &x2, vector< Model > *models)
double Error(int sample, const Model &model) const
Kernel(const Mat &x1, const Mat &x2)
void Fit(const vector< int > &samples, vector< Model > *models) const
#define T2
Definition md5.cpp:19
#define T1
Definition md5.cpp:18
Eigen::VectorXd Vec
Definition numeric.h:61
void NormalizePoints(const Mat &points, Mat *normalized_points, Mat3 *T)
Eigen::Matrix< double, 3, 3 > Mat3
Definition numeric.h:72
Eigen::MatrixXd Mat
Definition numeric.h:60
void NormalizeIsotropicPoints(const Mat &points, Mat *normalized_points, Mat3 *T)
std::vector< ElementType, Eigen::aligned_allocator< ElementType > > vector
TMat ExtractColumns(const TMat &A, const TCols &columns)
Definition numeric.h:434
static void Solve(const Mat &x1, const Mat &x2, vector< Mat3 > *models)
static void Solve(const Mat &x1, const Mat &x2, vector< Mat3 > *models)