Blender V5.0
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
55 EuclideanReconstruction* reconstruction) {
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;
66 CoordinatesForMarkersInImage(markers, image1, &x1);
67 CoordinatesForMarkersInImage(markers, image2, &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 }
137 const vector<Marker>& markers;
138};
139
140} // namespace
141
143 ProjectiveReconstruction* reconstruction) {
144 if (markers.size() < 16) {
145 return false;
146 }
147
148 int image1, image2;
149 GetImagesInMarkers(markers, &image1, &image2);
150
151 Mat x1, x2;
152 CoordinatesForMarkersInImage(markers, image1, &x1);
153 CoordinatesForMarkersInImage(markers, image2, &x2);
154
155 Mat3 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)
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition btTransform.h:90
void InsertCamera(int image, const Mat3 &R, const Vec3 &t)
float[3][3] Mat3
Definition gpu_matrix.cc:28
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define LG
#define LOG(level)
Definition log.h:97
#define CHECK_EQ(a, b)
Definition log.h:120
#define F
#define R
Eigen::VectorXd Vec
Definition numeric.h:64
double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2)
Eigen::Matrix< double, 3, 3 > Mat3
Definition numeric.h:75
bool ProjectiveReconstructTwoFrames(const vector< Marker > &markers, ProjectiveReconstruction *reconstruction)
Eigen::Vector2d Vec2
Definition numeric.h:108
Eigen::MatrixXd Mat
Definition numeric.h:63
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:76
std::vector< ElementType, Eigen::aligned_allocator< ElementType > > vector
double NormalizedEightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F)
Eigen::Vector3d Vec3
Definition numeric.h:109
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:115
int track
Definition marker.h:43
i
Definition text_draw.cc:230