23#include "ceres/ceres.h"
36 int first_row = (row + 1) % 3;
37 int second_row = (row + 2) % 3;
39 for (
int i = 0; i < 4; ++i) {
40 (*X)(0, i) =
P(first_row, i);
41 (*X)(1, i) =
P(second_row, i);
46 *P1 << Mat3::Identity(), Vec3::Zero();
48 Mat3 Ft = F.transpose();
59 for (
int i = 0; i < 3; ++i) {
64 for (
int i = 0; i < 3; ++i) {
65 for (
int j = 0; j < 3; ++j) {
67 (*F)(i, j) = XY.determinant();
82 for (
int i = 0; i < n; ++i) {
83 A(i, 0) = x2(0, i) * x1(0, i);
84 A(i, 1) = x2(0, i) * x1(1, i);
86 A(i, 3) = x2(1, i) * x1(0, i);
87 A(i, 4) = x2(1, i) * x1(1, i);
95 double smaller_singular_value =
Nullspace(&A, &f);
97 return smaller_singular_value;
102 Eigen::JacobiSVD<Mat3> USV(*F, Eigen::ComputeFullU | Eigen::ComputeFullV);
103 Vec3 d = USV.singularValues();
105 *F = USV.matrixU() * d.asDiagonal() * USV.matrixV().transpose();
119 Mat x1_normalized, x2_normalized;
124 double smaller_singular_value =
129 *F =
T2.transpose() * (*F) *
T1;
131 return smaller_singular_value;
138 std::vector<Mat3>* F) {
149 Matrix<double, 7, 9>
A;
150 for (
int ii = 0; ii < 7; ++ii) {
151 A(ii, 0) = x1(0, ii) * x2(0, ii);
152 A(ii, 1) = x1(1, ii) * x2(0, ii);
153 A(ii, 2) = x2(0, ii);
154 A(ii, 3) = x1(0, ii) * x2(1, ii);
155 A(ii, 4) = x1(1, ii) * x2(1, ii);
156 A(ii, 5) = x2(1, ii);
157 A(ii, 6) = x1(0, ii);
158 A(ii, 7) = x1(1, ii);
170 double a = F1(0, 0), j = F2(0, 0);
171 double b = F1(0, 1), k = F2(0, 1);
172 double c = F1(0, 2),
l = F2(0, 2);
173 double d = F1(1, 0), m = F2(1, 0);
174 double e = F1(1, 1), n = F2(1, 1);
175 double f = F1(1, 2), o = F2(1, 2);
176 double g = F1(2, 0), p = F2(2, 0);
177 double h = F1(2, 1), q = F2(2, 1);
178 double i = F1(2, 2), r = F2(2, 2);
183 a *
e * i +
b * f * g + c * d * h - a * f * h -
b * d * i - c *
e * g,
184 a *
e * r + a * i * n +
b * f * p +
b * g * o + c * d * q + c * h * m +
185 d * h *
l +
e * i * j + f * g * k - a * f * q - a * h * o -
186 b * d * r -
b * i * m - c *
e * p - c * g * n - d * i * k -
187 e * g *
l - f * h * j,
188 a * n * r +
b * o * p + c * m * q + d *
l * q +
e * j * r + f * k * p +
189 g * k * o + h *
l * m + i * j * n - a * o * q -
b * m * r -
190 c * n * p - d * k * r -
e *
l * p - f * j * q - g *
l * n -
191 h * j * o - i * k * m,
192 j * n * r + k * o * p +
l * m * q - j * o * q - k * m * r -
l * n * p,
200 for (
int kk = 0; kk < num_roots; ++kk) {
201 F->push_back(F1 + roots[kk] * F2);
208 std::vector<Mat3>* F) {
218 Mat x1_normalized, x2_normalized;
224 x1_normalized, x2_normalized, &(*F));
226 for (
int k = 0; k < F->size(); ++k) {
227 Mat3& Fmat = (*F)[k];
229 Fmat =
T2.transpose() * Fmat *
T1;
231 return smaller_singular_value;
236 if ((*F_normalized)(2, 2) < 0) {
242 Vec3 x(x1(0), x1(1), 1.0);
243 Vec3 y(x2(0), x2(1), 1.0);
246 Vec3 Ft_y = F.transpose() *
y;
247 double y_F_x = y.dot(F_x);
250 (F_x.head<2>().squaredNorm() + Ft_y.head<2>().squaredNorm());
254 Vec3 x(x1(0), x1(1), 1.0);
255 Vec3 y(x2(0), x2(1), 1.0);
258 Vec3 Ft_y = F.transpose() *
y;
259 double y_F_x = y.dot(F_x);
262 (1 / F_x.head<2>().squaredNorm() + 1 / Ft_y.head<2>().squaredNorm());
270 *E = K2.transpose() * F * K1;
279 *F = K2.inverse().transpose() * E * K1.inverse();
288 *
R = R2 * R1.transpose();
304 std::vector<Mat3>* Rs,
305 std::vector<Vec3>* ts) {
306 Eigen::JacobiSVD<Mat3> USV(E, Eigen::ComputeFullU | Eigen::ComputeFullV);
307 Mat3 U = USV.matrixU();
308 Mat3 Vt = USV.matrixV().transpose();
311 if (
U.determinant() < 0) {
315 if (Vt.determinant() < 0) {
327 Mat3 U_Wt_Vt =
U *
W.transpose() * Vt;
337 (*ts)[1] = -
U.col(2);
339 (*ts)[3] = -
U.col(2);
343 const std::vector<Vec3>& ts,
357 for (
int i = 0; i < 4; ++i) {
358 const Mat3& R2 = Rs[i];
359 const Vec3& t2 = ts[i];
363 double d1 =
Depth(R1, t1,
X);
364 double d2 =
Depth(R2, t2,
X);
366 if (d1 > 0 && d2 > 0) {
380 std::vector<Mat3> Rs;
381 std::vector<Vec3> ts;
394 Eigen::JacobiSVD<Mat3> svd(F, Eigen::ComputeFullU | Eigen::ComputeFullV);
398 double a = svd.singularValues()(0);
399 double b = svd.singularValues()(1);
400 double s = (a +
b) / 2.0;
402 LG <<
"Initial reconstruction's rotation is non-euclidean by "
403 << (((a -
b) / std::max(a,
b)) * 100)
404 <<
"%; singular values:" << svd.singularValues().transpose();
409 *E = svd.matrixU() * diag.asDiagonal() * svd.matrixV().transpose();
415 : max_num_iterations(50), expected_average_symmetric_distance(1
e-16) {
421class FundamentalSymmetricEpipolarCostFunctor {
423 FundamentalSymmetricEpipolarCostFunctor(
const Vec2& x,
const Vec2& y)
426 template <
typename T>
427 bool operator()(
const T* fundamental_parameters, T* residuals)
const {
428 typedef Eigen::Matrix<T, 3, 3>
Mat3;
429 typedef Eigen::Matrix<T, 3, 1>
Vec3;
431 Mat3 F(fundamental_parameters);
437 Vec3 Ft_y = F.transpose() *
y;
438 T y_F_x = y.dot(F_x);
440 residuals[0] = y_F_x *
T(1) / F_x.head(2).norm();
441 residuals[1] = y_F_x *
T(1) / Ft_y.head(2).norm();
454class TerminationCheckingCallback :
public ceres::IterationCallback {
456 TerminationCheckingCallback(
const Mat& x1,
458 const EstimateFundamentalOptions&
options,
460 : options_(
options), x1_(x1), x2_(x2), F_(F) {}
463 const ceres::IterationSummary& summary) {
465 if (!summary.step_is_successful) {
466 return ceres::SOLVER_CONTINUE;
470 double average_distance = 0.0;
471 for (
int i = 0; i < x1_.cols(); i++) {
474 average_distance /= x1_.cols();
476 if (average_distance <= options_.expected_average_symmetric_distance) {
477 return ceres::SOLVER_TERMINATE_SUCCESSFULLY;
480 return ceres::SOLVER_CONTINUE;
484 const EstimateFundamentalOptions& options_;
502 LG <<
"Estimated matrix after algebraic estimation:\n" << *
F;
505 ceres::Problem problem;
506 for (
int i = 0; i < x1.cols(); i++) {
507 FundamentalSymmetricEpipolarCostFunctor*
508 fundamental_symmetric_epipolar_cost_function =
509 new FundamentalSymmetricEpipolarCostFunctor(x1.col(i), x2.col(i));
511 problem.AddResidualBlock(
512 new ceres::AutoDiffCostFunction<FundamentalSymmetricEpipolarCostFunctor,
515 fundamental_symmetric_epipolar_cost_function),
521 ceres::Solver::Options solver_options;
522 solver_options.linear_solver_type = ceres::DENSE_QR;
523 solver_options.max_num_iterations =
options.max_num_iterations;
524 solver_options.update_state_every_iteration =
true;
528 solver_options.callbacks.push_back(&
callback);
531 ceres::Solver::Summary summary;
532 ceres::Solve(solver_options, &problem, &summary);
534 VLOG(1) <<
"Summary:\n" << summary.FullReport();
536 LG <<
"Final refined matrix:\n" << *
F;
538 return summary.IsSolutionUsable();
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
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
local_group_size(16, 16) .push_constant(Type b
CCL_NAMESPACE_BEGIN struct Options options
DEGForeachIDComponentCallback callback
double FundamentalFrom7CorrespondencesLinear(const Mat &x1, const Mat &x2, std::vector< Mat3 > *F)
int SolveCubicPolynomial(Real a, Real b, Real c, Real *x0, Real *x1, Real *x2)
void EssentialFromRt(const Mat3 &R1, const Vec3 &t1, const Mat3 &R2, const Vec3 &t2, Mat3 *E)
double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2)
double Nullspace(TMat *A, TVec *nullspace)
void FundamentalFromEssential(const Mat3 &E, const Mat3 &K1, const Mat3 &K2, Mat3 *F)
void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F)
bool EstimateFundamentalFromCorrespondences(const Mat &x1, const Mat &x2, const EstimateFundamentalOptions &options, Mat3 *F)
Mat3 CrossProductMatrix(const Vec3 &x)
static void EliminateRow(const Mat34 &P, int row, Mat *X)
void PreconditionerFromPoints(const Mat &points, Mat3 *T)
void VerticalStack(const TTop &top, const TBot &bottom, TStacked *stacked)
Eigen::Matrix< double, 3, 3 > Mat3
void TriangulateDLT(const Mat34 &P1, const Vec2 &x1, const Mat34 &P2, const Vec2 &x2, Vec4 *X_homogeneous)
void EnforceFundamentalRank2Constraint(Mat3 *F)
double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X)
void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2)
void MotionFromEssential(const Mat3 &E, std::vector< Mat3 > *Rs, std::vector< Vec3 > *ts)
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
void NormalizeFundamental(const Mat3 &F, Mat3 *F_normalized)
void ApplyTransformationToPoints(const Mat &points, const Mat3 &T, Mat *transformed_points)
int MotionFromEssentialChooseSolution(const std::vector< Mat3 > &Rs, const std::vector< Vec3 > &ts, const Mat3 &K1, const Vec2 &x1, const Mat3 &K2, const Vec2 &x2)
void EssentialFromFundamental(const Mat3 &F, const Mat3 &K1, const Mat3 &K2, Mat3 *E)
double NormalizedEightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F)
void RelativeCameraMotion(const Mat3 &R1, const Vec3 &t1, const Mat3 &R2, const Vec3 &t2, Mat3 *R, Vec3 *t)
static double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F)
double FrobeniusNorm(const TMat &A)
double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2)
void FundamentalToEssential(const Mat3 &F, Mat3 *E)
Eigen::Matrix< double, 9, 1 > Vec9
double FundamentalFromCorrespondences7Point(const Mat &x1, const Mat &x2, std::vector< Mat3 > *F)
double Nullspace2(TMat *A, TVec1 *x1, TVec2 *x2)
void P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t, Mat34 *P)
EstimateFundamentalOptions(void)