ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
projection.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #include "base/projection.h"
33 
34 #include "base/pose.h"
35 #include "util/matrix.h"
36 
37 namespace colmap {
38 
39 Eigen::Matrix3x4d ComposeProjectionMatrix(const Eigen::Vector4d& qvec,
40  const Eigen::Vector3d& tvec) {
41  Eigen::Matrix3x4d proj_matrix;
42  proj_matrix.leftCols<3>() = QuaternionToRotationMatrix(qvec);
43  proj_matrix.rightCols<1>() = tvec;
44  return proj_matrix;
45 }
46 
47 Eigen::Matrix3x4d ComposeProjectionMatrix(const Eigen::Matrix3d& R,
48  const Eigen::Vector3d& T) {
49  Eigen::Matrix3x4d proj_matrix;
50  proj_matrix.leftCols<3>() = R;
51  proj_matrix.rightCols<1>() = T;
52  return proj_matrix;
53 }
54 
56  Eigen::Matrix3x4d inv_proj_matrix;
57  inv_proj_matrix.leftCols<3>() = proj_matrix.leftCols<3>().transpose();
58  inv_proj_matrix.rightCols<1>() = ProjectionCenterFromMatrix(proj_matrix);
59  return inv_proj_matrix;
60 }
61 
62 Eigen::Matrix3d ComputeClosestRotationMatrix(const Eigen::Matrix3d& matrix) {
63  const Eigen::JacobiSVD<Eigen::Matrix3d> svd(
64  matrix, Eigen::ComputeFullU | Eigen::ComputeFullV);
65  Eigen::Matrix3d R = svd.matrixU() * (svd.matrixV().transpose());
66  if (R.determinant() < 0.0) {
67  R *= -1.0;
68  }
69  return R;
70 }
71 
72 bool DecomposeProjectionMatrix(const Eigen::Matrix3x4d& P, Eigen::Matrix3d* K,
73  Eigen::Matrix3d* R, Eigen::Vector3d* T) {
74  Eigen::Matrix3d RR;
75  Eigen::Matrix3d QQ;
76  DecomposeMatrixRQ(P.leftCols<3>().eval(), &RR, &QQ);
77 
79 
80  const double det_K = RR.determinant();
81  if (det_K == 0) {
82  return false;
83  } else if (det_K > 0) {
84  *K = RR;
85  } else {
86  *K = -RR;
87  }
88 
89  for (int i = 0; i < 3; ++i) {
90  if ((*K)(i, i) < 0.0) {
91  K->col(i) = -K->col(i);
92  R->row(i) = -R->row(i);
93  }
94  }
95 
96  *T = K->triangularView<Eigen::Upper>().solve(P.col(3));
97  if (det_K < 0) {
98  *T = -(*T);
99  }
100 
101  return true;
102 }
103 
104 Eigen::Vector2d ProjectPointToImage(const Eigen::Vector3d& point3D,
105  const Eigen::Matrix3x4d& proj_matrix,
106  const Camera& camera) {
107  const Eigen::Vector3d world_point = proj_matrix * point3D.homogeneous();
108  return camera.WorldToImage(world_point.hnormalized());
109 }
110 
111 double CalculateSquaredReprojectionError(const Eigen::Vector2d& point2D,
112  const Eigen::Vector3d& point3D,
113  const Eigen::Vector4d& qvec,
114  const Eigen::Vector3d& tvec,
115  const Camera& camera) {
116  const Eigen::Vector3d proj_point3D =
117  QuaternionRotatePoint(qvec, point3D) + tvec;
118 
119  // Check that point is infront of camera.
120  if (proj_point3D.z() < std::numeric_limits<double>::epsilon()) {
121  return std::numeric_limits<double>::max();
122  }
123 
124  const Eigen::Vector2d proj_point2D =
125  camera.WorldToImage(proj_point3D.hnormalized());
126 
127  return (proj_point2D - point2D).squaredNorm();
128 }
129 
130 double CalculateSquaredReprojectionError(const Eigen::Vector2d& point2D,
131  const Eigen::Vector3d& point3D,
132  const Eigen::Matrix3x4d& proj_matrix,
133  const Camera& camera) {
134  const double proj_z = proj_matrix.row(2).dot(point3D.homogeneous());
135 
136  // Check that point is infront of camera.
137  if (proj_z < std::numeric_limits<double>::epsilon()) {
138  return std::numeric_limits<double>::max();
139  }
140 
141  const double proj_x = proj_matrix.row(0).dot(point3D.homogeneous());
142  const double proj_y = proj_matrix.row(1).dot(point3D.homogeneous());
143  const double inv_proj_z = 1.0 / proj_z;
144 
145  const Eigen::Vector2d proj_point2D = camera.WorldToImage(
146  Eigen::Vector2d(inv_proj_z * proj_x, inv_proj_z * proj_y));
147 
148  return (proj_point2D - point2D).squaredNorm();
149 }
150 
151 double CalculateAngularError(const Eigen::Vector2d& point2D,
152  const Eigen::Vector3d& point3D,
153  const Eigen::Vector4d& qvec,
154  const Eigen::Vector3d& tvec,
155  const Camera& camera) {
156  return CalculateNormalizedAngularError(camera.ImageToWorld(point2D), point3D,
157  qvec, tvec);
158 }
159 
160 double CalculateAngularError(const Eigen::Vector2d& point2D,
161  const Eigen::Vector3d& point3D,
162  const Eigen::Matrix3x4d& proj_matrix,
163  const Camera& camera) {
164  return CalculateNormalizedAngularError(camera.ImageToWorld(point2D), point3D,
165  proj_matrix);
166 }
167 
168 double CalculateNormalizedAngularError(const Eigen::Vector2d& point2D,
169  const Eigen::Vector3d& point3D,
170  const Eigen::Vector4d& qvec,
171  const Eigen::Vector3d& tvec) {
172  const Eigen::Vector3d ray1 = point2D.homogeneous();
173  const Eigen::Vector3d ray2 = QuaternionRotatePoint(qvec, point3D) + tvec;
174  return std::acos(ray1.normalized().transpose() * ray2.normalized());
175 }
176 
177 double CalculateNormalizedAngularError(const Eigen::Vector2d& point2D,
178  const Eigen::Vector3d& point3D,
179  const Eigen::Matrix3x4d& proj_matrix) {
180  const Eigen::Vector3d ray1 = point2D.homogeneous();
181  const Eigen::Vector3d ray2 = proj_matrix * point3D.homogeneous();
182  return std::acos(ray1.normalized().transpose() * ray2.normalized());
183 }
184 
185 double CalculateDepth(const Eigen::Matrix3x4d& proj_matrix,
186  const Eigen::Vector3d& point3D) {
187  const double proj_z = proj_matrix.row(2).dot(point3D.homogeneous());
188  return proj_z * proj_matrix.col(2).norm();
189 }
190 
191 bool HasPointPositiveDepth(const Eigen::Matrix3x4d& proj_matrix,
192  const Eigen::Vector3d& point3D) {
193  return proj_matrix.row(2).dot(point3D.homogeneous()) >=
194  std::numeric_limits<double>::epsilon();
195 }
196 
197 } // namespace colmap
Eigen::Vector2d ImageToWorld(const Eigen::Vector2d &image_point) const
Definition: camera.cc:219
Eigen::Vector2d WorldToImage(const Eigen::Vector2d &world_point) const
Definition: camera.cc:230
Matrix< double, 3, 4 > Matrix3x4d
Definition: types.h:39
Eigen::Vector3d ProjectionCenterFromMatrix(const Eigen::Matrix3x4d &proj_matrix)
Definition: pose.cc:159
double CalculateSquaredReprojectionError(const Eigen::Vector2d &point2D, const Eigen::Vector3d &point3D, const Eigen::Vector4d &qvec, const Eigen::Vector3d &tvec, const Camera &camera)
Definition: projection.cc:111
bool HasPointPositiveDepth(const Eigen::Matrix3x4d &proj_matrix, const Eigen::Vector3d &point3D)
Definition: projection.cc:191
Eigen::Matrix3x4d InvertProjectionMatrix(const Eigen::Matrix3x4d &proj_matrix)
Definition: projection.cc:55
void DecomposeMatrixRQ(const MatrixType &A, MatrixType *R, MatrixType *Q)
Definition: matrix.h:45
double CalculateDepth(const Eigen::Matrix3x4d &proj_matrix, const Eigen::Vector3d &point3D)
Definition: projection.cc:185
bool DecomposeProjectionMatrix(const Eigen::Matrix3x4d &P, Eigen::Matrix3d *K, Eigen::Matrix3d *R, Eigen::Vector3d *T)
Definition: projection.cc:72
Eigen::Matrix3d ComputeClosestRotationMatrix(const Eigen::Matrix3d &matrix)
Definition: projection.cc:62
Eigen::Vector3d QuaternionRotatePoint(const Eigen::Vector4d &qvec, const Eigen::Vector3d &point)
Definition: pose.cc:110
double CalculateNormalizedAngularError(const Eigen::Vector2d &point2D, const Eigen::Vector3d &point3D, const Eigen::Vector4d &qvec, const Eigen::Vector3d &tvec)
Definition: projection.cc:168
Eigen::Matrix3x4d ComposeProjectionMatrix(const Eigen::Vector4d &qvec, const Eigen::Vector3d &tvec)
Definition: projection.cc:39
Eigen::Vector2d ProjectPointToImage(const Eigen::Vector3d &point3D, const Eigen::Matrix3x4d &proj_matrix, const Camera &camera)
Definition: projection.cc:104
double CalculateAngularError(const Eigen::Vector2d &point2D, const Eigen::Vector3d &point3D, const Eigen::Vector4d &qvec, const Eigen::Vector3d &tvec, const Camera &camera)
Definition: projection.cc:151
Eigen::Matrix3d QuaternionToRotationMatrix(const Eigen::Vector4d &qvec)
Definition: pose.cc:75