Blender V4.3
resect.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 <cstdio>
24
25#include "libmv/base/vector.h"
34
35namespace libmv {
36namespace {
37
38Mat2X PointMatrixFromMarkers(const vector<Marker>& markers) {
39 Mat2X points(2, markers.size());
40 for (int i = 0; i < markers.size(); ++i) {
41 points(0, i) = markers[i].x;
42 points(1, i) = markers[i].y;
43 }
44 return points;
45}
46
47// Uses an incremental rotation:
48//
49// x = R' * R * X + t;
50//
51// to avoid issues with the rotation representation. R' is derived from a
52// euler vector encoding the rotation in 3 parameters; the direction is the
53// axis to rotate around and the magnitude is the amount of the rotation.
54struct EuclideanResectCostFunction {
55 public:
56 typedef Vec FMatrixType;
57 typedef Vec6 XMatrixType;
58
59 EuclideanResectCostFunction(const vector<Marker>& markers,
60 const EuclideanReconstruction& reconstruction,
61 const Mat3& initial_R)
65
66 // dRt has dR (delta R) encoded as a euler vector in the first 3 parameters,
67 // followed by t in the next 3 parameters.
68 Vec operator()(const Vec6& dRt) const {
69 // Unpack R, t from dRt.
70 Mat3 R = RotationFromEulerVector(dRt.head<3>()) * initial_R;
71 Vec3 t = dRt.tail<3>();
72
73 // Compute the reprojection error for each coordinate.
74 Vec residuals(2 * markers.size());
75 residuals.setZero();
76 for (int i = 0; i < markers.size(); ++i) {
77 const EuclideanPoint& point =
78 *reconstruction.PointForTrack(markers[i].track);
79 Vec3 projected = R * point.X + t;
80 projected /= projected(2);
81 residuals[2 * i + 0] = projected(0) - markers[i].x;
82 residuals[2 * i + 1] = projected(1) - markers[i].y;
83 }
84 return residuals;
85 }
86
88 const EuclideanReconstruction& reconstruction;
90};
91
92} // namespace
93
96 bool final_pass) {
97 if (markers.size() < 5) {
98 return false;
99 }
100 Mat2X points_2d = PointMatrixFromMarkers(markers);
101 Mat3X points_3d(3, markers.size());
102 for (int i = 0; i < markers.size(); i++) {
103 points_3d.col(i) = reconstruction->PointForTrack(markers[i].track)->X;
104 }
105 LG << "Points for resect:\n" << points_2d;
106
107 Mat3 R;
108 Vec3 t;
109
110 if (0 ||
112 points_2d, points_3d, &R, &t, euclidean_resection::RESECTION_EPNP)) {
113 // printf("Resection for image %d failed\n", markers[0].image);
114 LG << "Resection for image " << markers[0].image << " failed;"
115 << " trying fallback projective resection.";
116
117 LG << "No fallback; failing resection for " << markers[0].image;
118 return false;
119
120 if (!final_pass) {
121 return false;
122 }
123 // Euclidean resection failed. Fall back to projective resection, which is
124 // less reliable but better conditioned when there are many points.
125 Mat34 P;
126 Mat4X points_3d_homogeneous(4, markers.size());
127 for (int i = 0; i < markers.size(); i++) {
128 points_3d_homogeneous.col(i).head<3>() = points_3d.col(i);
129 points_3d_homogeneous(3, i) = 1.0;
130 }
131 resection::Resection(points_2d, points_3d_homogeneous, &P);
132 if ((P * points_3d_homogeneous.col(0))(2) < 0) {
133 LG << "Point behind camera; switch sign.";
134 P = -P;
135 }
136
137 Mat3 ignored;
138 KRt_From_P(P, &ignored, &R, &t);
139
140 // The R matrix should be a rotation, but don't rely on it.
141 Eigen::JacobiSVD<Mat3> svd(R, Eigen::ComputeFullU | Eigen::ComputeFullV);
142
143 LG << "Resection rotation is: " << svd.singularValues().transpose();
144 LG << "Determinant is: " << R.determinant();
145
146 // Correct to make R a rotation.
147 R = svd.matrixU() * svd.matrixV().transpose();
148
149 Vec3 xx = R * points_3d.col(0) + t;
150 if (xx(2) < 0.0) {
151 LG << "Final point is still behind camera...";
152 }
153 // XXX Need to check if error is horrible and fail here too in that case.
154 }
155
156 // Refine the result.
158
159 // Give the cost our initial guess for R.
160 EuclideanResectCostFunction resect_cost(markers, *reconstruction, R);
161
162 // Encode the initial parameters: start with zero delta rotation, and the
163 // guess for t obtained from resection.
164 Vec6 dRt = Vec6::Zero();
165 dRt.tail<3>() = t;
166
167 Solver solver(resect_cost);
168
169 Solver::SolverParameters params;
170 /* Solver::Results results = */ solver.minimize(params, &dRt);
171 LG << "LM found incremental rotation: " << dRt.head<3>().transpose();
172 // TODO(keir): Check results to ensure clean termination.
173
174 // Unpack the rotation and translation.
175 R = RotationFromEulerVector(dRt.head<3>()) * R;
176 t = dRt.tail<3>();
177
178 LG << "Resection for image " << markers[0].image << " got:\n"
179 << "R:\n"
180 << R << "\nt:\n"
181 << t;
182 reconstruction->InsertCamera(markers[0].image, R, t);
183 return true;
184}
185
186namespace {
187
188// Directly parameterize the projection matrix, P, which is a 12 parameter
189// homogeneous entry. In theory P should be parameterized with only 11
190// parametetrs, but in practice it works fine to let the extra degree of
191// freedom drift.
192struct ProjectiveResectCostFunction {
193 public:
194 typedef Vec FMatrixType;
195 typedef Vec12 XMatrixType;
196
197 ProjectiveResectCostFunction(const vector<Marker>& markers,
198 const ProjectiveReconstruction& reconstruction)
200
201 Vec operator()(const Vec12& vector_P) const {
202 // Unpack P from vector_P.
203 Map<const Mat34> P(vector_P.data(), 3, 4);
204
205 // Compute the reprojection error for each coordinate.
206 Vec residuals(2 * markers.size());
207 residuals.setZero();
208 for (int i = 0; i < markers.size(); ++i) {
209 const ProjectivePoint& point =
210 *reconstruction.PointForTrack(markers[i].track);
211 Vec3 projected = P * point.X;
212 projected /= projected(2);
213 residuals[2 * i + 0] = projected(0) - markers[i].x;
214 residuals[2 * i + 1] = projected(1) - markers[i].y;
215 }
216 return residuals;
217 }
218
219 const vector<Marker>& markers;
220 const ProjectiveReconstruction& reconstruction;
221};
222
223} // namespace
224
227 if (markers.size() < 5) {
228 return false;
229 }
230
231 // Stack the homogeneous 3D points as the columns of a matrix.
232 Mat2X points_2d = PointMatrixFromMarkers(markers);
233 Mat4X points_3d_homogeneous(4, markers.size());
234 for (int i = 0; i < markers.size(); i++) {
235 points_3d_homogeneous.col(i) =
237 }
238 LG << "Points for resect:\n" << points_2d;
239
240 // Resection the point.
241 Mat34 P;
242 resection::Resection(points_2d, points_3d_homogeneous, &P);
243
244 // Flip the sign of P if necessary to keep the point in front of the camera.
245 if ((P * points_3d_homogeneous.col(0))(2) < 0) {
246 LG << "Point behind camera; switch sign.";
247 P = -P;
248 }
249
250 // TODO(keir): Check if error is horrible and fail in that case.
251
252 // Refine the resulting projection matrix using geometric error.
254
255 ProjectiveResectCostFunction resect_cost(markers, *reconstruction);
256
257 // Pack the initial P matrix into a size-12 vector..
258 Vec12 vector_P = Map<Vec12>(P.data());
259
260 Solver solver(resect_cost);
261
262 Solver::SolverParameters params;
263 /* Solver::Results results = */ solver.minimize(params, &vector_P);
264 // TODO(keir): Check results to ensure clean termination.
265
266 // Unpack the projection matrix.
267 P = Map<Mat34>(vector_P.data(), 3, 4);
268
269 LG << "Resection for image " << markers[0].image << " got:\n"
270 << "P:\n"
271 << P;
273 return true;
274}
275} // namespace libmv
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
btMatrix3x3 transpose() const
Return the transpose of the matrix.
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition btTransform.h:90
ProjectivePoint * PointForTrack(int track)
Returns a pointer to the point corresponding to track.
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 R
bool EuclideanResection(const Mat2X &x_camera, const Mat3X &X_world, Mat3 *R, Vec3 *t, ResectionMethod method)
void Resection(const Matrix< T, 2, Dynamic > &x, const Matrix< T, 4, Dynamic > &X, Matrix< T, 3, 4 > *P)
Definition resection.h:37
Eigen::VectorXd Vec
Definition numeric.h:61
Eigen::Matrix< double, 6, 1 > Vec6
Definition numeric.h:109
bool ProjectiveResect(const vector< Marker > &markers, ProjectiveReconstruction *reconstruction)
Definition resect.cc:225
Mat3 RotationFromEulerVector(Vec3 euler_vector)
Returns the rotaiton matrix built from given vector of euler angles.
Definition numeric.h:484
Eigen::Matrix< double, 3, 3 > Mat3
Definition numeric.h:72
bool EuclideanResect(const vector< Marker > &markers, EuclideanReconstruction *reconstruction, bool final_pass)
Definition resect.cc:94
void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp)
Definition projection.cc:32
Eigen::Matrix< double, 3, 4 > Mat34
Definition numeric.h:73
Eigen::Vector3d Vec3
Definition numeric.h:106
Eigen::Matrix< double, 4, Eigen::Dynamic > Mat4X
Definition numeric.h:93
Eigen::Matrix< double, 3, Eigen::Dynamic > Mat3X
Definition numeric.h:92
Eigen::Matrix< double, 12, 1 > Vec12
Definition numeric.h:115
Eigen::Matrix< double, 2, Eigen::Dynamic > Mat2X
Definition numeric.h:91
const Mat3 & initial_R
Definition resect.cc:89