Blender V4.3
initialize_reconstruction.cc
Go to the documentation of this file.
1// Copyright (c) 2011 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
22
23#include "libmv/base/vector.h"
31
32namespace libmv {
33namespace {
34
35void GetImagesInMarkers(const vector<Marker>& markers,
36 int* image1,
37 int* image2) {
38 if (markers.size() < 2) {
39 return;
40 }
41 *image1 = markers[0].image;
42 for (int i = 1; i < markers.size(); ++i) {
43 if (markers[i].image != *image1) {
44 *image2 = markers[i].image;
45 return;
46 }
47 }
48 *image2 = -1;
49 LOG(FATAL) << "Only one image in the markers.";
50}
51
52} // namespace
53
56 if (markers.size() < 16) {
57 LG << "Not enough markers to initialize from two frames: "
58 << markers.size();
59 return false;
60 }
61
62 int image1, image2;
63 GetImagesInMarkers(markers, &image1, &image2);
64
65 Mat x1, x2;
68
69 Mat3 F;
71
72 // The F matrix should be an E matrix, but squash it just to be sure.
73 Mat3 E;
75
76 // Recover motion between the two images. Since this function assumes a
77 // calibrated camera, use the identity for K.
78 Mat3 R;
79 Vec3 t;
80 Mat3 K = Mat3::Identity();
82 E, K, x1.col(0), K, x2.col(0), &R, &t)) {
83 LG << "Failed to compute R and t from E and K.";
84 return false;
85 }
86
87 // Image 1 gets the reference frame, image 2 gets the relative motion.
88 reconstruction->InsertCamera(image1, Mat3::Identity(), Vec3::Zero());
89 reconstruction->InsertCamera(image2, R, t);
90
91 LG << "From two frame reconstruction got:\nR:\n"
92 << R << "\nt:" << t.transpose();
93 return true;
94}
95
96namespace {
97
98Mat3 DecodeF(const Vec9& encoded_F) {
99 // Decode F and force it to be rank 2.
100 Map<const Mat3> full_rank_F(encoded_F.data(), 3, 3);
101 Eigen::JacobiSVD<Mat3> svd(full_rank_F,
102 Eigen::ComputeFullU | Eigen::ComputeFullV);
103 Vec3 diagonal = svd.singularValues();
104 diagonal(2) = 0;
105 Mat3 F = svd.matrixU() * diagonal.asDiagonal() * svd.matrixV().transpose();
106 return F;
107}
108
109// This is the stupidest way to refine F known to mankind, since it requires
110// doing a full SVD of F at each iteration. This uses sampson error.
111struct FundamentalSampsonCostFunction {
112 public:
113 typedef Vec FMatrixType;
114 typedef Vec9 XMatrixType;
115
116 // Assumes markers are ordered by track.
117 explicit FundamentalSampsonCostFunction(const vector<Marker>& markers)
118 : markers(markers) {}
119
120 Vec operator()(const Vec9& encoded_F) const {
121 // Decode F and force it to be rank 2.
122 Mat3 F = DecodeF(encoded_F);
123
124 Vec residuals(markers.size() / 2);
125 residuals.setZero();
126 for (int i = 0; i < markers.size() / 2; ++i) {
127 const Marker& marker1 = markers[2 * i + 0];
128 const Marker& marker2 = markers[2 * i + 1];
129 CHECK_EQ(marker1.track, marker2.track);
130 Vec2 x1(marker1.x, marker1.y);
131 Vec2 x2(marker2.x, marker2.y);
132
133 residuals[i] = SampsonDistance(F, x1, x2);
134 }
135 return residuals;
136 }
138};
139
140} // namespace
141
144 if (markers.size() < 16) {
145 return false;
146 }
147
148 int image1, image2;
149 GetImagesInMarkers(markers, &image1, &image2);
150
151 Mat x1, x2;
154
155 Mat3 F;
156 NormalizedEightPointSolver(x1, x2, &F);
157
158 // XXX Verify sampson distance.
159#if 0
160 // Refine the resulting projection fundamental matrix using Sampson's
161 // approximation of geometric error. This avoids having to do a full bundle
162 // at the cost of some accuracy.
163 //
164 // TODO(keir): After switching to a better bundling library, use a proper
165 // full bundle adjust here instead of this lame bundle adjustment.
167
168 FundamentalSampsonCostFunction fundamental_cost(markers);
169
170 // Pack the initial P matrix into a size-12 vector..
171 Vec9 encoded_F = Map<Vec9>(F.data(), 3, 3);
172
173 Solver solver(fundamental_cost);
174
175 Solver::SolverParameters params;
176 Solver::Results results = solver.minimize(params, &encoded_F);
177 // TODO(keir): Check results to ensure clean termination.
178
179 // Recover F from the minimization.
180 F = DecodeF(encoded_F);
181#endif
182
183 // Image 1 gets P = [I|0], image 2 gets arbitrary P.
184 Mat34 P1 = Mat34::Zero();
185 P1.block<3, 3>(0, 0) = Mat3::Identity();
186 Mat34 P2;
187 ProjectionsFromFundamental(F, &P1, &P2);
188
189 reconstruction->InsertCamera(image1, P1);
190 reconstruction->InsertCamera(image2, P2);
191
192 LG << "From two frame reconstruction got P2:\n" << P2;
193 return true;
194}
195} // namespace libmv
#define K(key)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition btTransform.h:90
float[3][3] Mat3
Definition gpu_matrix.cc:28
const vector< Marker > & markers
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
const ProjectiveReconstruction & reconstruction
Definition intersect.cc:198
#define LG
#define CHECK_EQ(a, b)
Definition log.h:46
#define LOG(severity)
Definition log.h:33
#define F
#define R
Eigen::VectorXd Vec
Definition numeric.h:61
double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2)
Eigen::Matrix< double, 3, 3 > Mat3
Definition numeric.h:72
bool ProjectiveReconstructTwoFrames(const vector< Marker > &markers, ProjectiveReconstruction *reconstruction)
Eigen::MatrixXd Mat
Definition numeric.h:60
bool EuclideanReconstructTwoFrames(const vector< Marker > &markers, EuclideanReconstruction *reconstruction)
void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2)
bool MotionFromEssentialAndCorrespondence(const Mat3 &E, const Mat3 &K1, const Vec2 &x1, const Mat3 &K2, const Vec2 &x2, Mat3 *R, Vec3 *t)
Eigen::Matrix< double, 3, 4 > Mat34
Definition numeric.h:73
double NormalizedEightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F)
Eigen::Vector3d Vec3
Definition numeric.h:106
void CoordinatesForMarkersInImage(const vector< Marker > &markers, int image, Mat *coordinates)
void FundamentalToEssential(const Mat3 &F, Mat3 *E)
Eigen::Matrix< double, 9, 1 > Vec9
Definition numeric.h:112