ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
triangulation.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 
33 
34 #include <Eigen/Geometry>
35 
36 #include "base/projection.h"
37 #include "base/triangulation.h"
40 #include "optim/loransac.h"
41 #include "util/logging.h"
42 #include "util/math.h"
43 
44 namespace colmap {
45 
46 void TriangulationEstimator::SetMinTriAngle(const double min_tri_angle) {
47  CHECK_GE(min_tri_angle, 0);
48  min_tri_angle_ = min_tri_angle;
49 }
50 
52  residual_type_ = residual_type;
53 }
54 
55 std::vector<TriangulationEstimator::M_t> TriangulationEstimator::Estimate(
56  const std::vector<X_t>& point_data,
57  const std::vector<Y_t>& pose_data) const {
58  CHECK_GE(point_data.size(), 2);
59  CHECK_EQ(point_data.size(), pose_data.size());
60 
61  if (point_data.size() == 2) {
62  // Two-view triangulation.
63 
64  const M_t xyz = TriangulatePoint(
65  pose_data[0].proj_matrix, pose_data[1].proj_matrix,
66  point_data[0].point_normalized, point_data[1].point_normalized);
67 
68  if (HasPointPositiveDepth(pose_data[0].proj_matrix, xyz) &&
69  HasPointPositiveDepth(pose_data[1].proj_matrix, xyz) &&
70  CalculateTriangulationAngle(pose_data[0].proj_center,
71  pose_data[1].proj_center,
72  xyz) >= min_tri_angle_) {
73  return std::vector<M_t>{xyz};
74  }
75  } else {
76  // Multi-view triangulation.
77 
78  std::vector<Eigen::Matrix3x4d> proj_matrices;
79  proj_matrices.reserve(point_data.size());
80  std::vector<Eigen::Vector2d> points;
81  points.reserve(point_data.size());
82  for (size_t i = 0; i < point_data.size(); ++i) {
83  proj_matrices.push_back(pose_data[i].proj_matrix);
84  points.push_back(point_data[i].point_normalized);
85  }
86 
87  const M_t xyz = TriangulateMultiViewPoint(proj_matrices, points);
88 
89  // Check for cheirality constraint.
90  for (const auto& pose : pose_data) {
91  if (!HasPointPositiveDepth(pose.proj_matrix, xyz)) {
92  return std::vector<M_t>();
93  }
94  }
95 
96  // Check for sufficient triangulation angle.
97  for (size_t i = 0; i < pose_data.size(); ++i) {
98  for (size_t j = 0; j < i; ++j) {
99  const double tri_angle = CalculateTriangulationAngle(
100  pose_data[i].proj_center, pose_data[j].proj_center, xyz);
101  if (tri_angle >= min_tri_angle_) {
102  return std::vector<M_t>{xyz};
103  }
104  }
105  }
106  }
107 
108  return std::vector<M_t>();
109 }
110 
111 void TriangulationEstimator::Residuals(const std::vector<X_t>& point_data,
112  const std::vector<Y_t>& pose_data,
113  const M_t& xyz,
114  std::vector<double>* residuals) const {
115  CHECK_EQ(point_data.size(), pose_data.size());
116 
117  residuals->resize(point_data.size());
118 
119  for (size_t i = 0; i < point_data.size(); ++i) {
120  if (residual_type_ == ResidualType::REPROJECTION_ERROR) {
121  (*residuals)[i] = CalculateSquaredReprojectionError(
122  point_data[i].point, xyz, pose_data[i].proj_matrix,
123  *pose_data[i].camera);
124  } else if (residual_type_ == ResidualType::ANGULAR_ERROR) {
125  const double angular_error = CalculateNormalizedAngularError(
126  point_data[i].point_normalized, xyz, pose_data[i].proj_matrix);
127  (*residuals)[i] = angular_error * angular_error;
128  }
129  }
130 }
131 
133  const EstimateTriangulationOptions& options,
134  const std::vector<TriangulationEstimator::PointData>& point_data,
135  const std::vector<TriangulationEstimator::PoseData>& pose_data,
136  std::vector<char>* inlier_mask, Eigen::Vector3d* xyz) {
137  CHECK_NOTNULL(inlier_mask);
138  CHECK_NOTNULL(xyz);
139  CHECK_GE(point_data.size(), 2);
140  CHECK_EQ(point_data.size(), pose_data.size());
141  options.Check();
142 
143  // Robustly estimate track using LORANSAC.
146  ransac(options.ransac_options);
147  ransac.estimator.SetMinTriAngle(options.min_tri_angle);
148  ransac.estimator.SetResidualType(options.residual_type);
149  ransac.local_estimator.SetMinTriAngle(options.min_tri_angle);
150  ransac.local_estimator.SetResidualType(options.residual_type);
151  const auto report = ransac.Estimate(point_data, pose_data);
152  if (!report.success) {
153  return false;
154  }
155 
156  *inlier_mask = report.inlier_mask;
157  *xyz = report.model;
158 
159  return report.success;
160 }
161 
162 } // namespace colmap
int points
void Residuals(const std::vector< X_t > &point_data, const std::vector< Y_t > &pose_data, const M_t &xyz, std::vector< double > *residuals) const
void SetResidualType(const ResidualType residual_type)
void SetMinTriAngle(const double min_tri_angle)
std::vector< M_t > Estimate(const std::vector< X_t > &point_data, const std::vector< Y_t > &pose_data) const
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 EstimateTriangulation(const EstimateTriangulationOptions &options, const std::vector< TriangulationEstimator::PointData > &point_data, const std::vector< TriangulationEstimator::PoseData > &pose_data, std::vector< char > *inlier_mask, Eigen::Vector3d *xyz)
bool HasPointPositiveDepth(const Eigen::Matrix3x4d &proj_matrix, const Eigen::Vector3d &point3D)
Definition: projection.cc:191
Eigen::Vector3d TriangulateMultiViewPoint(const std::vector< Eigen::Matrix3x4d > &proj_matrices, const std::vector< Eigen::Vector2d > &points)
Eigen::Vector3d TriangulatePoint(const Eigen::Matrix3x4d &proj_matrix1, const Eigen::Matrix3x4d &proj_matrix2, const Eigen::Vector2d &point1, const Eigen::Vector2d &point2)
double CalculateNormalizedAngularError(const Eigen::Vector2d &point2D, const Eigen::Vector3d &point3D, const Eigen::Vector4d &qvec, const Eigen::Vector3d &tvec)
Definition: projection.cc:168
double CalculateTriangulationAngle(const Eigen::Vector3d &proj_center1, const Eigen::Vector3d &proj_center2, const Eigen::Vector3d &point3D)
TriangulationEstimator::ResidualType residual_type