ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
absolute_pose.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <Eigen/Core>
11 #include <array>
12 #include <vector>
13 
14 #include "util/alignment.h"
15 #include "util/types.h"
16 
17 namespace colmap {
18 
19 // Analytic solver for the P3P (Perspective-Three-Point) problem.
20 //
21 // The algorithm is based on the following paper:
22 //
23 // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang. Complete Solution
24 // Classification for the Perspective-Three-Point Problem.
25 // http://www.mmrc.iss.ac.cn/~xgao/paper/ieee.pdf
26 class P3PEstimator {
27 public:
28  // The 2D image feature observations.
29  typedef Eigen::Vector2d X_t;
30  // The observed 3D features in the world frame.
31  typedef Eigen::Vector3d Y_t;
32  // The transformation from the world to the camera frame.
34 
35  // The minimum number of samples needed to estimate a model.
36  static const int kMinNumSamples = 3;
37 
38  // Estimate the most probable solution of the P3P problem from a set of
39  // three 2D-3D point correspondences.
40  //
41  // @param points2D Normalized 2D image points as 3x2 matrix.
42  // @param points3D 3D world points as 3x3 matrix.
43  //
44  // @return Most probable pose as length-1 vector of a 3x4 matrix.
45  static std::vector<M_t> Estimate(const std::vector<X_t>& points2D,
46  const std::vector<Y_t>& points3D);
47 
48  // Calculate the squared reprojection error given a set of 2D-3D point
49  // correspondences and a projection matrix.
50  //
51  // @param points2D Normalized 2D image points as Nx2 matrix.
52  // @param points3D 3D world points as Nx3 matrix.
53  // @param proj_matrix 3x4 projection matrix.
54  // @param residuals Output vector of residuals.
55  static void Residuals(const std::vector<X_t>& points2D,
56  const std::vector<Y_t>& points3D,
57  const M_t& proj_matrix,
58  std::vector<double>* residuals);
59 };
60 
61 // EPNP solver for the PNP (Perspective-N-Point) problem. The solver needs a
62 // minimum of 4 2D-3D correspondences.
63 //
64 // The algorithm is based on the following paper:
65 //
66 // Lepetit, Vincent, Francesc Moreno-Noguer, and Pascal Fua.
67 // "Epnp: An accurate o (n) solution to the pnp problem."
68 // International journal of computer vision 81.2 (2009): 155-166.
69 //
70 // The implementation is based on their original open-source release, but is
71 // ported to Eigen and contains several improvements over the original code.
73 public:
74  // The 2D image feature observations.
75  typedef Eigen::Vector2d X_t;
76  // The observed 3D features in the world frame.
77  typedef Eigen::Vector3d Y_t;
78  // The transformation from the world to the camera frame.
80 
81  // The minimum number of samples needed to estimate a model.
82  static const int kMinNumSamples = 4;
83 
84  // Estimate the most probable solution of the P3P problem from a set of
85  // three 2D-3D point correspondences.
86  //
87  // @param points2D Normalized 2D image points as 3x2 matrix.
88  // @param points3D 3D world points as 3x3 matrix.
89  //
90  // @return Most probable pose as length-1 vector of a 3x4 matrix.
91  static std::vector<M_t> Estimate(const std::vector<X_t>& points2D,
92  const std::vector<Y_t>& points3D);
93 
94  // Calculate the squared reprojection error given a set of 2D-3D point
95  // correspondences and a projection matrix.
96  //
97  // @param points2D Normalized 2D image points as Nx2 matrix.
98  // @param points3D 3D world points as Nx3 matrix.
99  // @param proj_matrix 3x4 projection matrix.
100  // @param residuals Output vector of residuals.
101  static void Residuals(const std::vector<X_t>& points2D,
102  const std::vector<Y_t>& points3D,
103  const M_t& proj_matrix,
104  std::vector<double>* residuals);
105 
106 private:
107  bool ComputePose(const std::vector<Eigen::Vector2d>& points2D,
108  const std::vector<Eigen::Vector3d>& points3D,
109  Eigen::Matrix3x4d* proj_matrix);
110 
111  void ChooseControlPoints();
112  bool ComputeBarycentricCoordinates();
113 
114  Eigen::Matrix<double, Eigen::Dynamic, 12> ComputeM();
115  Eigen::Matrix<double, 6, 10> ComputeL6x10(
116  const Eigen::Matrix<double, 12, 12>& Ut);
117  Eigen::Matrix<double, 6, 1> ComputeRho();
118 
119  void FindBetasApprox1(const Eigen::Matrix<double, 6, 10>& L_6x10,
120  const Eigen::Matrix<double, 6, 1>& rho,
121  Eigen::Vector4d* betas);
122  void FindBetasApprox2(const Eigen::Matrix<double, 6, 10>& L_6x10,
123  const Eigen::Matrix<double, 6, 1>& rho,
124  Eigen::Vector4d* betas);
125  void FindBetasApprox3(const Eigen::Matrix<double, 6, 10>& L_6x10,
126  const Eigen::Matrix<double, 6, 1>& rho,
127  Eigen::Vector4d* betas);
128 
129  void RunGaussNewton(const Eigen::Matrix<double, 6, 10>& L_6x10,
130  const Eigen::Matrix<double, 6, 1>& rho,
131  Eigen::Vector4d* betas);
132 
133  double ComputeRT(const Eigen::Matrix<double, 12, 12>& Ut,
134  const Eigen::Vector4d& betas,
135  Eigen::Matrix3d* R,
136  Eigen::Vector3d* t);
137 
138  void ComputeCcs(const Eigen::Vector4d& betas,
139  const Eigen::Matrix<double, 12, 12>& Ut);
140  void ComputePcs();
141 
142  void SolveForSign();
143 
144  void EstimateRT(Eigen::Matrix3d* R, Eigen::Vector3d* t);
145 
146  double ComputeTotalReprojectionError(const Eigen::Matrix3d& R,
147  const Eigen::Vector3d& t);
148 
149  const std::vector<Eigen::Vector2d>* points2D_ = nullptr;
150  const std::vector<Eigen::Vector3d>* points3D_ = nullptr;
151  std::vector<Eigen::Vector3d> pcs_;
152  std::vector<Eigen::Vector4d> alphas_;
153  std::array<Eigen::Vector3d, 4> cws_;
154  std::array<Eigen::Vector3d, 4> ccs_;
155 };
156 
157 } // namespace colmap
static void Residuals(const std::vector< X_t > &points2D, const std::vector< Y_t > &points3D, const M_t &proj_matrix, std::vector< double > *residuals)
static const int kMinNumSamples
Definition: absolute_pose.h:82
Eigen::Vector3d Y_t
Definition: absolute_pose.h:77
static std::vector< M_t > Estimate(const std::vector< X_t > &points2D, const std::vector< Y_t > &points3D)
Eigen::Vector2d X_t
Definition: absolute_pose.h:75
Eigen::Matrix3x4d M_t
Definition: absolute_pose.h:79
static std::vector< M_t > Estimate(const std::vector< X_t > &points2D, const std::vector< Y_t > &points3D)
Eigen::Vector2d X_t
Definition: absolute_pose.h:29
Eigen::Matrix3x4d M_t
Definition: absolute_pose.h:33
static void Residuals(const std::vector< X_t > &points2D, const std::vector< Y_t > &points3D, const M_t &proj_matrix, std::vector< double > *residuals)
static const int kMinNumSamples
Definition: absolute_pose.h:36
Eigen::Vector3d Y_t
Definition: absolute_pose.h:31
Matrix< double, 3, 4 > Matrix3x4d
Definition: types.h:39