camenduru commited on
Commit
31d76f2
·
1 Parent(s): f176d85

ceres-solver-v2

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +6 -0
  2. colmap/bin/colmap +3 -0
  3. colmap/include/colmap/base/camera.h +211 -0
  4. colmap/include/colmap/base/camera_database.h +58 -0
  5. colmap/include/colmap/base/camera_models.h +1533 -0
  6. colmap/include/colmap/base/camera_rig.h +128 -0
  7. colmap/include/colmap/base/correspondence_graph.h +206 -0
  8. colmap/include/colmap/base/cost_functions.h +301 -0
  9. colmap/include/colmap/base/database.h +394 -0
  10. colmap/include/colmap/base/database_cache.h +151 -0
  11. colmap/include/colmap/base/essential_matrix.h +160 -0
  12. colmap/include/colmap/base/gps.h +89 -0
  13. colmap/include/colmap/base/graph_cut.h +209 -0
  14. colmap/include/colmap/base/homography_matrix.h +111 -0
  15. colmap/include/colmap/base/image.h +364 -0
  16. colmap/include/colmap/base/image_reader.h +133 -0
  17. colmap/include/colmap/base/line.h +66 -0
  18. colmap/include/colmap/base/point2d.h +98 -0
  19. colmap/include/colmap/base/point3d.h +140 -0
  20. colmap/include/colmap/base/polynomial.h +101 -0
  21. colmap/include/colmap/base/pose.h +230 -0
  22. colmap/include/colmap/base/projection.h +167 -0
  23. colmap/include/colmap/base/reconstruction.h +651 -0
  24. colmap/include/colmap/base/reconstruction_manager.h +81 -0
  25. colmap/include/colmap/base/scene_clustering.h +100 -0
  26. colmap/include/colmap/base/similarity_transform.h +121 -0
  27. colmap/include/colmap/base/track.h +139 -0
  28. colmap/include/colmap/base/triangulation.h +118 -0
  29. colmap/include/colmap/base/undistortion.h +234 -0
  30. colmap/include/colmap/base/visibility_pyramid.h +104 -0
  31. colmap/include/colmap/base/warp.h +80 -0
  32. colmap/include/colmap/controllers/automatic_reconstruction.h +123 -0
  33. colmap/include/colmap/controllers/bundle_adjustment.h +56 -0
  34. colmap/include/colmap/controllers/hierarchical_mapper.h +82 -0
  35. colmap/include/colmap/controllers/incremental_mapper.h +199 -0
  36. colmap/include/colmap/estimators/absolute_pose.h +182 -0
  37. colmap/include/colmap/estimators/affine_transform.h +65 -0
  38. colmap/include/colmap/estimators/coordinate_frame.h +88 -0
  39. colmap/include/colmap/estimators/essential_matrix.h +127 -0
  40. colmap/include/colmap/estimators/essential_matrix_coeffs.h +206 -0
  41. colmap/include/colmap/estimators/essential_matrix_poly.h +0 -0
  42. colmap/include/colmap/estimators/euclidean_transform.h +56 -0
  43. colmap/include/colmap/estimators/fundamental_matrix.h +129 -0
  44. colmap/include/colmap/estimators/generalized_absolute_pose.h +100 -0
  45. colmap/include/colmap/estimators/generalized_absolute_pose_coeffs.h +44 -0
  46. colmap/include/colmap/estimators/generalized_relative_pose.h +94 -0
  47. colmap/include/colmap/estimators/homography_matrix.h +83 -0
  48. colmap/include/colmap/estimators/pose.h +234 -0
  49. colmap/include/colmap/estimators/similarity_transform.h +138 -0
  50. colmap/include/colmap/estimators/translation_transform.h +120 -0
.gitattributes CHANGED
@@ -43,3 +43,9 @@ src/exe/CMakeFiles/colmap_exe.dir/vocab_tree.cc.o filter=lfs diff=lfs merge=lfs
43
  src/exe/colmap filter=lfs diff=lfs merge=lfs -text
44
  src/libcolmap.a filter=lfs diff=lfs merge=lfs -text
45
  src/libcolmap_cuda.a filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
43
  src/exe/colmap filter=lfs diff=lfs merge=lfs -text
44
  src/libcolmap.a filter=lfs diff=lfs merge=lfs -text
45
  src/libcolmap_cuda.a filter=lfs diff=lfs merge=lfs -text
46
+ colmap/bin/colmap filter=lfs diff=lfs merge=lfs -text
47
+ colmap/lib/libcolmap.a filter=lfs diff=lfs merge=lfs -text
48
+ colmap/lib/libcolmap_cuda.a filter=lfs diff=lfs merge=lfs -text
49
+ colmap/lib/libpba.a filter=lfs diff=lfs merge=lfs -text
50
+ colmap/lib/libpoisson_recon.a filter=lfs diff=lfs merge=lfs -text
51
+ colmap/lib/libsift_gpu.a filter=lfs diff=lfs merge=lfs -text
colmap/bin/colmap ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9efc313d53067e8a32ff66555e20318dc8382bd06ccc9ea769440f20da5d74be
3
+ size 31933416
colmap/include/colmap/base/camera.h ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_CAMERA_H_
33
+ #define COLMAP_SRC_BASE_CAMERA_H_
34
+
35
+ #include <vector>
36
+
37
+ #include "util/types.h"
38
+
39
+ namespace colmap {
40
+
41
+ // Camera class that holds the intrinsic parameters. Cameras may be shared
42
+ // between multiple images, e.g., if the same "physical" camera took multiple
43
+ // pictures with the exact same lens and intrinsics (focal length, etc.).
44
+ // This class has a specific distortion model defined by a camera model class.
45
+ class Camera {
46
+ public:
47
+ Camera();
48
+
49
+ // Access the unique identifier of the camera.
50
+ inline camera_t CameraId() const;
51
+ inline void SetCameraId(const camera_t camera_id);
52
+
53
+ // Access the camera model.
54
+ inline int ModelId() const;
55
+ std::string ModelName() const;
56
+ void SetModelId(const int model_id);
57
+ void SetModelIdFromName(const std::string& model_name);
58
+
59
+ // Access dimensions of the camera sensor.
60
+ inline size_t Width() const;
61
+ inline size_t Height() const;
62
+ inline void SetWidth(const size_t width);
63
+ inline void SetHeight(const size_t height);
64
+
65
+ // Access focal length parameters.
66
+ double MeanFocalLength() const;
67
+ double FocalLength() const;
68
+ double FocalLengthX() const;
69
+ double FocalLengthY() const;
70
+ void SetFocalLength(const double focal_length);
71
+ void SetFocalLengthX(const double focal_length_x);
72
+ void SetFocalLengthY(const double focal_length_y);
73
+
74
+ // Check if camera has prior focal length.
75
+ inline bool HasPriorFocalLength() const;
76
+ inline void SetPriorFocalLength(const bool prior);
77
+
78
+ // Access principal point parameters. Only works if there are two
79
+ // principal point parameters.
80
+ double PrincipalPointX() const;
81
+ double PrincipalPointY() const;
82
+ void SetPrincipalPointX(const double ppx);
83
+ void SetPrincipalPointY(const double ppy);
84
+
85
+ // Get the indices of the parameter groups in the parameter vector.
86
+ const std::vector<size_t>& FocalLengthIdxs() const;
87
+ const std::vector<size_t>& PrincipalPointIdxs() const;
88
+ const std::vector<size_t>& ExtraParamsIdxs() const;
89
+
90
+ // Get intrinsic calibration matrix composed from focal length and principal
91
+ // point parameters, excluding distortion parameters.
92
+ Eigen::Matrix3d CalibrationMatrix() const;
93
+
94
+ // Get human-readable information about the parameter vector ordering.
95
+ std::string ParamsInfo() const;
96
+
97
+ // Access the raw parameter vector.
98
+ inline size_t NumParams() const;
99
+ inline const std::vector<double>& Params() const;
100
+ inline std::vector<double>& Params();
101
+ inline double Params(const size_t idx) const;
102
+ inline double& Params(const size_t idx);
103
+ inline const double* ParamsData() const;
104
+ inline double* ParamsData();
105
+ inline void SetParams(const std::vector<double>& params);
106
+
107
+ // Concatenate parameters as comma-separated list.
108
+ std::string ParamsToString() const;
109
+
110
+ // Set camera parameters from comma-separated list.
111
+ bool SetParamsFromString(const std::string& string);
112
+
113
+ // Check whether parameters are valid, i.e. the parameter vector has
114
+ // the correct dimensions that match the specified camera model.
115
+ bool VerifyParams() const;
116
+
117
+ // Check whether camera is already undistorted
118
+ bool IsUndistorted() const;
119
+
120
+ // Check whether camera has bogus parameters.
121
+ bool HasBogusParams(const double min_focal_length_ratio,
122
+ const double max_focal_length_ratio,
123
+ const double max_extra_param) const;
124
+
125
+ // Initialize parameters for given camera model and focal length, and set
126
+ // the principal point to be the image center.
127
+ void InitializeWithId(const int model_id, const double focal_length,
128
+ const size_t width, const size_t height);
129
+ void InitializeWithName(const std::string& model_name,
130
+ const double focal_length, const size_t width,
131
+ const size_t height);
132
+
133
+ // Project point in image plane to world / infinity.
134
+ Eigen::Vector2d ImageToWorld(const Eigen::Vector2d& image_point) const;
135
+
136
+ // Convert pixel threshold in image plane to world space.
137
+ double ImageToWorldThreshold(const double threshold) const;
138
+
139
+ // Project point from world / infinity to image plane.
140
+ Eigen::Vector2d WorldToImage(const Eigen::Vector2d& world_point) const;
141
+
142
+ // Rescale camera dimensions and accordingly the focal length and
143
+ // and the principal point.
144
+ void Rescale(const double scale);
145
+ void Rescale(const size_t width, const size_t height);
146
+
147
+ private:
148
+ // The unique identifier of the camera. If the identifier is not specified
149
+ // it is set to `kInvalidCameraId`.
150
+ camera_t camera_id_;
151
+
152
+ // The identifier of the camera model. If the camera model is not specified
153
+ // the identifier is `kInvalidCameraModelId`.
154
+ int model_id_;
155
+
156
+ // The dimensions of the image, 0 if not initialized.
157
+ size_t width_;
158
+ size_t height_;
159
+
160
+ // The focal length, principal point, and extra parameters. If the camera
161
+ // model is not specified, this vector is empty.
162
+ std::vector<double> params_;
163
+
164
+ // Whether there is a safe prior for the focal length,
165
+ // e.g. manually provided or extracted from EXIF
166
+ bool prior_focal_length_;
167
+ };
168
+
169
+ ////////////////////////////////////////////////////////////////////////////////
170
+ // Implementation
171
+ ////////////////////////////////////////////////////////////////////////////////
172
+
173
+ camera_t Camera::CameraId() const { return camera_id_; }
174
+
175
+ void Camera::SetCameraId(const camera_t camera_id) { camera_id_ = camera_id; }
176
+
177
+ int Camera::ModelId() const { return model_id_; }
178
+
179
+ size_t Camera::Width() const { return width_; }
180
+
181
+ size_t Camera::Height() const { return height_; }
182
+
183
+ void Camera::SetWidth(const size_t width) { width_ = width; }
184
+
185
+ void Camera::SetHeight(const size_t height) { height_ = height; }
186
+
187
+ bool Camera::HasPriorFocalLength() const { return prior_focal_length_; }
188
+
189
+ void Camera::SetPriorFocalLength(const bool prior) {
190
+ prior_focal_length_ = prior;
191
+ }
192
+
193
+ size_t Camera::NumParams() const { return params_.size(); }
194
+
195
+ const std::vector<double>& Camera::Params() const { return params_; }
196
+
197
+ std::vector<double>& Camera::Params() { return params_; }
198
+
199
+ double Camera::Params(const size_t idx) const { return params_[idx]; }
200
+
201
+ double& Camera::Params(const size_t idx) { return params_[idx]; }
202
+
203
+ const double* Camera::ParamsData() const { return params_.data(); }
204
+
205
+ double* Camera::ParamsData() { return params_.data(); }
206
+
207
+ void Camera::SetParams(const std::vector<double>& params) { params_ = params; }
208
+
209
+ } // namespace colmap
210
+
211
+ #endif // COLMAP_SRC_BASE_CAMERA_H_
colmap/include/colmap/base/camera_database.h ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_CAMERA_DATABASE_H_
33
+ #define COLMAP_SRC_BASE_CAMERA_DATABASE_H_
34
+
35
+ #include <string>
36
+
37
+ #include "util/camera_specs.h"
38
+
39
+ namespace colmap {
40
+
41
+ // Database that contains sensor widths for many cameras, which is useful
42
+ // to automatically extract the focal length if EXIF information is incomplete.
43
+ class CameraDatabase {
44
+ public:
45
+ CameraDatabase();
46
+
47
+ size_t NumEntries() const { return specs_.size(); }
48
+
49
+ bool QuerySensorWidth(const std::string& make, const std::string& model,
50
+ double* sensor_width);
51
+
52
+ private:
53
+ static const camera_specs_t specs_;
54
+ };
55
+
56
+ } // namespace colmap
57
+
58
+ #endif // COLMAP_SRC_BASE_CAMERA_DATABASE_H_
colmap/include/colmap/base/camera_models.h ADDED
@@ -0,0 +1,1533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_CAMERA_MODELS_H_
33
+ #define COLMAP_SRC_BASE_CAMERA_MODELS_H_
34
+
35
+ #include <cfloat>
36
+ #include <string>
37
+ #include <vector>
38
+
39
+ #include <Eigen/Core>
40
+ #include <Eigen/Dense>
41
+
42
+ #include <ceres/ceres.h>
43
+
44
+ namespace colmap {
45
+
46
+ // This file defines several different camera models and arbitrary new camera
47
+ // models can be added by the following steps:
48
+ //
49
+ // 1. Add a new struct in this file which implements all the necessary methods.
50
+ // 2. Define an unique model_name and model_id for the camera model.
51
+ // 3. Add camera model to `CAMERA_MODEL_CASES` macro in this file.
52
+ // 4. Add new template specialization of test case for camera model to
53
+ // `camera_models_test.cc`.
54
+ //
55
+ // A camera model can have three different types of camera parameters: focal
56
+ // length, principal point, extra parameters (distortion parameters). The
57
+ // parameter array is split into different groups, so that we can enable or
58
+ // disable the refinement of the individual groups during bundle adjustment. It
59
+ // is up to the camera model to access the parameters correctly (it is free to
60
+ // do so in an arbitrary manner) - the parameters are not accessed from outside.
61
+ //
62
+ // A camera model must have the following methods:
63
+ //
64
+ // - `WorldToImage`: transform normalized camera coordinates to image
65
+ // coordinates (the inverse of `ImageToWorld`). Assumes that the world
66
+ // coordinates are given as (u, v, 1).
67
+ // - `ImageToWorld`: transform image coordinates to normalized camera
68
+ // coordinates (the inverse of `WorldToImage`). Produces world coordinates
69
+ // as (u, v, 1).
70
+ // - `ImageToWorldThreshold`: transform a threshold given in pixels to
71
+ // normalized units (e.g. useful for reprojection error thresholds).
72
+ //
73
+ // Whenever you specify the camera parameters in a list, they must appear
74
+ // exactly in the order as they are accessed in the defined model struct.
75
+ //
76
+ // The camera models follow the convention that the upper left image corner has
77
+ // the coordinate (0, 0), the lower right corner (width, height), i.e. that
78
+ // the upper left pixel center has coordinate (0.5, 0.5) and the lower right
79
+ // pixel center has the coordinate (width - 0.5, height - 0.5).
80
+
81
+ static const int kInvalidCameraModelId = -1;
82
+
83
+ #ifndef CAMERA_MODEL_DEFINITIONS
84
+ #define CAMERA_MODEL_DEFINITIONS(model_id_value, model_name_value, \
85
+ num_params_value) \
86
+ static const int kModelId = model_id_value; \
87
+ static const size_t kNumParams = num_params_value; \
88
+ static const int model_id; \
89
+ static const std::string model_name; \
90
+ static const size_t num_params; \
91
+ static const std::string params_info; \
92
+ static const std::vector<size_t> focal_length_idxs; \
93
+ static const std::vector<size_t> principal_point_idxs; \
94
+ static const std::vector<size_t> extra_params_idxs; \
95
+ \
96
+ static inline int InitializeModelId() { return model_id_value; }; \
97
+ static inline std::string InitializeModelName() { \
98
+ return model_name_value; \
99
+ }; \
100
+ static inline size_t InitializeNumParams() { return num_params_value; }; \
101
+ static inline std::string InitializeParamsInfo(); \
102
+ static inline std::vector<size_t> InitializeFocalLengthIdxs(); \
103
+ static inline std::vector<size_t> InitializePrincipalPointIdxs(); \
104
+ static inline std::vector<size_t> InitializeExtraParamsIdxs(); \
105
+ static inline std::vector<double> InitializeParams( \
106
+ const double focal_length, const size_t width, const size_t height); \
107
+ \
108
+ template <typename T> \
109
+ static void WorldToImage(const T* params, const T u, const T v, T* x, T* y); \
110
+ template <typename T> \
111
+ static void ImageToWorld(const T* params, const T x, const T y, T* u, T* v); \
112
+ template <typename T> \
113
+ static void Distortion(const T* extra_params, const T u, const T v, T* du, \
114
+ T* dv);
115
+ #endif
116
+
117
+ #ifndef CAMERA_MODEL_CASES
118
+ #define CAMERA_MODEL_CASES \
119
+ CAMERA_MODEL_CASE(SimplePinholeCameraModel) \
120
+ CAMERA_MODEL_CASE(PinholeCameraModel) \
121
+ CAMERA_MODEL_CASE(SimpleRadialCameraModel) \
122
+ CAMERA_MODEL_CASE(SimpleRadialFisheyeCameraModel) \
123
+ CAMERA_MODEL_CASE(RadialCameraModel) \
124
+ CAMERA_MODEL_CASE(RadialFisheyeCameraModel) \
125
+ CAMERA_MODEL_CASE(OpenCVCameraModel) \
126
+ CAMERA_MODEL_CASE(OpenCVFisheyeCameraModel) \
127
+ CAMERA_MODEL_CASE(FullOpenCVCameraModel) \
128
+ CAMERA_MODEL_CASE(FOVCameraModel) \
129
+ CAMERA_MODEL_CASE(ThinPrismFisheyeCameraModel)
130
+ #endif
131
+
132
+ #ifndef CAMERA_MODEL_SWITCH_CASES
133
+ #define CAMERA_MODEL_SWITCH_CASES \
134
+ CAMERA_MODEL_CASES \
135
+ default: \
136
+ CAMERA_MODEL_DOES_NOT_EXIST_EXCEPTION \
137
+ break;
138
+ #endif
139
+
140
+ #define CAMERA_MODEL_DOES_NOT_EXIST_EXCEPTION \
141
+ throw std::domain_error("Camera model does not exist");
142
+
143
+ // The "Curiously Recurring Template Pattern" (CRTP) is used here, so that we
144
+ // can reuse some shared functionality between all camera models -
145
+ // defined in the BaseCameraModel.
146
+ template <typename CameraModel>
147
+ struct BaseCameraModel {
148
+ template <typename T>
149
+ static inline bool HasBogusParams(const std::vector<T>& params,
150
+ const size_t width, const size_t height,
151
+ const T min_focal_length_ratio,
152
+ const T max_focal_length_ratio,
153
+ const T max_extra_param);
154
+
155
+ template <typename T>
156
+ static inline bool HasBogusFocalLength(const std::vector<T>& params,
157
+ const size_t width,
158
+ const size_t height,
159
+ const T min_focal_length_ratio,
160
+ const T max_focal_length_ratio);
161
+
162
+ template <typename T>
163
+ static inline bool HasBogusPrincipalPoint(const std::vector<T>& params,
164
+ const size_t width,
165
+ const size_t height);
166
+
167
+ template <typename T>
168
+ static inline bool HasBogusExtraParams(const std::vector<T>& params,
169
+ const T max_extra_param);
170
+
171
+ template <typename T>
172
+ static inline T ImageToWorldThreshold(const T* params, const T threshold);
173
+
174
+ template <typename T>
175
+ static inline void IterativeUndistortion(const T* params, T* u, T* v);
176
+ };
177
+
178
+ // Simple Pinhole camera model.
179
+ //
180
+ // No Distortion is assumed. Only focal length and principal point is modeled.
181
+ //
182
+ // Parameter list is expected in the following order:
183
+ //
184
+ // f, cx, cy
185
+ //
186
+ // See https://en.wikipedia.org/wiki/Pinhole_camera_model
187
+ struct SimplePinholeCameraModel
188
+ : public BaseCameraModel<SimplePinholeCameraModel> {
189
+ CAMERA_MODEL_DEFINITIONS(0, "SIMPLE_PINHOLE", 3)
190
+ };
191
+
192
+ // Pinhole camera model.
193
+ //
194
+ // No Distortion is assumed. Only focal length and principal point is modeled.
195
+ //
196
+ // Parameter list is expected in the following order:
197
+ //
198
+ // fx, fy, cx, cy
199
+ //
200
+ // See https://en.wikipedia.org/wiki/Pinhole_camera_model
201
+ struct PinholeCameraModel : public BaseCameraModel<PinholeCameraModel> {
202
+ CAMERA_MODEL_DEFINITIONS(1, "PINHOLE", 4)
203
+ };
204
+
205
+ // Simple camera model with one focal length and one radial distortion
206
+ // parameter.
207
+ //
208
+ // This model is similar to the camera model that VisualSfM uses with the
209
+ // difference that the distortion here is applied to the projections and
210
+ // not to the measurements.
211
+ //
212
+ // Parameter list is expected in the following order:
213
+ //
214
+ // f, cx, cy, k
215
+ //
216
+ struct SimpleRadialCameraModel
217
+ : public BaseCameraModel<SimpleRadialCameraModel> {
218
+ CAMERA_MODEL_DEFINITIONS(2, "SIMPLE_RADIAL", 4)
219
+ };
220
+
221
+ // Simple camera model with one focal length and two radial distortion
222
+ // parameters.
223
+ //
224
+ // This model is equivalent to the camera model that Bundler uses
225
+ // (except for an inverse z-axis in the camera coordinate system).
226
+ //
227
+ // Parameter list is expected in the following order:
228
+ //
229
+ // f, cx, cy, k1, k2
230
+ //
231
+ struct RadialCameraModel : public BaseCameraModel<RadialCameraModel> {
232
+ CAMERA_MODEL_DEFINITIONS(3, "RADIAL", 5)
233
+ };
234
+
235
+ // OpenCV camera model.
236
+ //
237
+ // Based on the pinhole camera model. Additionally models radial and
238
+ // tangential distortion (up to 2nd degree of coefficients). Not suitable for
239
+ // large radial distortions of fish-eye cameras.
240
+ //
241
+ // Parameter list is expected in the following order:
242
+ //
243
+ // fx, fy, cx, cy, k1, k2, p1, p2
244
+ //
245
+ // See
246
+ // http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
247
+ struct OpenCVCameraModel : public BaseCameraModel<OpenCVCameraModel> {
248
+ CAMERA_MODEL_DEFINITIONS(4, "OPENCV", 8)
249
+ };
250
+
251
+ // OpenCV fish-eye camera model.
252
+ //
253
+ // Based on the pinhole camera model. Additionally models radial and
254
+ // tangential Distortion (up to 2nd degree of coefficients). Suitable for
255
+ // large radial distortions of fish-eye cameras.
256
+ //
257
+ // Parameter list is expected in the following order:
258
+ //
259
+ // fx, fy, cx, cy, k1, k2, k3, k4
260
+ //
261
+ // See
262
+ // http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
263
+ struct OpenCVFisheyeCameraModel
264
+ : public BaseCameraModel<OpenCVFisheyeCameraModel> {
265
+ CAMERA_MODEL_DEFINITIONS(5, "OPENCV_FISHEYE", 8)
266
+ };
267
+
268
+ // Full OpenCV camera model.
269
+ //
270
+ // Based on the pinhole camera model. Additionally models radial and
271
+ // tangential Distortion.
272
+ //
273
+ // Parameter list is expected in the following order:
274
+ //
275
+ // fx, fy, cx, cy, k1, k2, p1, p2, k3, k4, k5, k6
276
+ //
277
+ // See
278
+ // http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
279
+ struct FullOpenCVCameraModel : public BaseCameraModel<FullOpenCVCameraModel> {
280
+ CAMERA_MODEL_DEFINITIONS(6, "FULL_OPENCV", 12)
281
+ };
282
+
283
+ // FOV camera model.
284
+ //
285
+ // Based on the pinhole camera model. Additionally models radial distortion.
286
+ // This model is for example used by Project Tango for its equidistant
287
+ // calibration type.
288
+ //
289
+ // Parameter list is expected in the following order:
290
+ //
291
+ // fx, fy, cx, cy, omega
292
+ //
293
+ // See:
294
+ // Frederic Devernay, Olivier Faugeras. Straight lines have to be straight:
295
+ // Automatic calibration and removal of distortion from scenes of structured
296
+ // environments. Machine vision and applications, 2001.
297
+ struct FOVCameraModel : public BaseCameraModel<FOVCameraModel> {
298
+ CAMERA_MODEL_DEFINITIONS(7, "FOV", 5)
299
+
300
+ template <typename T>
301
+ static void Undistortion(const T* extra_params, const T u, const T v, T* du,
302
+ T* dv);
303
+ };
304
+
305
+ // Simple camera model with one focal length and one radial distortion
306
+ // parameter, suitable for fish-eye cameras.
307
+ //
308
+ // This model is equivalent to the OpenCVFisheyeCameraModel but has only one
309
+ // radial distortion coefficient.
310
+ //
311
+ // Parameter list is expected in the following order:
312
+ //
313
+ // f, cx, cy, k
314
+ //
315
+ struct SimpleRadialFisheyeCameraModel
316
+ : public BaseCameraModel<SimpleRadialFisheyeCameraModel> {
317
+ CAMERA_MODEL_DEFINITIONS(8, "SIMPLE_RADIAL_FISHEYE", 4)
318
+ };
319
+
320
+ // Simple camera model with one focal length and two radial distortion
321
+ // parameters, suitable for fish-eye cameras.
322
+ //
323
+ // This model is equivalent to the OpenCVFisheyeCameraModel but has only two
324
+ // radial distortion coefficients.
325
+ //
326
+ // Parameter list is expected in the following order:
327
+ //
328
+ // f, cx, cy, k1, k2
329
+ //
330
+ struct RadialFisheyeCameraModel
331
+ : public BaseCameraModel<RadialFisheyeCameraModel> {
332
+ CAMERA_MODEL_DEFINITIONS(9, "RADIAL_FISHEYE", 5)
333
+ };
334
+
335
+ // Camera model with radial and tangential distortion coefficients and
336
+ // additional coefficients accounting for thin-prism distortion.
337
+ //
338
+ // This camera model is described in
339
+ //
340
+ // "Camera Calibration with Distortion Models and Accuracy Evaluation",
341
+ // J Weng et al., TPAMI, 1992.
342
+ //
343
+ // Parameter list is expected in the following order:
344
+ //
345
+ // fx, fy, cx, cy, k1, k2, p1, p2, k3, k4, sx1, sy1
346
+ //
347
+ struct ThinPrismFisheyeCameraModel
348
+ : public BaseCameraModel<ThinPrismFisheyeCameraModel> {
349
+ CAMERA_MODEL_DEFINITIONS(10, "THIN_PRISM_FISHEYE", 12)
350
+ };
351
+
352
+ // Check whether camera model with given name or identifier exists.
353
+ bool ExistsCameraModelWithName(const std::string& model_name);
354
+ bool ExistsCameraModelWithId(const int model_id);
355
+
356
+ // Convert camera name to unique camera model identifier.
357
+ //
358
+ // @param name Unique name of camera model.
359
+ //
360
+ // @return Unique identifier of camera model.
361
+ int CameraModelNameToId(const std::string& model_name);
362
+
363
+ // Convert camera model identifier to unique camera model name.
364
+ //
365
+ // @param model_id Unique identifier of camera model.
366
+ //
367
+ // @return Unique name of camera model.
368
+ std::string CameraModelIdToName(const int model_id);
369
+
370
+ // Initialize camera parameters using given image properties.
371
+ //
372
+ // Initializes all focal length parameters to the same given focal length and
373
+ // sets the principal point to the image center.
374
+ //
375
+ // @param model_id Unique identifier of camera model.
376
+ // @param focal_length Focal length, equal for all focal length parameters.
377
+ // @param width Sensor width of the camera.
378
+ // @param height Sensor height of the camera.
379
+ std::vector<double> CameraModelInitializeParams(const int model_id,
380
+ const double focal_length,
381
+ const size_t width,
382
+ const size_t height);
383
+
384
+ // Get human-readable information about the parameter vector order.
385
+ //
386
+ // @param model_id Unique identifier of camera model.
387
+ std::string CameraModelParamsInfo(const int model_id);
388
+
389
+ // Get the indices of the parameter groups in the parameter vector.
390
+ //
391
+ // @param model_id Unique identifier of camera model.
392
+ const std::vector<size_t>& CameraModelFocalLengthIdxs(const int model_id);
393
+ const std::vector<size_t>& CameraModelPrincipalPointIdxs(const int model_id);
394
+ const std::vector<size_t>& CameraModelExtraParamsIdxs(const int model_id);
395
+
396
+ // Get the total number of parameters of a camera model.
397
+ size_t CameraModelNumParams(const int model_id);
398
+
399
+ // Check whether parameters are valid, i.e. the parameter vector has
400
+ // the correct dimensions that match the specified camera model.
401
+ //
402
+ // @param model_id Unique identifier of camera model.
403
+ // @param params Array of camera parameters.
404
+ bool CameraModelVerifyParams(const int model_id,
405
+ const std::vector<double>& params);
406
+
407
+ // Check whether camera has bogus parameters.
408
+ //
409
+ // @param model_id Unique identifier of camera model.
410
+ // @param params Array of camera parameters.
411
+ // @param width Sensor width of the camera.
412
+ // @param height Sensor height of the camera.
413
+ // @param min_focal_length_ratio Minimum ratio of focal length over
414
+ // maximum sensor dimension.
415
+ // @param min_focal_length_ratio Maximum ratio of focal length over
416
+ // maximum sensor dimension.
417
+ // @param max_extra_param Maximum magnitude of each extra parameter.
418
+ bool CameraModelHasBogusParams(const int model_id,
419
+ const std::vector<double>& params,
420
+ const size_t width, const size_t height,
421
+ const double min_focal_length_ratio,
422
+ const double max_focal_length_ratio,
423
+ const double max_extra_param);
424
+
425
+ // Transform world coordinates in camera coordinate system to image coordinates.
426
+ //
427
+ // This is the inverse of `CameraModelImageToWorld`.
428
+ //
429
+ // @param model_id Unique model_id of camera model as defined in
430
+ // `CAMERA_MODEL_NAME_TO_CODE`.
431
+ // @param params Array of camera parameters.
432
+ // @param u, v Coordinates in camera system as (u, v, 1).
433
+ // @param x, y Output image coordinates in pixels.
434
+ inline void CameraModelWorldToImage(const int model_id,
435
+ const std::vector<double>& params,
436
+ const double u, const double v, double* x,
437
+ double* y);
438
+
439
+ // Transform image coordinates to world coordinates in camera coordinate system.
440
+ //
441
+ // This is the inverse of `CameraModelWorldToImage`.
442
+ //
443
+ // @param model_id Unique identifier of camera model.
444
+ // @param params Array of camera parameters.
445
+ // @param x, y Image coordinates in pixels.
446
+ // @param v, u Output Coordinates in camera system as (u, v, 1).
447
+ inline void CameraModelImageToWorld(const int model_id,
448
+ const std::vector<double>& params,
449
+ const double x, const double y, double* u,
450
+ double* v);
451
+
452
+ // Convert pixel threshold in image plane to world space by dividing
453
+ // the threshold through the mean focal length.
454
+ //
455
+ // @param model_id Unique identifier of camera model.
456
+ // @param params Array of camera parameters.
457
+ // @param threshold Image space threshold in pixels.
458
+ //
459
+ // @ return World space threshold.
460
+ inline double CameraModelImageToWorldThreshold(
461
+ const int model_id, const std::vector<double>& params,
462
+ const double threshold);
463
+
464
+ ////////////////////////////////////////////////////////////////////////////////
465
+ // Implementation
466
+ ////////////////////////////////////////////////////////////////////////////////
467
+
468
+ ////////////////////////////////////////////////////////////////////////////////
469
+ // BaseCameraModel
470
+
471
+ template <typename CameraModel>
472
+ template <typename T>
473
+ bool BaseCameraModel<CameraModel>::HasBogusParams(
474
+ const std::vector<T>& params, const size_t width, const size_t height,
475
+ const T min_focal_length_ratio, const T max_focal_length_ratio,
476
+ const T max_extra_param) {
477
+ if (HasBogusPrincipalPoint(params, width, height)) {
478
+ return true;
479
+ }
480
+
481
+ if (HasBogusFocalLength(params, width, height, min_focal_length_ratio,
482
+ max_focal_length_ratio)) {
483
+ return true;
484
+ }
485
+
486
+ if (HasBogusExtraParams(params, max_extra_param)) {
487
+ return true;
488
+ }
489
+
490
+ return false;
491
+ }
492
+
493
+ template <typename CameraModel>
494
+ template <typename T>
495
+ bool BaseCameraModel<CameraModel>::HasBogusFocalLength(
496
+ const std::vector<T>& params, const size_t width, const size_t height,
497
+ const T min_focal_length_ratio, const T max_focal_length_ratio) {
498
+ const size_t max_size = std::max(width, height);
499
+
500
+ for (const auto& idx : CameraModel::focal_length_idxs) {
501
+ const T focal_length_ratio = params[idx] / max_size;
502
+ if (focal_length_ratio < min_focal_length_ratio ||
503
+ focal_length_ratio > max_focal_length_ratio) {
504
+ return true;
505
+ }
506
+ }
507
+
508
+ return false;
509
+ }
510
+
511
+ template <typename CameraModel>
512
+ template <typename T>
513
+ bool BaseCameraModel<CameraModel>::HasBogusPrincipalPoint(
514
+ const std::vector<T>& params, const size_t width, const size_t height) {
515
+ const T cx = params[CameraModel::principal_point_idxs[0]];
516
+ const T cy = params[CameraModel::principal_point_idxs[1]];
517
+ return cx < 0 || cx > width || cy < 0 || cy > height;
518
+ }
519
+
520
+ template <typename CameraModel>
521
+ template <typename T>
522
+ bool BaseCameraModel<CameraModel>::HasBogusExtraParams(
523
+ const std::vector<T>& params, const T max_extra_param) {
524
+ for (const auto& idx : CameraModel::extra_params_idxs) {
525
+ if (std::abs(params[idx]) > max_extra_param) {
526
+ return true;
527
+ }
528
+ }
529
+
530
+ return false;
531
+ }
532
+
533
+ template <typename CameraModel>
534
+ template <typename T>
535
+ T BaseCameraModel<CameraModel>::ImageToWorldThreshold(const T* params,
536
+ const T threshold) {
537
+ T mean_focal_length = 0;
538
+ for (const auto& idx : CameraModel::focal_length_idxs) {
539
+ mean_focal_length += params[idx];
540
+ }
541
+ mean_focal_length /= CameraModel::focal_length_idxs.size();
542
+ return threshold / mean_focal_length;
543
+ }
544
+
545
+ template <typename CameraModel>
546
+ template <typename T>
547
+ void BaseCameraModel<CameraModel>::IterativeUndistortion(const T* params, T* u,
548
+ T* v) {
549
+ // Parameters for Newton iteration using numerical differentiation with
550
+ // central differences, 100 iterations should be enough even for complex
551
+ // camera models with higher order terms.
552
+ const size_t kNumIterations = 100;
553
+ const double kMaxStepNorm = 1e-10;
554
+ const double kRelStepSize = 1e-6;
555
+
556
+ Eigen::Matrix2d J;
557
+ const Eigen::Vector2d x0(*u, *v);
558
+ Eigen::Vector2d x(*u, *v);
559
+ Eigen::Vector2d dx;
560
+ Eigen::Vector2d dx_0b;
561
+ Eigen::Vector2d dx_0f;
562
+ Eigen::Vector2d dx_1b;
563
+ Eigen::Vector2d dx_1f;
564
+
565
+ for (size_t i = 0; i < kNumIterations; ++i) {
566
+ const double step0 = std::max(std::numeric_limits<double>::epsilon(),
567
+ std::abs(kRelStepSize * x(0)));
568
+ const double step1 = std::max(std::numeric_limits<double>::epsilon(),
569
+ std::abs(kRelStepSize * x(1)));
570
+ CameraModel::Distortion(params, x(0), x(1), &dx(0), &dx(1));
571
+ CameraModel::Distortion(params, x(0) - step0, x(1), &dx_0b(0), &dx_0b(1));
572
+ CameraModel::Distortion(params, x(0) + step0, x(1), &dx_0f(0), &dx_0f(1));
573
+ CameraModel::Distortion(params, x(0), x(1) - step1, &dx_1b(0), &dx_1b(1));
574
+ CameraModel::Distortion(params, x(0), x(1) + step1, &dx_1f(0), &dx_1f(1));
575
+ J(0, 0) = 1 + (dx_0f(0) - dx_0b(0)) / (2 * step0);
576
+ J(0, 1) = (dx_1f(0) - dx_1b(0)) / (2 * step1);
577
+ J(1, 0) = (dx_0f(1) - dx_0b(1)) / (2 * step0);
578
+ J(1, 1) = 1 + (dx_1f(1) - dx_1b(1)) / (2 * step1);
579
+ const Eigen::Vector2d step_x = J.inverse() * (x + dx - x0);
580
+ x -= step_x;
581
+ if (step_x.squaredNorm() < kMaxStepNorm) {
582
+ break;
583
+ }
584
+ }
585
+
586
+ *u = x(0);
587
+ *v = x(1);
588
+ }
589
+
590
+ ////////////////////////////////////////////////////////////////////////////////
591
+ // SimplePinholeCameraModel
592
+
593
+ std::string SimplePinholeCameraModel::InitializeParamsInfo() {
594
+ return "f, cx, cy";
595
+ }
596
+
597
+ std::vector<size_t> SimplePinholeCameraModel::InitializeFocalLengthIdxs() {
598
+ return {0};
599
+ }
600
+
601
+ std::vector<size_t> SimplePinholeCameraModel::InitializePrincipalPointIdxs() {
602
+ return {1, 2};
603
+ }
604
+
605
+ std::vector<size_t> SimplePinholeCameraModel::InitializeExtraParamsIdxs() {
606
+ return {};
607
+ }
608
+
609
+ std::vector<double> SimplePinholeCameraModel::InitializeParams(
610
+ const double focal_length, const size_t width, const size_t height) {
611
+ return {focal_length, width / 2.0, height / 2.0};
612
+ }
613
+
614
+ template <typename T>
615
+ void SimplePinholeCameraModel::WorldToImage(const T* params, const T u,
616
+ const T v, T* x, T* y) {
617
+ const T f = params[0];
618
+ const T c1 = params[1];
619
+ const T c2 = params[2];
620
+
621
+ // No Distortion
622
+
623
+ // Transform to image coordinates
624
+ *x = f * u + c1;
625
+ *y = f * v + c2;
626
+ }
627
+
628
+ template <typename T>
629
+ void SimplePinholeCameraModel::ImageToWorld(const T* params, const T x,
630
+ const T y, T* u, T* v) {
631
+ const T f = params[0];
632
+ const T c1 = params[1];
633
+ const T c2 = params[2];
634
+
635
+ *u = (x - c1) / f;
636
+ *v = (y - c2) / f;
637
+ }
638
+
639
+ ////////////////////////////////////////////////////////////////////////////////
640
+ // PinholeCameraModel
641
+
642
+ std::string PinholeCameraModel::InitializeParamsInfo() {
643
+ return "fx, fy, cx, cy";
644
+ }
645
+
646
+ std::vector<size_t> PinholeCameraModel::InitializeFocalLengthIdxs() {
647
+ return {0, 1};
648
+ }
649
+
650
+ std::vector<size_t> PinholeCameraModel::InitializePrincipalPointIdxs() {
651
+ return {2, 3};
652
+ }
653
+
654
+ std::vector<size_t> PinholeCameraModel::InitializeExtraParamsIdxs() {
655
+ return {};
656
+ }
657
+
658
+ std::vector<double> PinholeCameraModel::InitializeParams(
659
+ const double focal_length, const size_t width, const size_t height) {
660
+ return {focal_length, focal_length, width / 2.0, height / 2.0};
661
+ }
662
+
663
+ template <typename T>
664
+ void PinholeCameraModel::WorldToImage(const T* params, const T u, const T v,
665
+ T* x, T* y) {
666
+ const T f1 = params[0];
667
+ const T f2 = params[1];
668
+ const T c1 = params[2];
669
+ const T c2 = params[3];
670
+
671
+ // No Distortion
672
+
673
+ // Transform to image coordinates
674
+ *x = f1 * u + c1;
675
+ *y = f2 * v + c2;
676
+ }
677
+
678
+ template <typename T>
679
+ void PinholeCameraModel::ImageToWorld(const T* params, const T x, const T y,
680
+ T* u, T* v) {
681
+ const T f1 = params[0];
682
+ const T f2 = params[1];
683
+ const T c1 = params[2];
684
+ const T c2 = params[3];
685
+
686
+ *u = (x - c1) / f1;
687
+ *v = (y - c2) / f2;
688
+ }
689
+
690
+ ////////////////////////////////////////////////////////////////////////////////
691
+ // SimpleRadialCameraModel
692
+
693
+ std::string SimpleRadialCameraModel::InitializeParamsInfo() {
694
+ return "f, cx, cy, k";
695
+ }
696
+
697
+ std::vector<size_t> SimpleRadialCameraModel::InitializeFocalLengthIdxs() {
698
+ return {0};
699
+ }
700
+
701
+ std::vector<size_t> SimpleRadialCameraModel::InitializePrincipalPointIdxs() {
702
+ return {1, 2};
703
+ }
704
+
705
+ std::vector<size_t> SimpleRadialCameraModel::InitializeExtraParamsIdxs() {
706
+ return {3};
707
+ }
708
+
709
+ std::vector<double> SimpleRadialCameraModel::InitializeParams(
710
+ const double focal_length, const size_t width, const size_t height) {
711
+ return {focal_length, width / 2.0, height / 2.0, 0};
712
+ }
713
+
714
+ template <typename T>
715
+ void SimpleRadialCameraModel::WorldToImage(const T* params, const T u,
716
+ const T v, T* x, T* y) {
717
+ const T f = params[0];
718
+ const T c1 = params[1];
719
+ const T c2 = params[2];
720
+
721
+ // Distortion
722
+ T du, dv;
723
+ Distortion(&params[3], u, v, &du, &dv);
724
+ *x = u + du;
725
+ *y = v + dv;
726
+
727
+ // Transform to image coordinates
728
+ *x = f * *x + c1;
729
+ *y = f * *y + c2;
730
+ }
731
+
732
+ template <typename T>
733
+ void SimpleRadialCameraModel::ImageToWorld(const T* params, const T x,
734
+ const T y, T* u, T* v) {
735
+ const T f = params[0];
736
+ const T c1 = params[1];
737
+ const T c2 = params[2];
738
+
739
+ // Lift points to normalized plane
740
+ *u = (x - c1) / f;
741
+ *v = (y - c2) / f;
742
+
743
+ IterativeUndistortion(&params[3], u, v);
744
+ }
745
+
746
+ template <typename T>
747
+ void SimpleRadialCameraModel::Distortion(const T* extra_params, const T u,
748
+ const T v, T* du, T* dv) {
749
+ const T k = extra_params[0];
750
+
751
+ const T u2 = u * u;
752
+ const T v2 = v * v;
753
+ const T r2 = u2 + v2;
754
+ const T radial = k * r2;
755
+ *du = u * radial;
756
+ *dv = v * radial;
757
+ }
758
+
759
+ ////////////////////////////////////////////////////////////////////////////////
760
+ // RadialCameraModel
761
+
762
+ std::string RadialCameraModel::InitializeParamsInfo() {
763
+ return "f, cx, cy, k1, k2";
764
+ }
765
+
766
+ std::vector<size_t> RadialCameraModel::InitializeFocalLengthIdxs() {
767
+ return {0};
768
+ }
769
+
770
+ std::vector<size_t> RadialCameraModel::InitializePrincipalPointIdxs() {
771
+ return {1, 2};
772
+ }
773
+
774
+ std::vector<size_t> RadialCameraModel::InitializeExtraParamsIdxs() {
775
+ return {3, 4};
776
+ }
777
+
778
+ std::vector<double> RadialCameraModel::InitializeParams(
779
+ const double focal_length, const size_t width, const size_t height) {
780
+ return {focal_length, width / 2.0, height / 2.0, 0, 0};
781
+ }
782
+
783
+ template <typename T>
784
+ void RadialCameraModel::WorldToImage(const T* params, const T u, const T v,
785
+ T* x, T* y) {
786
+ const T f = params[0];
787
+ const T c1 = params[1];
788
+ const T c2 = params[2];
789
+
790
+ // Distortion
791
+ T du, dv;
792
+ Distortion(&params[3], u, v, &du, &dv);
793
+ *x = u + du;
794
+ *y = v + dv;
795
+
796
+ // Transform to image coordinates
797
+ *x = f * *x + c1;
798
+ *y = f * *y + c2;
799
+ }
800
+
801
+ template <typename T>
802
+ void RadialCameraModel::ImageToWorld(const T* params, const T x, const T y,
803
+ T* u, T* v) {
804
+ const T f = params[0];
805
+ const T c1 = params[1];
806
+ const T c2 = params[2];
807
+
808
+ // Lift points to normalized plane
809
+ *u = (x - c1) / f;
810
+ *v = (y - c2) / f;
811
+
812
+ IterativeUndistortion(&params[3], u, v);
813
+ }
814
+
815
+ template <typename T>
816
+ void RadialCameraModel::Distortion(const T* extra_params, const T u, const T v,
817
+ T* du, T* dv) {
818
+ const T k1 = extra_params[0];
819
+ const T k2 = extra_params[1];
820
+
821
+ const T u2 = u * u;
822
+ const T v2 = v * v;
823
+ const T r2 = u2 + v2;
824
+ const T radial = k1 * r2 + k2 * r2 * r2;
825
+ *du = u * radial;
826
+ *dv = v * radial;
827
+ }
828
+
829
+ ////////////////////////////////////////////////////////////////////////////////
830
+ // OpenCVCameraModel
831
+
832
+ std::string OpenCVCameraModel::InitializeParamsInfo() {
833
+ return "fx, fy, cx, cy, k1, k2, p1, p2";
834
+ }
835
+
836
+ std::vector<size_t> OpenCVCameraModel::InitializeFocalLengthIdxs() {
837
+ return {0, 1};
838
+ }
839
+
840
+ std::vector<size_t> OpenCVCameraModel::InitializePrincipalPointIdxs() {
841
+ return {2, 3};
842
+ }
843
+
844
+ std::vector<size_t> OpenCVCameraModel::InitializeExtraParamsIdxs() {
845
+ return {4, 5, 6, 7};
846
+ }
847
+
848
+ std::vector<double> OpenCVCameraModel::InitializeParams(
849
+ const double focal_length, const size_t width, const size_t height) {
850
+ return {focal_length, focal_length, width / 2.0, height / 2.0, 0, 0, 0, 0};
851
+ }
852
+
853
+ template <typename T>
854
+ void OpenCVCameraModel::WorldToImage(const T* params, const T u, const T v,
855
+ T* x, T* y) {
856
+ const T f1 = params[0];
857
+ const T f2 = params[1];
858
+ const T c1 = params[2];
859
+ const T c2 = params[3];
860
+
861
+ // Distortion
862
+ T du, dv;
863
+ Distortion(&params[4], u, v, &du, &dv);
864
+ *x = u + du;
865
+ *y = v + dv;
866
+
867
+ // Transform to image coordinates
868
+ *x = f1 * *x + c1;
869
+ *y = f2 * *y + c2;
870
+ }
871
+
872
+ template <typename T>
873
+ void OpenCVCameraModel::ImageToWorld(const T* params, const T x, const T y,
874
+ T* u, T* v) {
875
+ const T f1 = params[0];
876
+ const T f2 = params[1];
877
+ const T c1 = params[2];
878
+ const T c2 = params[3];
879
+
880
+ // Lift points to normalized plane
881
+ *u = (x - c1) / f1;
882
+ *v = (y - c2) / f2;
883
+
884
+ IterativeUndistortion(&params[4], u, v);
885
+ }
886
+
887
+ template <typename T>
888
+ void OpenCVCameraModel::Distortion(const T* extra_params, const T u, const T v,
889
+ T* du, T* dv) {
890
+ const T k1 = extra_params[0];
891
+ const T k2 = extra_params[1];
892
+ const T p1 = extra_params[2];
893
+ const T p2 = extra_params[3];
894
+
895
+ const T u2 = u * u;
896
+ const T uv = u * v;
897
+ const T v2 = v * v;
898
+ const T r2 = u2 + v2;
899
+ const T radial = k1 * r2 + k2 * r2 * r2;
900
+ *du = u * radial + T(2) * p1 * uv + p2 * (r2 + T(2) * u2);
901
+ *dv = v * radial + T(2) * p2 * uv + p1 * (r2 + T(2) * v2);
902
+ }
903
+
904
+ ////////////////////////////////////////////////////////////////////////////////
905
+ // OpenCVFisheyeCameraModel
906
+
907
+ std::string OpenCVFisheyeCameraModel::InitializeParamsInfo() {
908
+ return "fx, fy, cx, cy, k1, k2, k3, k4";
909
+ }
910
+
911
+ std::vector<size_t> OpenCVFisheyeCameraModel::InitializeFocalLengthIdxs() {
912
+ return {0, 1};
913
+ }
914
+
915
+ std::vector<size_t> OpenCVFisheyeCameraModel::InitializePrincipalPointIdxs() {
916
+ return {2, 3};
917
+ }
918
+
919
+ std::vector<size_t> OpenCVFisheyeCameraModel::InitializeExtraParamsIdxs() {
920
+ return {4, 5, 6, 7};
921
+ }
922
+
923
+ std::vector<double> OpenCVFisheyeCameraModel::InitializeParams(
924
+ const double focal_length, const size_t width, const size_t height) {
925
+ return {focal_length, focal_length, width / 2.0, height / 2.0, 0, 0, 0, 0};
926
+ }
927
+
928
+ template <typename T>
929
+ void OpenCVFisheyeCameraModel::WorldToImage(const T* params, const T u,
930
+ const T v, T* x, T* y) {
931
+ const T f1 = params[0];
932
+ const T f2 = params[1];
933
+ const T c1 = params[2];
934
+ const T c2 = params[3];
935
+
936
+ // Distortion
937
+ T du, dv;
938
+ Distortion(&params[4], u, v, &du, &dv);
939
+ *x = u + du;
940
+ *y = v + dv;
941
+
942
+ // Transform to image coordinates
943
+ *x = f1 * *x + c1;
944
+ *y = f2 * *y + c2;
945
+ }
946
+
947
+ template <typename T>
948
+ void OpenCVFisheyeCameraModel::ImageToWorld(const T* params, const T x,
949
+ const T y, T* u, T* v) {
950
+ const T f1 = params[0];
951
+ const T f2 = params[1];
952
+ const T c1 = params[2];
953
+ const T c2 = params[3];
954
+
955
+ // Lift points to normalized plane
956
+ *u = (x - c1) / f1;
957
+ *v = (y - c2) / f2;
958
+
959
+ IterativeUndistortion(&params[4], u, v);
960
+ }
961
+
962
+ template <typename T>
963
+ void OpenCVFisheyeCameraModel::Distortion(const T* extra_params, const T u,
964
+ const T v, T* du, T* dv) {
965
+ const T k1 = extra_params[0];
966
+ const T k2 = extra_params[1];
967
+ const T k3 = extra_params[2];
968
+ const T k4 = extra_params[3];
969
+
970
+ const T r = ceres::sqrt(u * u + v * v);
971
+
972
+ if (r > T(std::numeric_limits<double>::epsilon())) {
973
+ const T theta = ceres::atan(r);
974
+ const T theta2 = theta * theta;
975
+ const T theta4 = theta2 * theta2;
976
+ const T theta6 = theta4 * theta2;
977
+ const T theta8 = theta4 * theta4;
978
+ const T thetad =
979
+ theta * (T(1) + k1 * theta2 + k2 * theta4 + k3 * theta6 + k4 * theta8);
980
+ *du = u * thetad / r - u;
981
+ *dv = v * thetad / r - v;
982
+ } else {
983
+ *du = T(0);
984
+ *dv = T(0);
985
+ }
986
+ }
987
+
988
+ ////////////////////////////////////////////////////////////////////////////////
989
+ // FullOpenCVCameraModel
990
+
991
+ std::string FullOpenCVCameraModel::InitializeParamsInfo() {
992
+ return "fx, fy, cx, cy, k1, k2, p1, p2, k3, k4, k5, k6";
993
+ }
994
+
995
+ std::vector<size_t> FullOpenCVCameraModel::InitializeFocalLengthIdxs() {
996
+ return {0, 1};
997
+ }
998
+
999
+ std::vector<size_t> FullOpenCVCameraModel::InitializePrincipalPointIdxs() {
1000
+ return {2, 3};
1001
+ }
1002
+
1003
+ std::vector<size_t> FullOpenCVCameraModel::InitializeExtraParamsIdxs() {
1004
+ return {4, 5, 6, 7, 8, 9, 10, 11};
1005
+ }
1006
+
1007
+ std::vector<double> FullOpenCVCameraModel::InitializeParams(
1008
+ const double focal_length, const size_t width, const size_t height) {
1009
+ return {focal_length,
1010
+ focal_length,
1011
+ width / 2.0,
1012
+ height / 2.0,
1013
+ 0,
1014
+ 0,
1015
+ 0,
1016
+ 0,
1017
+ 0,
1018
+ 0,
1019
+ 0,
1020
+ 0};
1021
+ }
1022
+
1023
+ template <typename T>
1024
+ void FullOpenCVCameraModel::WorldToImage(const T* params, const T u, const T v,
1025
+ T* x, T* y) {
1026
+ const T f1 = params[0];
1027
+ const T f2 = params[1];
1028
+ const T c1 = params[2];
1029
+ const T c2 = params[3];
1030
+
1031
+ // Distortion
1032
+ T du, dv;
1033
+ Distortion(&params[4], u, v, &du, &dv);
1034
+ *x = u + du;
1035
+ *y = v + dv;
1036
+
1037
+ // Transform to image coordinates
1038
+ *x = f1 * *x + c1;
1039
+ *y = f2 * *y + c2;
1040
+ }
1041
+
1042
+ template <typename T>
1043
+ void FullOpenCVCameraModel::ImageToWorld(const T* params, const T x, const T y,
1044
+ T* u, T* v) {
1045
+ const T f1 = params[0];
1046
+ const T f2 = params[1];
1047
+ const T c1 = params[2];
1048
+ const T c2 = params[3];
1049
+
1050
+ // Lift points to normalized plane
1051
+ *u = (x - c1) / f1;
1052
+ *v = (y - c2) / f2;
1053
+
1054
+ IterativeUndistortion(&params[4], u, v);
1055
+ }
1056
+
1057
+ template <typename T>
1058
+ void FullOpenCVCameraModel::Distortion(const T* extra_params, const T u,
1059
+ const T v, T* du, T* dv) {
1060
+ const T k1 = extra_params[0];
1061
+ const T k2 = extra_params[1];
1062
+ const T p1 = extra_params[2];
1063
+ const T p2 = extra_params[3];
1064
+ const T k3 = extra_params[4];
1065
+ const T k4 = extra_params[5];
1066
+ const T k5 = extra_params[6];
1067
+ const T k6 = extra_params[7];
1068
+
1069
+ const T u2 = u * u;
1070
+ const T uv = u * v;
1071
+ const T v2 = v * v;
1072
+ const T r2 = u2 + v2;
1073
+ const T r4 = r2 * r2;
1074
+ const T r6 = r4 * r2;
1075
+ const T radial = (T(1) + k1 * r2 + k2 * r4 + k3 * r6) /
1076
+ (T(1) + k4 * r2 + k5 * r4 + k6 * r6);
1077
+ *du = u * radial + T(2) * p1 * uv + p2 * (r2 + T(2) * u2) - u;
1078
+ *dv = v * radial + T(2) * p2 * uv + p1 * (r2 + T(2) * v2) - v;
1079
+ }
1080
+
1081
+ ////////////////////////////////////////////////////////////////////////////////
1082
+ // FOVCameraModel
1083
+
1084
+ std::string FOVCameraModel::InitializeParamsInfo() {
1085
+ return "fx, fy, cx, cy, omega";
1086
+ }
1087
+
1088
+ std::vector<size_t> FOVCameraModel::InitializeFocalLengthIdxs() {
1089
+ return {0, 1};
1090
+ }
1091
+
1092
+ std::vector<size_t> FOVCameraModel::InitializePrincipalPointIdxs() {
1093
+ return {2, 3};
1094
+ }
1095
+
1096
+ std::vector<size_t> FOVCameraModel::InitializeExtraParamsIdxs() { return {4}; }
1097
+
1098
+ std::vector<double> FOVCameraModel::InitializeParams(const double focal_length,
1099
+ const size_t width,
1100
+ const size_t height) {
1101
+ return {focal_length, focal_length, width / 2.0, height / 2.0, 1e-2};
1102
+ }
1103
+
1104
+ template <typename T>
1105
+ void FOVCameraModel::WorldToImage(const T* params, const T u, const T v, T* x,
1106
+ T* y) {
1107
+ const T f1 = params[0];
1108
+ const T f2 = params[1];
1109
+ const T c1 = params[2];
1110
+ const T c2 = params[3];
1111
+
1112
+ // Distortion
1113
+ Distortion(&params[4], u, v, x, y);
1114
+
1115
+ // Transform to image coordinates
1116
+ *x = f1 * *x + c1;
1117
+ *y = f2 * *y + c2;
1118
+ }
1119
+
1120
+ template <typename T>
1121
+ void FOVCameraModel::ImageToWorld(const T* params, const T x, const T y, T* u,
1122
+ T* v) {
1123
+ const T f1 = params[0];
1124
+ const T f2 = params[1];
1125
+ const T c1 = params[2];
1126
+ const T c2 = params[3];
1127
+
1128
+ // Lift points to normalized plane
1129
+ const T uu = (x - c1) / f1;
1130
+ const T vv = (y - c2) / f2;
1131
+
1132
+ // Undistortion
1133
+ Undistortion(&params[4], uu, vv, u, v);
1134
+ }
1135
+
1136
+ template <typename T>
1137
+ void FOVCameraModel::Distortion(const T* extra_params, const T u, const T v,
1138
+ T* du, T* dv) {
1139
+ const T omega = extra_params[0];
1140
+
1141
+ // Chosen arbitrarily.
1142
+ const T kEpsilon = T(1e-4);
1143
+
1144
+ const T radius2 = u * u + v * v;
1145
+ const T omega2 = omega * omega;
1146
+
1147
+ T factor;
1148
+ if (omega2 < kEpsilon) {
1149
+ // Derivation of this case with Matlab:
1150
+ // syms radius omega;
1151
+ // factor(radius) = atan(radius * 2 * tan(omega / 2)) / ...
1152
+ // (radius * omega);
1153
+ // simplify(taylor(factor, omega, 'order', 3))
1154
+ factor = (omega2 * radius2) / T(3) - omega2 / T(12) + T(1);
1155
+ } else if (radius2 < kEpsilon) {
1156
+ // Derivation of this case with Matlab:
1157
+ // syms radius omega;
1158
+ // factor(radius) = atan(radius * 2 * tan(omega / 2)) / ...
1159
+ // (radius * omega);
1160
+ // simplify(taylor(factor, radius, 'order', 3))
1161
+ const T tan_half_omega = ceres::tan(omega / T(2));
1162
+ factor = (T(-2) * tan_half_omega *
1163
+ (T(4) * radius2 * tan_half_omega * tan_half_omega - T(3))) /
1164
+ (T(3) * omega);
1165
+ } else {
1166
+ const T radius = ceres::sqrt(radius2);
1167
+ const T numerator = ceres::atan(radius * T(2) * ceres::tan(omega / T(2)));
1168
+ factor = numerator / (radius * omega);
1169
+ }
1170
+
1171
+ *du = u * factor;
1172
+ *dv = v * factor;
1173
+ }
1174
+
1175
+ template <typename T>
1176
+ void FOVCameraModel::Undistortion(const T* extra_params, const T u, const T v,
1177
+ T* du, T* dv) {
1178
+ T omega = extra_params[0];
1179
+
1180
+ // Chosen arbitrarily.
1181
+ const T kEpsilon = T(1e-4);
1182
+
1183
+ const T radius2 = u * u + v * v;
1184
+ const T omega2 = omega * omega;
1185
+
1186
+ T factor;
1187
+ if (omega2 < kEpsilon) {
1188
+ // Derivation of this case with Matlab:
1189
+ // syms radius omega;
1190
+ // factor(radius) = tan(radius * omega) / ...
1191
+ // (radius * 2*tan(omega/2));
1192
+ // simplify(taylor(factor, omega, 'order', 3))
1193
+ factor = (omega2 * radius2) / T(3) - omega2 / T(12) + T(1);
1194
+ } else if (radius2 < kEpsilon) {
1195
+ // Derivation of this case with Matlab:
1196
+ // syms radius omega;
1197
+ // factor(radius) = tan(radius * omega) / ...
1198
+ // (radius * 2*tan(omega/2));
1199
+ // simplify(taylor(factor, radius, 'order', 3))
1200
+ factor = (omega * (omega * omega * radius2 + T(3))) /
1201
+ (T(6) * ceres::tan(omega / T(2)));
1202
+ } else {
1203
+ const T radius = ceres::sqrt(radius2);
1204
+ const T numerator = ceres::tan(radius * omega);
1205
+ factor = numerator / (radius * T(2) * ceres::tan(omega / T(2)));
1206
+ }
1207
+
1208
+ *du = u * factor;
1209
+ *dv = v * factor;
1210
+ }
1211
+
1212
+ ////////////////////////////////////////////////////////////////////////////////
1213
+ // SimpleRadialFisheyeCameraModel
1214
+
1215
+ std::string SimpleRadialFisheyeCameraModel::InitializeParamsInfo() {
1216
+ return "f, cx, cy, k";
1217
+ }
1218
+
1219
+ std::vector<size_t>
1220
+ SimpleRadialFisheyeCameraModel::InitializeFocalLengthIdxs() {
1221
+ return {0};
1222
+ }
1223
+
1224
+ std::vector<size_t>
1225
+ SimpleRadialFisheyeCameraModel::InitializePrincipalPointIdxs() {
1226
+ return {1, 2};
1227
+ }
1228
+
1229
+ std::vector<size_t>
1230
+ SimpleRadialFisheyeCameraModel::InitializeExtraParamsIdxs() {
1231
+ return {3};
1232
+ }
1233
+
1234
+ std::vector<double> SimpleRadialFisheyeCameraModel::InitializeParams(
1235
+ const double focal_length, const size_t width, const size_t height) {
1236
+ return {focal_length, width / 2.0, height / 2.0, 0};
1237
+ }
1238
+
1239
+ template <typename T>
1240
+ void SimpleRadialFisheyeCameraModel::WorldToImage(const T* params, const T u,
1241
+ const T v, T* x, T* y) {
1242
+ const T f = params[0];
1243
+ const T c1 = params[1];
1244
+ const T c2 = params[2];
1245
+
1246
+ // Distortion
1247
+ T du, dv;
1248
+ Distortion(&params[3], u, v, &du, &dv);
1249
+ *x = u + du;
1250
+ *y = v + dv;
1251
+
1252
+ // Transform to image coordinates
1253
+ *x = f * *x + c1;
1254
+ *y = f * *y + c2;
1255
+ }
1256
+
1257
+ template <typename T>
1258
+ void SimpleRadialFisheyeCameraModel::ImageToWorld(const T* params, const T x,
1259
+ const T y, T* u, T* v) {
1260
+ const T f = params[0];
1261
+ const T c1 = params[1];
1262
+ const T c2 = params[2];
1263
+
1264
+ // Lift points to normalized plane
1265
+ *u = (x - c1) / f;
1266
+ *v = (y - c2) / f;
1267
+
1268
+ IterativeUndistortion(&params[3], u, v);
1269
+ }
1270
+
1271
+ template <typename T>
1272
+ void SimpleRadialFisheyeCameraModel::Distortion(const T* extra_params,
1273
+ const T u, const T v, T* du,
1274
+ T* dv) {
1275
+ const T k = extra_params[0];
1276
+
1277
+ const T r = ceres::sqrt(u * u + v * v);
1278
+
1279
+ if (r > T(std::numeric_limits<double>::epsilon())) {
1280
+ const T theta = ceres::atan(r);
1281
+ const T theta2 = theta * theta;
1282
+ const T thetad = theta * (T(1) + k * theta2);
1283
+ *du = u * thetad / r - u;
1284
+ *dv = v * thetad / r - v;
1285
+ } else {
1286
+ *du = T(0);
1287
+ *dv = T(0);
1288
+ }
1289
+ }
1290
+
1291
+ ////////////////////////////////////////////////////////////////////////////////
1292
+ // RadialFisheyeCameraModel
1293
+
1294
+ std::string RadialFisheyeCameraModel::InitializeParamsInfo() {
1295
+ return "f, cx, cy, k1, k2";
1296
+ }
1297
+
1298
+ std::vector<size_t> RadialFisheyeCameraModel::InitializeFocalLengthIdxs() {
1299
+ return {0};
1300
+ }
1301
+
1302
+ std::vector<size_t> RadialFisheyeCameraModel::InitializePrincipalPointIdxs() {
1303
+ return {1, 2};
1304
+ }
1305
+
1306
+ std::vector<size_t> RadialFisheyeCameraModel::InitializeExtraParamsIdxs() {
1307
+ return {3, 4};
1308
+ }
1309
+
1310
+ std::vector<double> RadialFisheyeCameraModel::InitializeParams(
1311
+ const double focal_length, const size_t width, const size_t height) {
1312
+ return {focal_length, width / 2.0, height / 2.0, 0, 0};
1313
+ }
1314
+
1315
+ template <typename T>
1316
+ void RadialFisheyeCameraModel::WorldToImage(const T* params, const T u,
1317
+ const T v, T* x, T* y) {
1318
+ const T f = params[0];
1319
+ const T c1 = params[1];
1320
+ const T c2 = params[2];
1321
+
1322
+ // Distortion
1323
+ T du, dv;
1324
+ Distortion(&params[3], u, v, &du, &dv);
1325
+ *x = u + du;
1326
+ *y = v + dv;
1327
+
1328
+ // Transform to image coordinates
1329
+ *x = f * *x + c1;
1330
+ *y = f * *y + c2;
1331
+ }
1332
+
1333
+ template <typename T>
1334
+ void RadialFisheyeCameraModel::ImageToWorld(const T* params, const T x,
1335
+ const T y, T* u, T* v) {
1336
+ const T f = params[0];
1337
+ const T c1 = params[1];
1338
+ const T c2 = params[2];
1339
+
1340
+ // Lift points to normalized plane
1341
+ *u = (x - c1) / f;
1342
+ *v = (y - c2) / f;
1343
+
1344
+ IterativeUndistortion(&params[3], u, v);
1345
+ }
1346
+
1347
+ template <typename T>
1348
+ void RadialFisheyeCameraModel::Distortion(const T* extra_params, const T u,
1349
+ const T v, T* du, T* dv) {
1350
+ const T k1 = extra_params[0];
1351
+ const T k2 = extra_params[1];
1352
+
1353
+ const T r = ceres::sqrt(u * u + v * v);
1354
+
1355
+ if (r > T(std::numeric_limits<double>::epsilon())) {
1356
+ const T theta = ceres::atan(r);
1357
+ const T theta2 = theta * theta;
1358
+ const T theta4 = theta2 * theta2;
1359
+ const T thetad = theta * (T(1) + k1 * theta2 + k2 * theta4);
1360
+ *du = u * thetad / r - u;
1361
+ *dv = v * thetad / r - v;
1362
+ } else {
1363
+ *du = T(0);
1364
+ *dv = T(0);
1365
+ }
1366
+ }
1367
+
1368
+ ////////////////////////////////////////////////////////////////////////////////
1369
+ // ThinPrismFisheyeCameraModel
1370
+
1371
+ std::string ThinPrismFisheyeCameraModel::InitializeParamsInfo() {
1372
+ return "fx, fy, cx, cy, k1, k2, p1, p2, k3, k4, sx1, sy1";
1373
+ }
1374
+
1375
+ std::vector<size_t> ThinPrismFisheyeCameraModel::InitializeFocalLengthIdxs() {
1376
+ return {0, 1};
1377
+ }
1378
+
1379
+ std::vector<size_t>
1380
+ ThinPrismFisheyeCameraModel::InitializePrincipalPointIdxs() {
1381
+ return {2, 3};
1382
+ }
1383
+
1384
+ std::vector<size_t> ThinPrismFisheyeCameraModel::InitializeExtraParamsIdxs() {
1385
+ return {4, 5, 6, 7, 8, 9, 10, 11};
1386
+ }
1387
+
1388
+ std::vector<double> ThinPrismFisheyeCameraModel::InitializeParams(
1389
+ const double focal_length, const size_t width, const size_t height) {
1390
+ return {focal_length,
1391
+ focal_length,
1392
+ width / 2.0,
1393
+ height / 2.0,
1394
+ 0,
1395
+ 0,
1396
+ 0,
1397
+ 0,
1398
+ 0,
1399
+ 0,
1400
+ 0,
1401
+ 0};
1402
+ }
1403
+
1404
+ template <typename T>
1405
+ void ThinPrismFisheyeCameraModel::WorldToImage(const T* params, const T u,
1406
+ const T v, T* x, T* y) {
1407
+ const T f1 = params[0];
1408
+ const T f2 = params[1];
1409
+ const T c1 = params[2];
1410
+ const T c2 = params[3];
1411
+
1412
+ const T r = ceres::sqrt(u * u + v * v);
1413
+
1414
+ T uu, vv;
1415
+ if (r > T(std::numeric_limits<double>::epsilon())) {
1416
+ const T theta = ceres::atan(r);
1417
+ uu = theta * u / r;
1418
+ vv = theta * v / r;
1419
+ } else {
1420
+ uu = u;
1421
+ vv = v;
1422
+ }
1423
+
1424
+ // Distortion
1425
+ T du, dv;
1426
+ Distortion(&params[4], uu, vv, &du, &dv);
1427
+ *x = uu + du;
1428
+ *y = vv + dv;
1429
+
1430
+ // Transform to image coordinates
1431
+ *x = f1 * *x + c1;
1432
+ *y = f2 * *y + c2;
1433
+ }
1434
+
1435
+ template <typename T>
1436
+ void ThinPrismFisheyeCameraModel::ImageToWorld(const T* params, const T x,
1437
+ const T y, T* u, T* v) {
1438
+ const T f1 = params[0];
1439
+ const T f2 = params[1];
1440
+ const T c1 = params[2];
1441
+ const T c2 = params[3];
1442
+
1443
+ // Lift points to normalized plane
1444
+ *u = (x - c1) / f1;
1445
+ *v = (y - c2) / f2;
1446
+
1447
+ IterativeUndistortion(&params[4], u, v);
1448
+
1449
+ const T theta = ceres::sqrt(*u * *u + *v * *v);
1450
+ const T theta_cos_theta = theta * ceres::cos(theta);
1451
+ if (theta_cos_theta > T(std::numeric_limits<double>::epsilon())) {
1452
+ const T scale = ceres::sin(theta) / theta_cos_theta;
1453
+ *u *= scale;
1454
+ *v *= scale;
1455
+ }
1456
+ }
1457
+
1458
+ template <typename T>
1459
+ void ThinPrismFisheyeCameraModel::Distortion(const T* extra_params, const T u,
1460
+ const T v, T* du, T* dv) {
1461
+ const T k1 = extra_params[0];
1462
+ const T k2 = extra_params[1];
1463
+ const T p1 = extra_params[2];
1464
+ const T p2 = extra_params[3];
1465
+ const T k3 = extra_params[4];
1466
+ const T k4 = extra_params[5];
1467
+ const T sx1 = extra_params[6];
1468
+ const T sy1 = extra_params[7];
1469
+
1470
+ const T u2 = u * u;
1471
+ const T uv = u * v;
1472
+ const T v2 = v * v;
1473
+ const T r2 = u2 + v2;
1474
+ const T r4 = r2 * r2;
1475
+ const T r6 = r4 * r2;
1476
+ const T r8 = r6 * r2;
1477
+ const T radial = k1 * r2 + k2 * r4 + k3 * r6 + k4 * r8;
1478
+ *du = u * radial + T(2) * p1 * uv + p2 * (r2 + T(2) * u2) + sx1 * r2;
1479
+ *dv = v * radial + T(2) * p2 * uv + p1 * (r2 + T(2) * v2) + sy1 * r2;
1480
+ }
1481
+
1482
+ ////////////////////////////////////////////////////////////////////////////////
1483
+
1484
+ void CameraModelWorldToImage(const int model_id,
1485
+ const std::vector<double>& params, const double u,
1486
+ const double v, double* x, double* y) {
1487
+ switch (model_id) {
1488
+ #define CAMERA_MODEL_CASE(CameraModel) \
1489
+ case CameraModel::kModelId: \
1490
+ CameraModel::WorldToImage(params.data(), u, v, x, y); \
1491
+ break;
1492
+
1493
+ CAMERA_MODEL_SWITCH_CASES
1494
+
1495
+ #undef CAMERA_MODEL_CASE
1496
+ }
1497
+ }
1498
+
1499
+ void CameraModelImageToWorld(const int model_id,
1500
+ const std::vector<double>& params, const double x,
1501
+ const double y, double* u, double* v) {
1502
+ switch (model_id) {
1503
+ #define CAMERA_MODEL_CASE(CameraModel) \
1504
+ case CameraModel::kModelId: \
1505
+ CameraModel::ImageToWorld(params.data(), x, y, u, v); \
1506
+ break;
1507
+
1508
+ CAMERA_MODEL_SWITCH_CASES
1509
+
1510
+ #undef CAMERA_MODEL_CASE
1511
+ }
1512
+ }
1513
+
1514
+ double CameraModelImageToWorldThreshold(const int model_id,
1515
+ const std::vector<double>& params,
1516
+ const double threshold) {
1517
+ switch (model_id) {
1518
+ #define CAMERA_MODEL_CASE(CameraModel) \
1519
+ case CameraModel::kModelId: \
1520
+ return CameraModel::ImageToWorldThreshold(params.data(), threshold); \
1521
+ break;
1522
+
1523
+ CAMERA_MODEL_SWITCH_CASES
1524
+
1525
+ #undef CAMERA_MODEL_CASE
1526
+ }
1527
+
1528
+ return -1;
1529
+ }
1530
+
1531
+ } // namespace colmap
1532
+
1533
+ #endif // COLMAP_SRC_BASE_CAMERA_MODELS_H_
colmap/include/colmap/base/camera_rig.h ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_CAMERA_RIG_H_
33
+ #define COLMAP_SRC_BASE_CAMERA_RIG_H_
34
+
35
+ #include <unordered_map>
36
+ #include <vector>
37
+
38
+ #include "base/camera.h"
39
+ #include "base/pose.h"
40
+ #include "base/reconstruction.h"
41
+ #include "util/alignment.h"
42
+ #include "util/types.h"
43
+
44
+ namespace colmap {
45
+
46
+ // This class holds information about the relative configuration of camera rigs.
47
+ // Camera rigs are composed of multiple cameras with a rigid relative extrinsic
48
+ // configuration over multiple snapshots. Snapshots are defined as the
49
+ // collection of images captured simultaneously by all cameras in the rig.
50
+ class CameraRig {
51
+ public:
52
+ CameraRig();
53
+
54
+ // The number of cameras in the rig.
55
+ size_t NumCameras() const;
56
+
57
+ // The number of snapshots captured by this rig.
58
+ size_t NumSnapshots() const;
59
+
60
+ // Check whether the given camera is part of the rig.
61
+ bool HasCamera(const camera_t camera_id) const;
62
+
63
+ // Access the reference camera.
64
+ camera_t RefCameraId() const;
65
+ void SetRefCameraId(const camera_t camera_id);
66
+
67
+ // Get the identifiers of the cameras in the rig.
68
+ std::vector<camera_t> GetCameraIds() const;
69
+
70
+ // Get the snapshots of the camera rig.
71
+ const std::vector<std::vector<image_t>>& Snapshots() const;
72
+
73
+ // Add a new camera to the rig. The relative pose may contain dummy values and
74
+ // can then be computed automatically from a given reconstruction using the
75
+ // method `ComputeRelativePoses`.
76
+ void AddCamera(const camera_t camera_id, const Eigen::Vector4d& rel_qvec,
77
+ const Eigen::Vector3d& rel_tvec);
78
+
79
+ // Add the images of a single snapshot to rig. A snapshot consists of the
80
+ // captured images of all cameras of the rig. All images of a snapshot share
81
+ // the same global camera rig pose, i.e. all images in the camera rig are
82
+ // captured simultaneously.
83
+ void AddSnapshot(const std::vector<image_t>& image_ids);
84
+
85
+ // Check whether the camera rig setup is valid.
86
+ void Check(const Reconstruction& reconstruction) const;
87
+
88
+ // Get the relative poses of the cameras in the rig.
89
+ Eigen::Vector4d& RelativeQvec(const camera_t camera_id);
90
+ const Eigen::Vector4d& RelativeQvec(const camera_t camera_id) const;
91
+ Eigen::Vector3d& RelativeTvec(const camera_t camera_id);
92
+ const Eigen::Vector3d& RelativeTvec(const camera_t camera_id) const;
93
+
94
+ // Compute the scaling factor from the reconstruction to the camera rig
95
+ // dimensions by averaging over the distances between the projection centers.
96
+ // Note that this assumes that there is at least one camera pair in the rig
97
+ // with non-zero baseline, otherwise the function returns NaN.
98
+ double ComputeScale(const Reconstruction& reconstruction) const;
99
+
100
+ // Compute the relative poses in the rig from the reconstruction by averaging
101
+ // the relative poses over all snapshots. The pose of the reference camera
102
+ // will be the identity transformation. This assumes that the camera rig has
103
+ // snapshots that are registered in the reconstruction.
104
+ bool ComputeRelativePoses(const Reconstruction& reconstruction);
105
+
106
+ // Compute the absolute camera pose of the rig. The absolute camera pose of
107
+ // the rig is computed as the average of all relative camera poses in the rig
108
+ // and their corresponding image poses in the reconstruction.
109
+ void ComputeAbsolutePose(const size_t snapshot_idx,
110
+ const Reconstruction& reconstruction,
111
+ Eigen::Vector4d* abs_qvec,
112
+ Eigen::Vector3d* abs_tvec) const;
113
+
114
+ private:
115
+ struct RigCamera {
116
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
117
+ Eigen::Vector4d rel_qvec = ComposeIdentityQuaternion();
118
+ Eigen::Vector3d rel_tvec = Eigen::Vector3d(0, 0, 0);
119
+ };
120
+
121
+ camera_t ref_camera_id_ = kInvalidCameraId;
122
+ EIGEN_STL_UMAP(camera_t, RigCamera) rig_cameras_;
123
+ std::vector<std::vector<image_t>> snapshots_;
124
+ };
125
+
126
+ } // namespace colmap
127
+
128
+ #endif // COLMAP_SRC_BASE_CAMERA_RIG_H_
colmap/include/colmap/base/correspondence_graph.h ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_CORRESPONDENCE_GRAPH_H_
33
+ #define COLMAP_SRC_BASE_CORRESPONDENCE_GRAPH_H_
34
+
35
+ #include <unordered_map>
36
+ #include <vector>
37
+
38
+ #include "base/database.h"
39
+ #include "util/types.h"
40
+
41
+ namespace colmap {
42
+
43
+ // Scene graph represents the graph of image to image and feature to feature
44
+ // correspondences of a dataset. It should be accessed from the DatabaseCache.
45
+ class CorrespondenceGraph {
46
+ public:
47
+ struct Correspondence {
48
+ Correspondence()
49
+ : image_id(kInvalidImageId), point2D_idx(kInvalidPoint2DIdx) {}
50
+ Correspondence(const image_t image_id, const point2D_t point2D_idx)
51
+ : image_id(image_id), point2D_idx(point2D_idx) {}
52
+
53
+ // The identifier of the corresponding image.
54
+ image_t image_id;
55
+
56
+ // The index of the corresponding point in the corresponding image.
57
+ point2D_t point2D_idx;
58
+ };
59
+
60
+ CorrespondenceGraph();
61
+
62
+ // Number of added images.
63
+ inline size_t NumImages() const;
64
+
65
+ // Number of added images.
66
+ inline size_t NumImagePairs() const;
67
+
68
+ // Check whether image exists.
69
+ inline bool ExistsImage(const image_t image_id) const;
70
+
71
+ // Get the number of observations in an image. An observation is an image
72
+ // point that has at least one correspondence.
73
+ inline point2D_t NumObservationsForImage(const image_t image_id) const;
74
+
75
+ // Get the number of correspondences per image.
76
+ inline point2D_t NumCorrespondencesForImage(const image_t image_id) const;
77
+
78
+ // Get the number of correspondences between a pair of images.
79
+ inline point2D_t NumCorrespondencesBetweenImages(
80
+ const image_t image_id1, const image_t image_id2) const;
81
+
82
+ // Get the number of correspondences between all images.
83
+ std::unordered_map<image_pair_t, point2D_t> NumCorrespondencesBetweenImages()
84
+ const;
85
+
86
+ // Finalize the database manager.
87
+ //
88
+ // - Calculates the number of observations per image by counting the number
89
+ // of image points that have at least one correspondence.
90
+ // - Deletes images without observations, as they are useless for SfM.
91
+ // - Shrinks the correspondence vectors to their size to save memory.
92
+ void Finalize();
93
+
94
+ // Add new image to the correspondence graph.
95
+ void AddImage(const image_t image_id, const size_t num_points2D);
96
+
97
+ // Add correspondences between images. This function ignores invalid
98
+ // correspondences where the point indices are out of bounds or duplicate
99
+ // correspondences between the same image points. Whenever either of the two
100
+ // cases occur this function prints a warning to the standard output.
101
+ void AddCorrespondences(const image_t image_id1, const image_t image_id2,
102
+ const FeatureMatches& matches);
103
+
104
+ // Find the correspondence of an image observation to all other images.
105
+ inline const std::vector<Correspondence>& FindCorrespondences(
106
+ const image_t image_id, const point2D_t point2D_idx) const;
107
+
108
+ // Find correspondences to the given observation.
109
+ //
110
+ // Transitively collects correspondences to the given observation by first
111
+ // finding correspondences to the given observation, then looking for
112
+ // correspondences to the collected correspondences in the first step, and so
113
+ // forth until the transitivity is exhausted or no more correspondences are
114
+ // found. The returned list does not contain duplicates and contains
115
+ // the given observation.
116
+ void FindTransitiveCorrespondences(
117
+ const image_t image_id, const point2D_t point2D_idx,
118
+ const size_t transitivity,
119
+ std::vector<Correspondence>* found_corrs) const;
120
+
121
+ // Find all correspondences between two images.
122
+ FeatureMatches FindCorrespondencesBetweenImages(
123
+ const image_t image_id1, const image_t image_id2) const;
124
+
125
+ // Check whether the image point has correspondences.
126
+ inline bool HasCorrespondences(const image_t image_id,
127
+ const point2D_t point2D_idx) const;
128
+
129
+ // Check whether the given observation is part of a two-view track, i.e.
130
+ // it only has one correspondence and that correspondence has the given
131
+ // observation as its only correspondence.
132
+ bool IsTwoViewObservation(const image_t image_id,
133
+ const point2D_t point2D_idx) const;
134
+
135
+ private:
136
+ struct Image {
137
+ // Number of 2D points with at least one correspondence to another image.
138
+ point2D_t num_observations = 0;
139
+
140
+ // Total number of correspondences to other images. This measure is useful
141
+ // to find a good initial pair, that is connected to many images.
142
+ point2D_t num_correspondences = 0;
143
+
144
+ // Correspondences to other images per image point.
145
+ std::vector<std::vector<Correspondence>> corrs;
146
+ };
147
+
148
+ struct ImagePair {
149
+ // The number of correspondences between pairs of images.
150
+ point2D_t num_correspondences = 0;
151
+ };
152
+
153
+ EIGEN_STL_UMAP(image_t, Image) images_;
154
+ std::unordered_map<image_pair_t, ImagePair> image_pairs_;
155
+ };
156
+
157
+ ////////////////////////////////////////////////////////////////////////////////
158
+ // Implementation
159
+ ////////////////////////////////////////////////////////////////////////////////
160
+
161
+ size_t CorrespondenceGraph::NumImages() const { return images_.size(); }
162
+
163
+ size_t CorrespondenceGraph::NumImagePairs() const {
164
+ return image_pairs_.size();
165
+ }
166
+
167
+ bool CorrespondenceGraph::ExistsImage(const image_t image_id) const {
168
+ return images_.find(image_id) != images_.end();
169
+ }
170
+
171
+ point2D_t CorrespondenceGraph::NumObservationsForImage(
172
+ const image_t image_id) const {
173
+ return images_.at(image_id).num_observations;
174
+ }
175
+
176
+ point2D_t CorrespondenceGraph::NumCorrespondencesForImage(
177
+ const image_t image_id) const {
178
+ return images_.at(image_id).num_correspondences;
179
+ }
180
+
181
+ point2D_t CorrespondenceGraph::NumCorrespondencesBetweenImages(
182
+ const image_t image_id1, const image_t image_id2) const {
183
+ const image_pair_t pair_id =
184
+ Database::ImagePairToPairId(image_id1, image_id2);
185
+ const auto it = image_pairs_.find(pair_id);
186
+ if (it == image_pairs_.end()) {
187
+ return 0;
188
+ } else {
189
+ return static_cast<point2D_t>(it->second.num_correspondences);
190
+ }
191
+ }
192
+
193
+ const std::vector<CorrespondenceGraph::Correspondence>&
194
+ CorrespondenceGraph::FindCorrespondences(const image_t image_id,
195
+ const point2D_t point2D_idx) const {
196
+ return images_.at(image_id).corrs.at(point2D_idx);
197
+ }
198
+
199
+ bool CorrespondenceGraph::HasCorrespondences(
200
+ const image_t image_id, const point2D_t point2D_idx) const {
201
+ return !images_.at(image_id).corrs.at(point2D_idx).empty();
202
+ }
203
+
204
+ } // namespace colmap
205
+
206
+ #endif // COLMAP_SRC_BASE_CORRESPONDENCE_GRAPH_H_
colmap/include/colmap/base/cost_functions.h ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_COST_FUNCTIONS_H_
33
+ #define COLMAP_SRC_BASE_COST_FUNCTIONS_H_
34
+
35
+ #include <Eigen/Core>
36
+
37
+ #include <ceres/ceres.h>
38
+ #include <ceres/rotation.h>
39
+
40
+ namespace colmap {
41
+
42
+ // Standard bundle adjustment cost function for variable
43
+ // camera pose and calibration and point parameters.
44
+ template <typename CameraModel>
45
+ class BundleAdjustmentCostFunction {
46
+ public:
47
+ explicit BundleAdjustmentCostFunction(const Eigen::Vector2d& point2D)
48
+ : observed_x_(point2D(0)), observed_y_(point2D(1)) {}
49
+
50
+ static ceres::CostFunction* Create(const Eigen::Vector2d& point2D) {
51
+ return (new ceres::AutoDiffCostFunction<
52
+ BundleAdjustmentCostFunction<CameraModel>, 2, 4, 3, 3,
53
+ CameraModel::kNumParams>(
54
+ new BundleAdjustmentCostFunction(point2D)));
55
+ }
56
+
57
+ template <typename T>
58
+ bool operator()(const T* const qvec, const T* const tvec,
59
+ const T* const point3D, const T* const camera_params,
60
+ T* residuals) const {
61
+ // Rotate and translate.
62
+ T projection[3];
63
+ ceres::UnitQuaternionRotatePoint(qvec, point3D, projection);
64
+ projection[0] += tvec[0];
65
+ projection[1] += tvec[1];
66
+ projection[2] += tvec[2];
67
+
68
+ // Project to image plane.
69
+ projection[0] /= projection[2];
70
+ projection[1] /= projection[2];
71
+
72
+ // Distort and transform to pixel space.
73
+ CameraModel::WorldToImage(camera_params, projection[0], projection[1],
74
+ &residuals[0], &residuals[1]);
75
+
76
+ // Re-projection error.
77
+ residuals[0] -= T(observed_x_);
78
+ residuals[1] -= T(observed_y_);
79
+
80
+ return true;
81
+ }
82
+
83
+ private:
84
+ const double observed_x_;
85
+ const double observed_y_;
86
+ };
87
+
88
+ // Bundle adjustment cost function for variable
89
+ // camera calibration and point parameters, and fixed camera pose.
90
+ template <typename CameraModel>
91
+ class BundleAdjustmentConstantPoseCostFunction {
92
+ public:
93
+ BundleAdjustmentConstantPoseCostFunction(const Eigen::Vector4d& qvec,
94
+ const Eigen::Vector3d& tvec,
95
+ const Eigen::Vector2d& point2D)
96
+ : qw_(qvec(0)),
97
+ qx_(qvec(1)),
98
+ qy_(qvec(2)),
99
+ qz_(qvec(3)),
100
+ tx_(tvec(0)),
101
+ ty_(tvec(1)),
102
+ tz_(tvec(2)),
103
+ observed_x_(point2D(0)),
104
+ observed_y_(point2D(1)) {}
105
+
106
+ static ceres::CostFunction* Create(const Eigen::Vector4d& qvec,
107
+ const Eigen::Vector3d& tvec,
108
+ const Eigen::Vector2d& point2D) {
109
+ return (new ceres::AutoDiffCostFunction<
110
+ BundleAdjustmentConstantPoseCostFunction<CameraModel>, 2, 3,
111
+ CameraModel::kNumParams>(
112
+ new BundleAdjustmentConstantPoseCostFunction(qvec, tvec, point2D)));
113
+ }
114
+
115
+ template <typename T>
116
+ bool operator()(const T* const point3D, const T* const camera_params,
117
+ T* residuals) const {
118
+ const T qvec[4] = {T(qw_), T(qx_), T(qy_), T(qz_)};
119
+
120
+ // Rotate and translate.
121
+ T projection[3];
122
+ ceres::UnitQuaternionRotatePoint(qvec, point3D, projection);
123
+ projection[0] += T(tx_);
124
+ projection[1] += T(ty_);
125
+ projection[2] += T(tz_);
126
+
127
+ // Project to image plane.
128
+ projection[0] /= projection[2];
129
+ projection[1] /= projection[2];
130
+
131
+ // Distort and transform to pixel space.
132
+ CameraModel::WorldToImage(camera_params, projection[0], projection[1],
133
+ &residuals[0], &residuals[1]);
134
+
135
+ // Re-projection error.
136
+ residuals[0] -= T(observed_x_);
137
+ residuals[1] -= T(observed_y_);
138
+
139
+ return true;
140
+ }
141
+
142
+ private:
143
+ const double qw_;
144
+ const double qx_;
145
+ const double qy_;
146
+ const double qz_;
147
+ const double tx_;
148
+ const double ty_;
149
+ const double tz_;
150
+ const double observed_x_;
151
+ const double observed_y_;
152
+ };
153
+
154
+ // Rig bundle adjustment cost function for variable camera pose and calibration
155
+ // and point parameters. Different from the standard bundle adjustment function,
156
+ // this cost function is suitable for camera rigs with consistent relative poses
157
+ // of the cameras within the rig. The cost function first projects points into
158
+ // the local system of the camera rig and then into the local system of the
159
+ // camera within the rig.
160
+ template <typename CameraModel>
161
+ class RigBundleAdjustmentCostFunction {
162
+ public:
163
+ explicit RigBundleAdjustmentCostFunction(const Eigen::Vector2d& point2D)
164
+ : observed_x_(point2D(0)), observed_y_(point2D(1)) {}
165
+
166
+ static ceres::CostFunction* Create(const Eigen::Vector2d& point2D) {
167
+ return (new ceres::AutoDiffCostFunction<
168
+ RigBundleAdjustmentCostFunction<CameraModel>, 2, 4, 3, 4, 3, 3,
169
+ CameraModel::kNumParams>(
170
+ new RigBundleAdjustmentCostFunction(point2D)));
171
+ }
172
+
173
+ template <typename T>
174
+ bool operator()(const T* const rig_qvec, const T* const rig_tvec,
175
+ const T* const rel_qvec, const T* const rel_tvec,
176
+ const T* const point3D, const T* const camera_params,
177
+ T* residuals) const {
178
+ // Concatenate rotations.
179
+ T qvec[4];
180
+ ceres::QuaternionProduct(rel_qvec, rig_qvec, qvec);
181
+
182
+ // Concatenate translations.
183
+ T tvec[3];
184
+ ceres::UnitQuaternionRotatePoint(rel_qvec, rig_tvec, tvec);
185
+ tvec[0] += rel_tvec[0];
186
+ tvec[1] += rel_tvec[1];
187
+ tvec[2] += rel_tvec[2];
188
+
189
+ // Rotate and translate.
190
+ T projection[3];
191
+ ceres::UnitQuaternionRotatePoint(qvec, point3D, projection);
192
+ projection[0] += tvec[0];
193
+ projection[1] += tvec[1];
194
+ projection[2] += tvec[2];
195
+
196
+ // Project to image plane.
197
+ projection[0] /= projection[2];
198
+ projection[1] /= projection[2];
199
+
200
+ // Distort and transform to pixel space.
201
+ CameraModel::WorldToImage(camera_params, projection[0], projection[1],
202
+ &residuals[0], &residuals[1]);
203
+
204
+ // Re-projection error.
205
+ residuals[0] -= T(observed_x_);
206
+ residuals[1] -= T(observed_y_);
207
+
208
+ return true;
209
+ }
210
+
211
+ private:
212
+ const double observed_x_;
213
+ const double observed_y_;
214
+ };
215
+
216
+ // Cost function for refining two-view geometry based on the Sampson-Error.
217
+ //
218
+ // First pose is assumed to be located at the origin with 0 rotation. Second
219
+ // pose is assumed to be on the unit sphere around the first pose, i.e. the
220
+ // pose of the second camera is parameterized by a 3D rotation and a
221
+ // 3D translation with unit norm. `tvec` is therefore over-parameterized as is
222
+ // and should be down-projected using `SphereManifold`.
223
+ class RelativePoseCostFunction {
224
+ public:
225
+ RelativePoseCostFunction(const Eigen::Vector2d& x1, const Eigen::Vector2d& x2)
226
+ : x1_(x1(0)), y1_(x1(1)), x2_(x2(0)), y2_(x2(1)) {}
227
+
228
+ static ceres::CostFunction* Create(const Eigen::Vector2d& x1,
229
+ const Eigen::Vector2d& x2) {
230
+ return (new ceres::AutoDiffCostFunction<RelativePoseCostFunction, 1, 4, 3>(
231
+ new RelativePoseCostFunction(x1, x2)));
232
+ }
233
+
234
+ template <typename T>
235
+ bool operator()(const T* const qvec, const T* const tvec,
236
+ T* residuals) const {
237
+ Eigen::Matrix<T, 3, 3, Eigen::RowMajor> R;
238
+ ceres::QuaternionToRotation(qvec, R.data());
239
+
240
+ // Matrix representation of the cross product t x R.
241
+ Eigen::Matrix<T, 3, 3> t_x;
242
+ t_x << T(0), -tvec[2], tvec[1], tvec[2], T(0), -tvec[0], -tvec[1], tvec[0],
243
+ T(0);
244
+
245
+ // Essential matrix.
246
+ const Eigen::Matrix<T, 3, 3> E = t_x * R;
247
+
248
+ // Homogeneous image coordinates.
249
+ const Eigen::Matrix<T, 3, 1> x1_h(T(x1_), T(y1_), T(1));
250
+ const Eigen::Matrix<T, 3, 1> x2_h(T(x2_), T(y2_), T(1));
251
+
252
+ // Squared sampson error.
253
+ const Eigen::Matrix<T, 3, 1> Ex1 = E * x1_h;
254
+ const Eigen::Matrix<T, 3, 1> Etx2 = E.transpose() * x2_h;
255
+ const T x2tEx1 = x2_h.transpose() * Ex1;
256
+ residuals[0] = x2tEx1 * x2tEx1 /
257
+ (Ex1(0) * Ex1(0) + Ex1(1) * Ex1(1) + Etx2(0) * Etx2(0) +
258
+ Etx2(1) * Etx2(1));
259
+
260
+ return true;
261
+ }
262
+
263
+ private:
264
+ const double x1_;
265
+ const double y1_;
266
+ const double x2_;
267
+ const double y2_;
268
+ };
269
+
270
+ inline void SetQuaternionManifold(ceres::Problem* problem, double* qvec) {
271
+ #if CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1
272
+ problem->SetManifold(qvec, new ceres::QuaternionManifold);
273
+ #else
274
+ problem->SetParameterization(qvec, new ceres::QuaternionParameterization);
275
+ #endif
276
+ }
277
+
278
+ inline void SetSubsetManifold(int size, const std::vector<int>& constant_params,
279
+ ceres::Problem* problem, double* params) {
280
+ #if CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1
281
+ problem->SetManifold(params,
282
+ new ceres::SubsetManifold(size, constant_params));
283
+ #else
284
+ problem->SetParameterization(
285
+ params, new ceres::SubsetParameterization(size, constant_params));
286
+ #endif
287
+ }
288
+
289
+ template <int size>
290
+ inline void SetSphereManifold(ceres::Problem* problem, double* params) {
291
+ #if CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1
292
+ problem->SetManifold(params, new ceres::SphereManifold<size>);
293
+ #else
294
+ problem->SetParameterization(
295
+ params, new ceres::HomogeneousVectorParameterization(size));
296
+ #endif
297
+ }
298
+
299
+ } // namespace colmap
300
+
301
+ #endif // COLMAP_SRC_BASE_COST_FUNCTIONS_H_
colmap/include/colmap/base/database.h ADDED
@@ -0,0 +1,394 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_DATABASE_H_
33
+ #define COLMAP_SRC_BASE_DATABASE_H_
34
+
35
+ #include <mutex>
36
+ #include <unordered_map>
37
+ #include <vector>
38
+
39
+ #include <Eigen/Core>
40
+ #include <sqlite3.h>
41
+
42
+ #include "base/camera.h"
43
+ #include "base/image.h"
44
+ #include "estimators/two_view_geometry.h"
45
+ #include "feature/types.h"
46
+ #include "util/types.h"
47
+
48
+ namespace colmap {
49
+
50
+ // Database class to read and write images, features, cameras, matches, etc.
51
+ // from a SQLite database. The class is not thread-safe and must not be accessed
52
+ // concurrently. The class is optimized for single-thread speed and for optimal
53
+ // performance, wrap multiple method calls inside a leading `BeginTransaction`
54
+ // and trailing `EndTransaction`.
55
+ class Database {
56
+ public:
57
+ const static int kSchemaVersion = 1;
58
+
59
+ // The maximum number of images, that can be stored in the database.
60
+ // This limitation arises due to the fact, that we generate unique IDs for
61
+ // image pairs manually. Note: do not change this to
62
+ // another type than `size_t`.
63
+ const static size_t kMaxNumImages;
64
+
65
+ Database();
66
+ explicit Database(const std::string& path);
67
+ ~Database();
68
+
69
+ // Open and close database. The same database should not be opened
70
+ // concurrently in multiple threads or processes.
71
+ void Open(const std::string& path);
72
+ void Close();
73
+
74
+ // Check if entry already exists in database. For image pairs, the order of
75
+ // `image_id1` and `image_id2` does not matter.
76
+ bool ExistsCamera(const camera_t camera_id) const;
77
+ bool ExistsImage(const image_t image_id) const;
78
+ bool ExistsImageWithName(std::string name) const;
79
+ bool ExistsKeypoints(const image_t image_id) const;
80
+ bool ExistsDescriptors(const image_t image_id) const;
81
+ bool ExistsMatches(const image_t image_id1, const image_t image_id2) const;
82
+ bool ExistsInlierMatches(const image_t image_id1,
83
+ const image_t image_id2) const;
84
+
85
+ // Number of rows in `cameras` table.
86
+ size_t NumCameras() const;
87
+
88
+ // Number of rows in `images` table.
89
+ size_t NumImages() const;
90
+
91
+ // Sum of `rows` column in `keypoints` table, i.e. number of total keypoints.
92
+ size_t NumKeypoints() const;
93
+
94
+ // The number of keypoints for the image with most features.
95
+ size_t MaxNumKeypoints() const;
96
+
97
+ // Number of descriptors for specific image.
98
+ size_t NumKeypointsForImage(const image_t image_id) const;
99
+
100
+ // Sum of `rows` column in `descriptors` table,
101
+ // i.e. number of total descriptors.
102
+ size_t NumDescriptors() const;
103
+
104
+ // The number of descriptors for the image with most features.
105
+ size_t MaxNumDescriptors() const;
106
+
107
+ // Number of descriptors for specific image.
108
+ size_t NumDescriptorsForImage(const image_t image_id) const;
109
+
110
+ // Sum of `rows` column in `matches` table, i.e. number of total matches.
111
+ size_t NumMatches() const;
112
+
113
+ // Sum of `rows` column in `two_view_geometries` table,
114
+ // i.e. number of total inlier matches.
115
+ size_t NumInlierMatches() const;
116
+
117
+ // Number of rows in `matches` table.
118
+ size_t NumMatchedImagePairs() const;
119
+
120
+ // Number of rows in `two_view_geometries` table.
121
+ size_t NumVerifiedImagePairs() const;
122
+
123
+ // Each image pair is assigned an unique ID in the `matches` and
124
+ // `two_view_geometries` table. We intentionally avoid to store the pairs in a
125
+ // separate table by using e.g. AUTOINCREMENT, since the overhead of querying
126
+ // the unique pair ID is significant.
127
+ inline static image_pair_t ImagePairToPairId(const image_t image_id1,
128
+ const image_t image_id2);
129
+
130
+ inline static void PairIdToImagePair(const image_pair_t pair_id,
131
+ image_t* image_id1, image_t* image_id2);
132
+
133
+ // Return true if image pairs should be swapped. Used to enforce a specific
134
+ // image order to generate unique image pair identifiers independent of the
135
+ // order in which the image identifiers are used.
136
+ inline static bool SwapImagePair(const image_t image_id1,
137
+ const image_t image_id2);
138
+
139
+ // Read an existing entry in the database. The user is responsible for making
140
+ // sure that the entry actually exists. For image pairs, the order of
141
+ // `image_id1` and `image_id2` does not matter.
142
+ Camera ReadCamera(const camera_t camera_id) const;
143
+ std::vector<Camera> ReadAllCameras() const;
144
+
145
+ Image ReadImage(const image_t image_id) const;
146
+ Image ReadImageWithName(const std::string& name) const;
147
+ std::vector<Image> ReadAllImages() const;
148
+
149
+ FeatureKeypoints ReadKeypoints(const image_t image_id) const;
150
+ FeatureDescriptors ReadDescriptors(const image_t image_id) const;
151
+
152
+ FeatureMatches ReadMatches(const image_t image_id1,
153
+ const image_t image_id2) const;
154
+ std::vector<std::pair<image_pair_t, FeatureMatches>> ReadAllMatches() const;
155
+
156
+ TwoViewGeometry ReadTwoViewGeometry(const image_t image_id1,
157
+ const image_t image_id2) const;
158
+ void ReadTwoViewGeometries(
159
+ std::vector<image_pair_t>* image_pair_ids,
160
+ std::vector<TwoViewGeometry>* two_view_geometries) const;
161
+
162
+ // Read all image pairs that have an entry in the `NumVerifiedImagePairs`
163
+ // table with at least one inlier match and their number of inlier matches.
164
+ void ReadTwoViewGeometryNumInliers(
165
+ std::vector<std::pair<image_t, image_t>>* image_pairs,
166
+ std::vector<int>* num_inliers) const;
167
+
168
+ // Add new camera and return its database identifier. If `use_camera_id`
169
+ // is false a new identifier is automatically generated.
170
+ camera_t WriteCamera(const Camera& camera,
171
+ const bool use_camera_id = false) const;
172
+
173
+ // Add new image and return its database identifier. If `use_image_id`
174
+ // is false a new identifier is automatically generated.
175
+ image_t WriteImage(const Image& image, const bool use_image_id = false) const;
176
+
177
+ // Write a new entry in the database. The user is responsible for making sure
178
+ // that the entry does not yet exist. For image pairs, the order of
179
+ // `image_id1` and `image_id2` does not matter.
180
+ void WriteKeypoints(const image_t image_id,
181
+ const FeatureKeypoints& keypoints) const;
182
+ void WriteDescriptors(const image_t image_id,
183
+ const FeatureDescriptors& descriptors) const;
184
+ void WriteMatches(const image_t image_id1, const image_t image_id2,
185
+ const FeatureMatches& matches) const;
186
+ void WriteTwoViewGeometry(const image_t image_id1, const image_t image_id2,
187
+ const TwoViewGeometry& two_view_geometry) const;
188
+
189
+ // Update an existing camera in the database. The user is responsible for
190
+ // making sure that the entry already exists.
191
+ void UpdateCamera(const Camera& camera) const;
192
+
193
+ // Update an existing image in the database. The user is responsible for
194
+ // making sure that the entry already exists.
195
+ void UpdateImage(const Image& image) const;
196
+
197
+ // Delete matches of an image pair.
198
+ void DeleteMatches(const image_t image_id1, const image_t image_id2) const;
199
+
200
+ // Delete inlier matches of an image pair.
201
+ void DeleteInlierMatches(const image_t image_id1,
202
+ const image_t image_id2) const;
203
+
204
+ // Clear all database tables
205
+ void ClearAllTables() const;
206
+
207
+ // Clear the entire cameras table
208
+ void ClearCameras() const;
209
+
210
+ // Clear the entire images, keypoints, and descriptors tables
211
+ void ClearImages() const;
212
+
213
+ // Clear the entire descriptors table
214
+ void ClearDescriptors() const;
215
+
216
+ // Clear the entire keypoints table
217
+ void ClearKeypoints() const;
218
+
219
+ // Clear the entire matches table.
220
+ void ClearMatches() const;
221
+
222
+ // Clear the entire inlier matches table.
223
+ void ClearTwoViewGeometries() const;
224
+
225
+ // Merge two databases into a single, new database.
226
+ static void Merge(const Database& database1, const Database& database2,
227
+ Database* merged_database);
228
+
229
+ private:
230
+ friend class DatabaseTransaction;
231
+
232
+ // Combine multiple queries into one transaction by wrapping a code section
233
+ // into a `BeginTransaction` and `EndTransaction`. You can create a scoped
234
+ // transaction with `DatabaseTransaction` that ends when the transaction
235
+ // object is destructed. Combining queries results in faster transaction time
236
+ // due to reduced locking of the database etc.
237
+ void BeginTransaction() const;
238
+ void EndTransaction() const;
239
+
240
+ // Prepare SQL statements once at construction of the database, and reuse
241
+ // the statements for multiple queries by resetting their states.
242
+ void PrepareSQLStatements();
243
+ void FinalizeSQLStatements();
244
+
245
+ // Create database tables, if not existing, called when opening a database.
246
+ void CreateTables() const;
247
+ void CreateCameraTable() const;
248
+ void CreateImageTable() const;
249
+ void CreateKeypointsTable() const;
250
+ void CreateDescriptorsTable() const;
251
+ void CreateMatchesTable() const;
252
+ void CreateTwoViewGeometriesTable() const;
253
+
254
+ void UpdateSchema() const;
255
+
256
+ bool ExistsTable(const std::string& table_name) const;
257
+ bool ExistsColumn(const std::string& table_name,
258
+ const std::string& column_name) const;
259
+
260
+ bool ExistsRowId(sqlite3_stmt* sql_stmt, const sqlite3_int64 row_id) const;
261
+ bool ExistsRowString(sqlite3_stmt* sql_stmt,
262
+ const std::string& row_entry) const;
263
+
264
+ size_t CountRows(const std::string& table) const;
265
+ size_t CountRowsForEntry(sqlite3_stmt* sql_stmt,
266
+ const sqlite3_int64 row_id) const;
267
+ size_t SumColumn(const std::string& column, const std::string& table) const;
268
+ size_t MaxColumn(const std::string& column, const std::string& table) const;
269
+
270
+ sqlite3* database_ = nullptr;
271
+
272
+ // Check if elements got removed from the database to only apply
273
+ // the VACUUM command in such case
274
+ mutable bool database_cleared_ = false;
275
+
276
+ // Ensure that only one database object at a time updates the schema of a
277
+ // database. Since the schema is updated every time a database is opened, this
278
+ // is to ensure that there are no race conditions ("database locked" error
279
+ // messages) when the user actually only intends to read from the database,
280
+ // which requires to open it.
281
+ static std::mutex update_schema_mutex_;
282
+
283
+ // Used to ensure that only one transaction is active at the same time.
284
+ std::mutex transaction_mutex_;
285
+
286
+ // A collection of all `sqlite3_stmt` objects for deletion in the destructor.
287
+ std::vector<sqlite3_stmt*> sql_stmts_;
288
+
289
+ // num_*
290
+ sqlite3_stmt* sql_stmt_num_keypoints_ = nullptr;
291
+ sqlite3_stmt* sql_stmt_num_descriptors_ = nullptr;
292
+
293
+ // exists_*
294
+ sqlite3_stmt* sql_stmt_exists_camera_ = nullptr;
295
+ sqlite3_stmt* sql_stmt_exists_image_id_ = nullptr;
296
+ sqlite3_stmt* sql_stmt_exists_image_name_ = nullptr;
297
+ sqlite3_stmt* sql_stmt_exists_keypoints_ = nullptr;
298
+ sqlite3_stmt* sql_stmt_exists_descriptors_ = nullptr;
299
+ sqlite3_stmt* sql_stmt_exists_matches_ = nullptr;
300
+ sqlite3_stmt* sql_stmt_exists_two_view_geometry_ = nullptr;
301
+
302
+ // add_*
303
+ sqlite3_stmt* sql_stmt_add_camera_ = nullptr;
304
+ sqlite3_stmt* sql_stmt_add_image_ = nullptr;
305
+
306
+ // update_*
307
+ sqlite3_stmt* sql_stmt_update_camera_ = nullptr;
308
+ sqlite3_stmt* sql_stmt_update_image_ = nullptr;
309
+
310
+ // read_*
311
+ sqlite3_stmt* sql_stmt_read_camera_ = nullptr;
312
+ sqlite3_stmt* sql_stmt_read_cameras_ = nullptr;
313
+ sqlite3_stmt* sql_stmt_read_image_id_ = nullptr;
314
+ sqlite3_stmt* sql_stmt_read_image_name_ = nullptr;
315
+ sqlite3_stmt* sql_stmt_read_images_ = nullptr;
316
+ sqlite3_stmt* sql_stmt_read_keypoints_ = nullptr;
317
+ sqlite3_stmt* sql_stmt_read_descriptors_ = nullptr;
318
+ sqlite3_stmt* sql_stmt_read_matches_ = nullptr;
319
+ sqlite3_stmt* sql_stmt_read_matches_all_ = nullptr;
320
+ sqlite3_stmt* sql_stmt_read_two_view_geometry_ = nullptr;
321
+ sqlite3_stmt* sql_stmt_read_two_view_geometries_ = nullptr;
322
+ sqlite3_stmt* sql_stmt_read_two_view_geometry_num_inliers_ = nullptr;
323
+
324
+ // write_*
325
+ sqlite3_stmt* sql_stmt_write_keypoints_ = nullptr;
326
+ sqlite3_stmt* sql_stmt_write_descriptors_ = nullptr;
327
+ sqlite3_stmt* sql_stmt_write_matches_ = nullptr;
328
+ sqlite3_stmt* sql_stmt_write_two_view_geometry_ = nullptr;
329
+
330
+ // delete_*
331
+ sqlite3_stmt* sql_stmt_delete_matches_ = nullptr;
332
+ sqlite3_stmt* sql_stmt_delete_two_view_geometry_ = nullptr;
333
+
334
+ // clear_*
335
+ sqlite3_stmt* sql_stmt_clear_cameras_ = nullptr;
336
+ sqlite3_stmt* sql_stmt_clear_images_ = nullptr;
337
+ sqlite3_stmt* sql_stmt_clear_descriptors_ = nullptr;
338
+ sqlite3_stmt* sql_stmt_clear_keypoints_ = nullptr;
339
+ sqlite3_stmt* sql_stmt_clear_matches_ = nullptr;
340
+ sqlite3_stmt* sql_stmt_clear_two_view_geometries_ = nullptr;
341
+ };
342
+
343
+ // This class automatically manages the scope of a database transaction by
344
+ // calling `BeginTransaction` and `EndTransaction` during construction and
345
+ // destruction, respectively.
346
+ class DatabaseTransaction {
347
+ public:
348
+ explicit DatabaseTransaction(Database* database);
349
+ ~DatabaseTransaction();
350
+
351
+ private:
352
+ NON_COPYABLE(DatabaseTransaction)
353
+ NON_MOVABLE(DatabaseTransaction)
354
+ Database* database_;
355
+ std::unique_lock<std::mutex> database_lock_;
356
+ };
357
+
358
+ ////////////////////////////////////////////////////////////////////////////////
359
+ // Implementation
360
+ ////////////////////////////////////////////////////////////////////////////////
361
+
362
+ image_pair_t Database::ImagePairToPairId(const image_t image_id1,
363
+ const image_t image_id2) {
364
+ CHECK_GE(image_id1, 0);
365
+ CHECK_GE(image_id2, 0);
366
+ CHECK_LT(image_id1, kMaxNumImages);
367
+ CHECK_LT(image_id2, kMaxNumImages);
368
+ if (SwapImagePair(image_id1, image_id2)) {
369
+ return static_cast<image_pair_t>(kMaxNumImages) * image_id2 + image_id1;
370
+ } else {
371
+ return static_cast<image_pair_t>(kMaxNumImages) * image_id1 + image_id2;
372
+ }
373
+ }
374
+
375
+ void Database::PairIdToImagePair(const image_pair_t pair_id, image_t* image_id1,
376
+ image_t* image_id2) {
377
+ *image_id2 = static_cast<image_t>(pair_id % kMaxNumImages);
378
+ *image_id1 = static_cast<image_t>((pair_id - *image_id2) / kMaxNumImages);
379
+ CHECK_GE(*image_id1, 0);
380
+ CHECK_GE(*image_id2, 0);
381
+ CHECK_LT(*image_id1, kMaxNumImages);
382
+ CHECK_LT(*image_id2, kMaxNumImages);
383
+ }
384
+
385
+ // Return true if image pairs should be swapped. Used to enforce a specific
386
+ // image order to generate unique image pair identifiers independent of the
387
+ // order in which the image identifiers are used.
388
+ bool Database::SwapImagePair(const image_t image_id1, const image_t image_id2) {
389
+ return image_id1 > image_id2;
390
+ }
391
+
392
+ } // namespace colmap
393
+
394
+ #endif // COLMAP_SRC_BASE_DATABASE_H_
colmap/include/colmap/base/database_cache.h ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_DATABASE_CACHE_H_
33
+ #define COLMAP_SRC_BASE_DATABASE_CACHE_H_
34
+
35
+ #include <string>
36
+ #include <unordered_map>
37
+ #include <unordered_set>
38
+ #include <vector>
39
+
40
+ #include <Eigen/Core>
41
+
42
+ #include "base/camera.h"
43
+ #include "base/camera_models.h"
44
+ #include "base/correspondence_graph.h"
45
+ #include "base/database.h"
46
+ #include "base/image.h"
47
+ #include "util/alignment.h"
48
+ #include "util/types.h"
49
+
50
+ namespace colmap {
51
+
52
+ // A class that caches the contents of the database in memory, used to quickly
53
+ // create new reconstruction instances when multiple models are reconstructed.
54
+ class DatabaseCache {
55
+ public:
56
+ DatabaseCache();
57
+
58
+ // Get number of objects.
59
+ inline size_t NumCameras() const;
60
+ inline size_t NumImages() const;
61
+
62
+ // Get specific objects.
63
+ inline class Camera& Camera(const camera_t camera_id);
64
+ inline const class Camera& Camera(const camera_t camera_id) const;
65
+ inline class Image& Image(const image_t image_id);
66
+ inline const class Image& Image(const image_t image_id) const;
67
+
68
+ // Get all objects.
69
+ inline const EIGEN_STL_UMAP(camera_t, class Camera) & Cameras() const;
70
+ inline const EIGEN_STL_UMAP(image_t, class Image) & Images() const;
71
+
72
+ // Check whether specific object exists.
73
+ inline bool ExistsCamera(const camera_t camera_id) const;
74
+ inline bool ExistsImage(const image_t image_id) const;
75
+
76
+ // Get reference to correspondence graph.
77
+ inline const class CorrespondenceGraph& CorrespondenceGraph() const;
78
+
79
+ // Manually add data to cache.
80
+ void AddCamera(class Camera camera);
81
+ void AddImage(class Image image);
82
+
83
+ // Load cameras, images, features, and matches from database.
84
+ //
85
+ // @param database Source database from which to load data.
86
+ // @param min_num_matches Only load image pairs with a minimum number
87
+ // of matches.
88
+ // @param ignore_watermarks Whether to ignore watermark image pairs.
89
+ // @param image_names Whether to use only load the data for a subset
90
+ // of the images. All images are used if empty.
91
+ void Load(const Database& database, const size_t min_num_matches,
92
+ const bool ignore_watermarks,
93
+ const std::unordered_set<std::string>& image_names);
94
+
95
+ // Find specific image by name. Note that this uses linear search.
96
+ const class Image* FindImageWithName(const std::string& name) const;
97
+
98
+ private:
99
+ class CorrespondenceGraph correspondence_graph_;
100
+
101
+ EIGEN_STL_UMAP(camera_t, class Camera) cameras_;
102
+ EIGEN_STL_UMAP(image_t, class Image) images_;
103
+ };
104
+
105
+ ////////////////////////////////////////////////////////////////////////////////
106
+ // Implementation
107
+ ////////////////////////////////////////////////////////////////////////////////
108
+
109
+ size_t DatabaseCache::NumCameras() const { return cameras_.size(); }
110
+ size_t DatabaseCache::NumImages() const { return images_.size(); }
111
+
112
+ class Camera& DatabaseCache::Camera(const camera_t camera_id) {
113
+ return cameras_.at(camera_id);
114
+ }
115
+
116
+ const class Camera& DatabaseCache::Camera(const camera_t camera_id) const {
117
+ return cameras_.at(camera_id);
118
+ }
119
+
120
+ class Image& DatabaseCache::Image(const image_t image_id) {
121
+ return images_.at(image_id);
122
+ }
123
+
124
+ const class Image& DatabaseCache::Image(const image_t image_id) const {
125
+ return images_.at(image_id);
126
+ }
127
+
128
+ const EIGEN_STL_UMAP(camera_t, class Camera) & DatabaseCache::Cameras() const {
129
+ return cameras_;
130
+ }
131
+
132
+ const EIGEN_STL_UMAP(image_t, class Image) & DatabaseCache::Images() const {
133
+ return images_;
134
+ }
135
+
136
+ bool DatabaseCache::ExistsCamera(const camera_t camera_id) const {
137
+ return cameras_.find(camera_id) != cameras_.end();
138
+ }
139
+
140
+ bool DatabaseCache::ExistsImage(const image_t image_id) const {
141
+ return images_.find(image_id) != images_.end();
142
+ }
143
+
144
+ inline const class CorrespondenceGraph& DatabaseCache::CorrespondenceGraph()
145
+ const {
146
+ return correspondence_graph_;
147
+ }
148
+
149
+ } // namespace colmap
150
+
151
+ #endif // COLMAP_SRC_BASE_DATABASE_CACHE_H_
colmap/include/colmap/base/essential_matrix.h ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_ESSENTIAL_MATRIX_H_
33
+ #define COLMAP_SRC_BASE_ESSENTIAL_MATRIX_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include <ceres/ceres.h>
40
+
41
+ #include "util/alignment.h"
42
+ #include "util/types.h"
43
+
44
+ namespace colmap {
45
+
46
+ // Decompose an essential matrix into the possible rotations and translations.
47
+ //
48
+ // The first pose is assumed to be P = [I | 0] and the set of four other
49
+ // possible second poses are defined as: {[R1 | t], [R2 | t],
50
+ // [R1 | -t], [R2 | -t]}
51
+ //
52
+ // @param E 3x3 essential matrix.
53
+ // @param R1 First possible 3x3 rotation matrix.
54
+ // @param R2 Second possible 3x3 rotation matrix.
55
+ // @param t 3x1 possible translation vector (also -t possible).
56
+ void DecomposeEssentialMatrix(const Eigen::Matrix3d& E, Eigen::Matrix3d* R1,
57
+ Eigen::Matrix3d* R2, Eigen::Vector3d* t);
58
+
59
+ // Recover the most probable pose from the given essential matrix.
60
+ //
61
+ // The pose of the first image is assumed to be P = [I | 0].
62
+ //
63
+ // @param E 3x3 essential matrix.
64
+ // @param points1 First set of corresponding points.
65
+ // @param points2 Second set of corresponding points.
66
+ // @param inlier_mask Only points with `true` in the inlier mask are
67
+ // considered in the cheirality test. Size of the
68
+ // inlier mask must match the number of points N.
69
+ // @param R Most probable 3x3 rotation matrix.
70
+ // @param t Most probable 3x1 translation vector.
71
+ // @param points3D Triangulated 3D points infront of camera.
72
+ void PoseFromEssentialMatrix(const Eigen::Matrix3d& E,
73
+ const std::vector<Eigen::Vector2d>& points1,
74
+ const std::vector<Eigen::Vector2d>& points2,
75
+ Eigen::Matrix3d* R, Eigen::Vector3d* t,
76
+ std::vector<Eigen::Vector3d>* points3D);
77
+
78
+ // Compose essential matrix from relative camera poses.
79
+ //
80
+ // Assumes that first camera pose has projection matrix P = [I | 0], and
81
+ // pose of second camera is given as transformation from world to camera system.
82
+ //
83
+ // @param R 3x3 rotation matrix.
84
+ // @param t 3x1 translation vector.
85
+ //
86
+ // @return 3x3 essential matrix.
87
+ Eigen::Matrix3d EssentialMatrixFromPose(const Eigen::Matrix3d& R,
88
+ const Eigen::Vector3d& t);
89
+
90
+ // Compose essential matrix from two absolute camera poses.
91
+ //
92
+ // @param proj_matrix1 3x4 projection matrix.
93
+ // @param proj_matrix2 3x4 projection matrix.
94
+ //
95
+ // @return 3x3 essential matrix.
96
+ Eigen::Matrix3d EssentialMatrixFromAbsolutePoses(
97
+ const Eigen::Matrix3x4d& proj_matrix1,
98
+ const Eigen::Matrix3x4d& proj_matrix2);
99
+
100
+ // Find optimal image points, such that:
101
+ //
102
+ // optimal_point1^t * E * optimal_point2 = 0
103
+ //
104
+ // as described in:
105
+ //
106
+ // Lindstrom, P., "Triangulation made easy",
107
+ // Computer Vision and Pattern Recognition (CVPR),
108
+ // 2010 IEEE Conference on , vol., no., pp.1554,1561, 13-18 June 2010
109
+ //
110
+ // @param E Essential or fundamental matrix.
111
+ // @param point1 Corresponding 2D point in first image.
112
+ // @param point2 Corresponding 2D point in second image.
113
+ // @param optimal_point1 Estimated optimal image point in the first image.
114
+ // @param optimal_point2 Estimated optimal image point in the second image.
115
+ void FindOptimalImageObservations(const Eigen::Matrix3d& E,
116
+ const Eigen::Vector2d& point1,
117
+ const Eigen::Vector2d& point2,
118
+ Eigen::Vector2d* optimal_point1,
119
+ Eigen::Vector2d* optimal_point2);
120
+
121
+ // Compute the location of the epipole in homogeneous coordinates.
122
+ //
123
+ // @param E 3x3 essential matrix.
124
+ // @param left_image If true, epipole in left image is computed,
125
+ // else in right image.
126
+ //
127
+ // @return Epipole in homogeneous coordinates.
128
+ Eigen::Vector3d EpipoleFromEssentialMatrix(const Eigen::Matrix3d& E,
129
+ const bool left_image);
130
+
131
+ // Invert the essential matrix, i.e. if the essential matrix E describes the
132
+ // transformation from camera A to B, the inverted essential matrix E' describes
133
+ // the transformation from camera B to A.
134
+ //
135
+ // @param E 3x3 essential matrix.
136
+ //
137
+ // @return Inverted essential matrix.
138
+ Eigen::Matrix3d InvertEssentialMatrix(const Eigen::Matrix3d& matrix);
139
+
140
+ // Refine essential matrix.
141
+ //
142
+ // Decomposes the essential matrix into rotation and translation components
143
+ // and refines the relative pose using the function `RefineRelativePose`.
144
+ //
145
+ // @param E 3x3 essential matrix.
146
+ // @param points1 First set of corresponding points.
147
+ // @param points2 Second set of corresponding points.
148
+ // @param inlier_mask Inlier mask for corresponding points.
149
+ // @param options Solver options.
150
+ //
151
+ // @return Flag indicating if solution is usable.
152
+ bool RefineEssentialMatrix(const ceres::Solver::Options& options,
153
+ const std::vector<Eigen::Vector2d>& points1,
154
+ const std::vector<Eigen::Vector2d>& points2,
155
+ const std::vector<char>& inlier_mask,
156
+ Eigen::Matrix3d* E);
157
+
158
+ } // namespace colmap
159
+
160
+ #endif // COLMAP_SRC_BASE_ESSENTIAL_MATRIX_H_
colmap/include/colmap/base/gps.h ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_GPS_H_
33
+ #define COLMAP_SRC_BASE_GPS_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ // Transform ellipsoidal GPS coordinates to Cartesian GPS coordinate
45
+ // representation and vice versa.
46
+ class GPSTransform {
47
+ public:
48
+ enum ELLIPSOID { GRS80, WGS84 };
49
+
50
+ explicit GPSTransform(const int ellipsoid = GRS80);
51
+
52
+ std::vector<Eigen::Vector3d> EllToXYZ(
53
+ const std::vector<Eigen::Vector3d>& ell) const;
54
+
55
+ std::vector<Eigen::Vector3d> XYZToEll(
56
+ const std::vector<Eigen::Vector3d>& xyz) const;
57
+
58
+ // Convert GPS (lat / lon / alt) to ENU coords. with lat0 and lon0
59
+ // defining the origin of the ENU frame
60
+ std::vector<Eigen::Vector3d> EllToENU(const std::vector<Eigen::Vector3d>& ell,
61
+ const double lat0,
62
+ const double lon0) const;
63
+
64
+ std::vector<Eigen::Vector3d> XYZToENU(const std::vector<Eigen::Vector3d>& xyz,
65
+ const double lat0,
66
+ const double lon0) const;
67
+
68
+ std::vector<Eigen::Vector3d> ENUToEll(const std::vector<Eigen::Vector3d>& enu,
69
+ const double lat0, const double lon0,
70
+ const double alt0) const;
71
+
72
+ std::vector<Eigen::Vector3d> ENUToXYZ(const std::vector<Eigen::Vector3d>& enu,
73
+ const double lat0, const double lon0,
74
+ const double alt0) const;
75
+
76
+ private:
77
+ // Semimajor axis.
78
+ double a_;
79
+ // Semiminor axis.
80
+ double b_;
81
+ // Flattening.
82
+ double f_;
83
+ // Numerical eccentricity.
84
+ double e2_;
85
+ };
86
+
87
+ } // namespace colmap
88
+
89
+ #endif // COLMAP_SRC_BASE_GPS_H_
colmap/include/colmap/base/graph_cut.h ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_GRAPH_CUT_H_
33
+ #define COLMAP_SRC_BASE_GRAPH_CUT_H_
34
+
35
+ #include <unordered_map>
36
+ #include <vector>
37
+
38
+ #include <boost/graph/adjacency_list.hpp>
39
+ #include <boost/graph/boykov_kolmogorov_max_flow.hpp>
40
+ #include <boost/graph/graph_traits.hpp>
41
+ #include <boost/graph/one_bit_color_map.hpp>
42
+
43
+ #include "util/logging.h"
44
+
45
+ namespace colmap {
46
+
47
+ // Compute the min-cut of a undirected graph using the Stoer Wagner algorithm.
48
+ void ComputeMinGraphCutStoerWagner(
49
+ const std::vector<std::pair<int, int>>& edges,
50
+ const std::vector<int>& weights, int* cut_weight,
51
+ std::vector<char>* cut_labels);
52
+
53
+ // Compute the normalized min-cut of an undirected graph using Metis.
54
+ // Partitions the graph into clusters and returns the cluster labels per vertex.
55
+ std::unordered_map<int, int> ComputeNormalizedMinGraphCut(
56
+ const std::vector<std::pair<int, int>>& edges,
57
+ const std::vector<int>& weights, const int num_parts);
58
+
59
+ // Compute the minimum graph cut of a directed S-T graph using the
60
+ // Boykov-Kolmogorov max-flow min-cut algorithm, as descibed in:
61
+ // "An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy
62
+ // Minimization in Vision". Yuri Boykov and Vladimir Kolmogorov. PAMI, 2004.
63
+ template <typename node_t, typename value_t>
64
+ class MinSTGraphCut {
65
+ public:
66
+ typedef boost::adjacency_list_traits<boost::vecS, boost::vecS,
67
+ boost::directedS>
68
+ graph_traits_t;
69
+ typedef graph_traits_t::edge_descriptor edge_descriptor_t;
70
+ typedef graph_traits_t::vertices_size_type vertices_size_t;
71
+
72
+ struct Edge {
73
+ value_t capacity;
74
+ value_t residual;
75
+ edge_descriptor_t reverse;
76
+ };
77
+
78
+ typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
79
+ size_t, Edge>
80
+ graph_t;
81
+
82
+ MinSTGraphCut(const size_t num_nodes);
83
+
84
+ // Count the number of nodes and edges in the graph.
85
+ size_t NumNodes() const;
86
+ size_t NumEdges() const;
87
+
88
+ // Add node to the graph.
89
+ void AddNode(const node_t node_idx, const value_t source_capacity,
90
+ const value_t sink_capacity);
91
+
92
+ // Add edge to the graph.
93
+ void AddEdge(const node_t node_idx1, const node_t node_idx2,
94
+ const value_t capacity, const value_t reverse_capacity);
95
+
96
+ // Compute the min-cut using the max-flow algorithm. Returns the flow.
97
+ value_t Compute();
98
+
99
+ // Check whether node is connected to source or sink after computing the cut.
100
+ bool IsConnectedToSource(const node_t node_idx) const;
101
+ bool IsConnectedToSink(const node_t node_idx) const;
102
+
103
+ private:
104
+ const node_t S_node_;
105
+ const node_t T_node_;
106
+ graph_t graph_;
107
+ std::vector<boost::default_color_type> colors_;
108
+ };
109
+
110
+ ////////////////////////////////////////////////////////////////////////////////
111
+ // Implementation
112
+ ////////////////////////////////////////////////////////////////////////////////
113
+
114
+ template <typename node_t, typename value_t>
115
+ MinSTGraphCut<node_t, value_t>::MinSTGraphCut(const size_t num_nodes)
116
+ : S_node_(num_nodes), T_node_(num_nodes + 1), graph_(num_nodes + 2) {}
117
+
118
+ template <typename node_t, typename value_t>
119
+ size_t MinSTGraphCut<node_t, value_t>::NumNodes() const {
120
+ return boost::num_vertices(graph_) - 2;
121
+ }
122
+
123
+ template <typename node_t, typename value_t>
124
+ size_t MinSTGraphCut<node_t, value_t>::NumEdges() const {
125
+ return boost::num_edges(graph_);
126
+ }
127
+
128
+ template <typename node_t, typename value_t>
129
+ void MinSTGraphCut<node_t, value_t>::AddNode(const node_t node_idx,
130
+ const value_t source_capacity,
131
+ const value_t sink_capacity) {
132
+ CHECK_GE(node_idx, 0);
133
+ CHECK_LE(node_idx, boost::num_vertices(graph_));
134
+ CHECK_GE(source_capacity, 0);
135
+ CHECK_GE(sink_capacity, 0);
136
+
137
+ if (source_capacity > 0) {
138
+ const edge_descriptor_t edge =
139
+ boost::add_edge(S_node_, node_idx, graph_).first;
140
+ const edge_descriptor_t edge_reverse =
141
+ boost::add_edge(node_idx, S_node_, graph_).first;
142
+ graph_[edge].capacity = source_capacity;
143
+ graph_[edge].reverse = edge_reverse;
144
+ graph_[edge_reverse].reverse = edge;
145
+ }
146
+
147
+ if (sink_capacity > 0) {
148
+ const edge_descriptor_t edge =
149
+ boost::add_edge(node_idx, T_node_, graph_).first;
150
+ const edge_descriptor_t edge_reverse =
151
+ boost::add_edge(T_node_, node_idx, graph_).first;
152
+ graph_[edge].capacity = sink_capacity;
153
+ graph_[edge].reverse = edge_reverse;
154
+ graph_[edge_reverse].reverse = edge;
155
+ }
156
+ }
157
+
158
+ template <typename node_t, typename value_t>
159
+ void MinSTGraphCut<node_t, value_t>::AddEdge(const node_t node_idx1,
160
+ const node_t node_idx2,
161
+ const value_t capacity,
162
+ const value_t reverse_capacity) {
163
+ CHECK_GE(node_idx1, 0);
164
+ CHECK_LE(node_idx1, boost::num_vertices(graph_));
165
+ CHECK_GE(node_idx2, 0);
166
+ CHECK_LE(node_idx2, boost::num_vertices(graph_));
167
+ CHECK_GE(capacity, 0);
168
+ CHECK_GE(reverse_capacity, 0);
169
+
170
+ const edge_descriptor_t edge =
171
+ boost::add_edge(node_idx1, node_idx2, graph_).first;
172
+ const edge_descriptor_t edge_reverse =
173
+ boost::add_edge(node_idx2, node_idx1, graph_).first;
174
+ graph_[edge].capacity = capacity;
175
+ graph_[edge_reverse].capacity = reverse_capacity;
176
+ graph_[edge].reverse = edge_reverse;
177
+ graph_[edge_reverse].reverse = edge;
178
+ }
179
+
180
+ template <typename node_t, typename value_t>
181
+ value_t MinSTGraphCut<node_t, value_t>::Compute() {
182
+ const vertices_size_t num_vertices = boost::num_vertices(graph_);
183
+
184
+ colors_.resize(num_vertices);
185
+ std::vector<edge_descriptor_t> predecessors(num_vertices);
186
+ std::vector<vertices_size_t> distances(num_vertices);
187
+
188
+ return boost::boykov_kolmogorov_max_flow(
189
+ graph_, boost::get(&Edge::capacity, graph_),
190
+ boost::get(&Edge::residual, graph_), boost::get(&Edge::reverse, graph_),
191
+ predecessors.data(), colors_.data(), distances.data(),
192
+ boost::get(boost::vertex_index, graph_), S_node_, T_node_);
193
+ }
194
+
195
+ template <typename node_t, typename value_t>
196
+ bool MinSTGraphCut<node_t, value_t>::IsConnectedToSource(
197
+ const node_t node_idx) const {
198
+ return colors_.at(node_idx) != boost::white_color;
199
+ }
200
+
201
+ template <typename node_t, typename value_t>
202
+ bool MinSTGraphCut<node_t, value_t>::IsConnectedToSink(
203
+ const node_t node_idx) const {
204
+ return colors_.at(node_idx) == boost::white_color;
205
+ }
206
+
207
+ } // namespace colmap
208
+
209
+ #endif // COLMAP_SRC_BASE_GRAPH_CUT_H_
colmap/include/colmap/base/homography_matrix.h ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_HOMOGRAPHY_MATRIX_UTILS_H_
33
+ #define COLMAP_SRC_BASE_HOMOGRAPHY_MATRIX_UTILS_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ // Decompose an homography matrix into the possible rotations, translations,
45
+ // and plane normal vectors, according to:
46
+ //
47
+ // Malis, Ezio, and Manuel Vargas. "Deeper understanding of the homography
48
+ // decomposition for vision-based control." (2007): 90.
49
+ //
50
+ // The first pose is assumed to be P = [I | 0]. Note that the homography is
51
+ // plane-induced if `R.size() == t.size() == n.size() == 4`. If `R.size() ==
52
+ // t.size() == n.size() == 1` the homography is pure-rotational.
53
+ //
54
+ // @param H 3x3 homography matrix.
55
+ // @param K 3x3 calibration matrix.
56
+ // @param R Possible 3x3 rotation matrices.
57
+ // @param t Possible translation vectors.
58
+ // @param n Possible normal vectors.
59
+ void DecomposeHomographyMatrix(const Eigen::Matrix3d& H,
60
+ const Eigen::Matrix3d& K1,
61
+ const Eigen::Matrix3d& K2,
62
+ std::vector<Eigen::Matrix3d>* R,
63
+ std::vector<Eigen::Vector3d>* t,
64
+ std::vector<Eigen::Vector3d>* n);
65
+
66
+ // Recover the most probable pose from the given homography matrix.
67
+ //
68
+ // The pose of the first image is assumed to be P = [I | 0].
69
+ //
70
+ // @param H 3x3 homography matrix.
71
+ // @param K1 3x3 calibration matrix of first camera.
72
+ // @param K2 3x3 calibration matrix of second camera.
73
+ // @param points1 First set of corresponding points.
74
+ // @param points2 Second set of corresponding points.
75
+ // @param inlier_mask Only points with `true` in the inlier mask are
76
+ // considered in the cheirality test. Size of the
77
+ // inlier mask must match the number of points N.
78
+ // @param R Most probable 3x3 rotation matrix.
79
+ // @param t Most probable 3x1 translation vector.
80
+ // @param n Most probable 3x1 normal vector.
81
+ // @param points3D Triangulated 3D points infront of camera
82
+ // (only if homography is not pure-rotational).
83
+ void PoseFromHomographyMatrix(const Eigen::Matrix3d& H,
84
+ const Eigen::Matrix3d& K1,
85
+ const Eigen::Matrix3d& K2,
86
+ const std::vector<Eigen::Vector2d>& points1,
87
+ const std::vector<Eigen::Vector2d>& points2,
88
+ Eigen::Matrix3d* R, Eigen::Vector3d* t,
89
+ Eigen::Vector3d* n,
90
+ std::vector<Eigen::Vector3d>* points3D);
91
+
92
+ // Compose homography matrix from relative pose.
93
+ //
94
+ // @param K1 3x3 calibration matrix of first camera.
95
+ // @param K2 3x3 calibration matrix of second camera.
96
+ // @param R Most probable 3x3 rotation matrix.
97
+ // @param t Most probable 3x1 translation vector.
98
+ // @param n Most probable 3x1 normal vector.
99
+ // @param d Orthogonal distance from plane.
100
+ //
101
+ // @return 3x3 homography matrix.
102
+ Eigen::Matrix3d HomographyMatrixFromPose(const Eigen::Matrix3d& K1,
103
+ const Eigen::Matrix3d& K2,
104
+ const Eigen::Matrix3d& R,
105
+ const Eigen::Vector3d& t,
106
+ const Eigen::Vector3d& n,
107
+ const double d);
108
+
109
+ } // namespace colmap
110
+
111
+ #endif // COLMAP_SRC_BASE_HOMOGRAPHY_MATRIX_UTILS_H_
colmap/include/colmap/base/image.h ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_IMAGE_H_
33
+ #define COLMAP_SRC_BASE_IMAGE_H_
34
+
35
+ #include <string>
36
+ #include <vector>
37
+
38
+ #include <Eigen/Core>
39
+
40
+ #include "base/camera.h"
41
+ #include "base/point2d.h"
42
+ #include "base/visibility_pyramid.h"
43
+ #include "util/alignment.h"
44
+ #include "util/logging.h"
45
+ #include "util/math.h"
46
+ #include "util/types.h"
47
+
48
+ namespace colmap {
49
+
50
+ // Class that holds information about an image. An image is the product of one
51
+ // camera shot at a certain location (parameterized as the pose). An image may
52
+ // share a camera with multiple other images, if its intrinsics are the same.
53
+ class Image {
54
+ public:
55
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
56
+
57
+ Image();
58
+
59
+ // Setup / tear down the image and necessary internal data structures before
60
+ // and after being used in reconstruction.
61
+ void SetUp(const Camera& camera);
62
+ void TearDown();
63
+
64
+ // Access the unique identifier of the image.
65
+ inline image_t ImageId() const;
66
+ inline void SetImageId(const image_t image_id);
67
+
68
+ // Access the name of the image.
69
+ inline const std::string& Name() const;
70
+ inline std::string& Name();
71
+ inline void SetName(const std::string& name);
72
+
73
+ // Access the unique identifier of the camera. Note that multiple images
74
+ // might share the same camera.
75
+ inline camera_t CameraId() const;
76
+ inline void SetCameraId(const camera_t camera_id);
77
+ // Check whether identifier of camera has been set.
78
+ inline bool HasCamera() const;
79
+
80
+ // Check if image is registered.
81
+ inline bool IsRegistered() const;
82
+ inline void SetRegistered(const bool registered);
83
+
84
+ // Get the number of image points.
85
+ inline point2D_t NumPoints2D() const;
86
+
87
+ // Get the number of triangulations, i.e. the number of points that
88
+ // are part of a 3D point track.
89
+ inline point2D_t NumPoints3D() const;
90
+
91
+ // Get the number of observations, i.e. the number of image points that
92
+ // have at least one correspondence to another image.
93
+ inline point2D_t NumObservations() const;
94
+ inline void SetNumObservations(const point2D_t num_observations);
95
+
96
+ // Get the number of correspondences for all image points.
97
+ inline point2D_t NumCorrespondences() const;
98
+ inline void SetNumCorrespondences(const point2D_t num_observations);
99
+
100
+ // Get the number of observations that see a triangulated point, i.e. the
101
+ // number of image points that have at least one correspondence to a
102
+ // triangulated point in another image.
103
+ inline point2D_t NumVisiblePoints3D() const;
104
+
105
+ // Get the score of triangulated observations. In contrast to
106
+ // `NumVisiblePoints3D`, this score also captures the distribution
107
+ // of triangulated observations in the image. This is useful to select
108
+ // the next best image in incremental reconstruction, because a more
109
+ // uniform distribution of observations results in more robust registration.
110
+ inline size_t Point3DVisibilityScore() const;
111
+
112
+ // Access quaternion vector as (qw, qx, qy, qz) specifying the rotation of the
113
+ // pose which is defined as the transformation from world to image space.
114
+ inline const Eigen::Vector4d& Qvec() const;
115
+ inline Eigen::Vector4d& Qvec();
116
+ inline double Qvec(const size_t idx) const;
117
+ inline double& Qvec(const size_t idx);
118
+ inline void SetQvec(const Eigen::Vector4d& qvec);
119
+
120
+ // Quaternion prior, e.g. given by EXIF gyroscope tag.
121
+ inline const Eigen::Vector4d& QvecPrior() const;
122
+ inline Eigen::Vector4d& QvecPrior();
123
+ inline double QvecPrior(const size_t idx) const;
124
+ inline double& QvecPrior(const size_t idx);
125
+ inline bool HasQvecPrior() const;
126
+ inline void SetQvecPrior(const Eigen::Vector4d& qvec);
127
+
128
+ // Access translation vector as (tx, ty, tz) specifying the translation of the
129
+ // pose which is defined as the transformation from world to image space.
130
+ inline const Eigen::Vector3d& Tvec() const;
131
+ inline Eigen::Vector3d& Tvec();
132
+ inline double Tvec(const size_t idx) const;
133
+ inline double& Tvec(const size_t idx);
134
+ inline void SetTvec(const Eigen::Vector3d& tvec);
135
+
136
+ // Translation prior, e.g. given by EXIF GPS tag.
137
+ inline const Eigen::Vector3d& TvecPrior() const;
138
+ inline Eigen::Vector3d& TvecPrior();
139
+ inline double TvecPrior(const size_t idx) const;
140
+ inline double& TvecPrior(const size_t idx);
141
+ inline bool HasTvecPrior() const;
142
+ inline void SetTvecPrior(const Eigen::Vector3d& tvec);
143
+
144
+ // Access the coordinates of image points.
145
+ inline const class Point2D& Point2D(const point2D_t point2D_idx) const;
146
+ inline class Point2D& Point2D(const point2D_t point2D_idx);
147
+ inline const std::vector<class Point2D>& Points2D() const;
148
+ void SetPoints2D(const std::vector<Eigen::Vector2d>& points);
149
+ void SetPoints2D(const std::vector<class Point2D>& points);
150
+
151
+ // Set the point as triangulated, i.e. it is part of a 3D point track.
152
+ void SetPoint3DForPoint2D(const point2D_t point2D_idx,
153
+ const point3D_t point3D_id);
154
+
155
+ // Set the point as not triangulated, i.e. it is not part of a 3D point track.
156
+ void ResetPoint3DForPoint2D(const point2D_t point2D_idx);
157
+
158
+ // Check whether an image point has a correspondence to an image point in
159
+ // another image that has a 3D point.
160
+ inline bool IsPoint3DVisible(const point2D_t point2D_idx) const;
161
+
162
+ // Check whether one of the image points is part of the 3D point track.
163
+ bool HasPoint3D(const point3D_t point3D_id) const;
164
+
165
+ // Indicate that another image has a point that is triangulated and has
166
+ // a correspondence to this image point. Note that this must only be called
167
+ // after calling `SetUp`.
168
+ void IncrementCorrespondenceHasPoint3D(const point2D_t point2D_idx);
169
+
170
+ // Indicate that another image has a point that is not triangulated any more
171
+ // and has a correspondence to this image point. This assumes that
172
+ // `IncrementCorrespondenceHasPoint3D` was called for the same image point
173
+ // and correspondence before. Note that this must only be called
174
+ // after calling `SetUp`.
175
+ void DecrementCorrespondenceHasPoint3D(const point2D_t point2D_idx);
176
+
177
+ // Normalize the quaternion vector.
178
+ void NormalizeQvec();
179
+
180
+ // Compose the projection matrix from world to image space.
181
+ Eigen::Matrix3x4d ProjectionMatrix() const;
182
+
183
+ // Compose the inverse projection matrix from image to world space
184
+ Eigen::Matrix3x4d InverseProjectionMatrix() const;
185
+
186
+ // Compose rotation matrix from quaternion vector.
187
+ Eigen::Matrix3d RotationMatrix() const;
188
+
189
+ // Extract the projection center in world space.
190
+ Eigen::Vector3d ProjectionCenter() const;
191
+
192
+ // Extract the viewing direction of the image.
193
+ Eigen::Vector3d ViewingDirection() const;
194
+
195
+ // The number of levels in the 3D point multi-resolution visibility pyramid.
196
+ static const int kNumPoint3DVisibilityPyramidLevels;
197
+
198
+ private:
199
+ // Identifier of the image, if not specified `kInvalidImageId`.
200
+ image_t image_id_;
201
+
202
+ // The name of the image, i.e. the relative path.
203
+ std::string name_;
204
+
205
+ // The identifier of the associated camera. Note that multiple images might
206
+ // share the same camera. If not specified `kInvalidCameraId`.
207
+ camera_t camera_id_;
208
+
209
+ // Whether the image is successfully registered in the reconstruction.
210
+ bool registered_;
211
+
212
+ // The number of 3D points the image observes, i.e. the sum of its `points2D`
213
+ // where `point3D_id != kInvalidPoint3DId`.
214
+ point2D_t num_points3D_;
215
+
216
+ // The number of image points that have at least one correspondence to
217
+ // another image.
218
+ point2D_t num_observations_;
219
+
220
+ // The sum of correspondences per image point.
221
+ point2D_t num_correspondences_;
222
+
223
+ // The number of 2D points, which have at least one corresponding 2D point in
224
+ // another image that is part of a 3D point track, i.e. the sum of `points2D`
225
+ // where `num_tris > 0`.
226
+ point2D_t num_visible_points3D_;
227
+
228
+ // The pose of the image, defined as the transformation from world to image.
229
+ Eigen::Vector4d qvec_;
230
+ Eigen::Vector3d tvec_;
231
+
232
+ // The pose prior of the image, e.g. extracted from EXIF tags.
233
+ Eigen::Vector4d qvec_prior_;
234
+ Eigen::Vector3d tvec_prior_;
235
+
236
+ // All image points, including points that are not part of a 3D point track.
237
+ std::vector<class Point2D> points2D_;
238
+
239
+ // Per image point, the number of correspondences that have a 3D point.
240
+ std::vector<point2D_t> num_correspondences_have_point3D_;
241
+
242
+ // Data structure to compute the distribution of triangulated correspondences
243
+ // in the image. Note that this structure is only usable after `SetUp`.
244
+ VisibilityPyramid point3D_visibility_pyramid_;
245
+ };
246
+
247
+ ////////////////////////////////////////////////////////////////////////////////
248
+ // Implementation
249
+ ////////////////////////////////////////////////////////////////////////////////
250
+
251
+ image_t Image::ImageId() const { return image_id_; }
252
+
253
+ void Image::SetImageId(const image_t image_id) { image_id_ = image_id; }
254
+
255
+ const std::string& Image::Name() const { return name_; }
256
+
257
+ std::string& Image::Name() { return name_; }
258
+
259
+ void Image::SetName(const std::string& name) { name_ = name; }
260
+
261
+ inline camera_t Image::CameraId() const { return camera_id_; }
262
+
263
+ inline void Image::SetCameraId(const camera_t camera_id) {
264
+ CHECK_NE(camera_id, kInvalidCameraId);
265
+ camera_id_ = camera_id;
266
+ }
267
+
268
+ inline bool Image::HasCamera() const { return camera_id_ != kInvalidCameraId; }
269
+
270
+ bool Image::IsRegistered() const { return registered_; }
271
+
272
+ void Image::SetRegistered(const bool registered) { registered_ = registered; }
273
+
274
+ point2D_t Image::NumPoints2D() const {
275
+ return static_cast<point2D_t>(points2D_.size());
276
+ }
277
+
278
+ point2D_t Image::NumPoints3D() const { return num_points3D_; }
279
+
280
+ point2D_t Image::NumObservations() const { return num_observations_; }
281
+
282
+ void Image::SetNumObservations(const point2D_t num_observations) {
283
+ num_observations_ = num_observations;
284
+ }
285
+
286
+ point2D_t Image::NumCorrespondences() const { return num_correspondences_; }
287
+
288
+ void Image::SetNumCorrespondences(const point2D_t num_correspondences) {
289
+ num_correspondences_ = num_correspondences;
290
+ }
291
+
292
+ point2D_t Image::NumVisiblePoints3D() const { return num_visible_points3D_; }
293
+
294
+ size_t Image::Point3DVisibilityScore() const {
295
+ return point3D_visibility_pyramid_.Score();
296
+ }
297
+
298
+ const Eigen::Vector4d& Image::Qvec() const { return qvec_; }
299
+
300
+ Eigen::Vector4d& Image::Qvec() { return qvec_; }
301
+
302
+ inline double Image::Qvec(const size_t idx) const { return qvec_(idx); }
303
+
304
+ inline double& Image::Qvec(const size_t idx) { return qvec_(idx); }
305
+
306
+ void Image::SetQvec(const Eigen::Vector4d& qvec) { qvec_ = qvec; }
307
+
308
+ const Eigen::Vector4d& Image::QvecPrior() const { return qvec_prior_; }
309
+
310
+ Eigen::Vector4d& Image::QvecPrior() { return qvec_prior_; }
311
+
312
+ inline double Image::QvecPrior(const size_t idx) const {
313
+ return qvec_prior_(idx);
314
+ }
315
+
316
+ inline double& Image::QvecPrior(const size_t idx) { return qvec_prior_(idx); }
317
+
318
+ inline bool Image::HasQvecPrior() const { return !IsNaN(qvec_prior_.sum()); }
319
+
320
+ void Image::SetQvecPrior(const Eigen::Vector4d& qvec) { qvec_prior_ = qvec; }
321
+
322
+ const Eigen::Vector3d& Image::Tvec() const { return tvec_; }
323
+
324
+ Eigen::Vector3d& Image::Tvec() { return tvec_; }
325
+
326
+ inline double Image::Tvec(const size_t idx) const { return tvec_(idx); }
327
+
328
+ inline double& Image::Tvec(const size_t idx) { return tvec_(idx); }
329
+
330
+ void Image::SetTvec(const Eigen::Vector3d& tvec) { tvec_ = tvec; }
331
+
332
+ const Eigen::Vector3d& Image::TvecPrior() const { return tvec_prior_; }
333
+
334
+ Eigen::Vector3d& Image::TvecPrior() { return tvec_prior_; }
335
+
336
+ inline double Image::TvecPrior(const size_t idx) const {
337
+ return tvec_prior_(idx);
338
+ }
339
+
340
+ inline double& Image::TvecPrior(const size_t idx) { return tvec_prior_(idx); }
341
+
342
+ inline bool Image::HasTvecPrior() const { return !IsNaN(tvec_prior_.sum()); }
343
+
344
+ void Image::SetTvecPrior(const Eigen::Vector3d& tvec) { tvec_prior_ = tvec; }
345
+
346
+ const class Point2D& Image::Point2D(const point2D_t point2D_idx) const {
347
+ return points2D_.at(point2D_idx);
348
+ }
349
+
350
+ class Point2D& Image::Point2D(const point2D_t point2D_idx) {
351
+ return points2D_.at(point2D_idx);
352
+ }
353
+
354
+ const std::vector<class Point2D>& Image::Points2D() const { return points2D_; }
355
+
356
+ bool Image::IsPoint3DVisible(const point2D_t point2D_idx) const {
357
+ return num_correspondences_have_point3D_.at(point2D_idx) > 0;
358
+ }
359
+
360
+ } // namespace colmap
361
+
362
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::Image)
363
+
364
+ #endif // COLMAP_SRC_BASE_IMAGE_H_
colmap/include/colmap/base/image_reader.h ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_IMAGE_READER_H_
33
+ #define COLMAP_SRC_BASE_IMAGE_READER_H_
34
+
35
+ #include <unordered_set>
36
+
37
+ #include "base/database.h"
38
+ #include "util/bitmap.h"
39
+ #include "util/threading.h"
40
+
41
+ namespace colmap {
42
+
43
+ struct ImageReaderOptions {
44
+ // Path to database in which to store the extracted data.
45
+ std::string database_path = "";
46
+
47
+ // Root path to folder which contains the images.
48
+ std::string image_path = "";
49
+
50
+ // Optional root path to folder which contains image masks. For a given image,
51
+ // the corresponding mask must have the same sub-path below this root as the
52
+ // image has below image_path. The filename must be equal, aside from the
53
+ // added extension .png. For example, for an image image_path/abc/012.jpg, the
54
+ // mask would be mask_path/abc/012.jpg.png. No features will be extracted in
55
+ // regions where the mask image is black (pixel intensity value 0 in
56
+ // grayscale).
57
+ std::string mask_path = "";
58
+
59
+ // Optional list of images to read. The list must contain the relative path
60
+ // of the images with respect to the image_path.
61
+ std::vector<std::string> image_list;
62
+
63
+ // Name of the camera model.
64
+ std::string camera_model = "SIMPLE_RADIAL";
65
+
66
+ // Whether to use the same camera for all images.
67
+ bool single_camera = false;
68
+
69
+ // Whether to use the same camera for all images in the same sub-folder.
70
+ bool single_camera_per_folder = false;
71
+
72
+ // Whether to use a different camera for each image.
73
+ bool single_camera_per_image = false;
74
+
75
+ // Whether to explicitly use an existing camera for all images. Note that in
76
+ // this case the specified camera model and parameters are ignored.
77
+ int existing_camera_id = kInvalidCameraId;
78
+
79
+ // Manual specification of camera parameters. If empty, camera parameters
80
+ // will be extracted from EXIF, i.e. principal point and focal length.
81
+ std::string camera_params = "";
82
+
83
+ // If camera parameters are not specified manually and the image does not
84
+ // have focal length EXIF information, the focal length is set to the
85
+ // value `default_focal_length_factor * max(width, height)`.
86
+ double default_focal_length_factor = 1.2;
87
+
88
+ // Optional path to an image file specifying a mask for all images. No
89
+ // features will be extracted in regions where the mask is black (pixel
90
+ // intensity value 0 in grayscale).
91
+ std::string camera_mask_path = "";
92
+
93
+ bool Check() const;
94
+ };
95
+
96
+ // Recursively iterate over the images in a directory. Skips an image if it
97
+ // already exists in the database. Extracts the camera intrinsics from EXIF and
98
+ // writes the camera information to the database.
99
+ class ImageReader {
100
+ public:
101
+ enum class Status {
102
+ FAILURE,
103
+ SUCCESS,
104
+ IMAGE_EXISTS,
105
+ BITMAP_ERROR,
106
+ CAMERA_SINGLE_DIM_ERROR,
107
+ CAMERA_EXIST_DIM_ERROR,
108
+ CAMERA_PARAM_ERROR
109
+ };
110
+
111
+ ImageReader(const ImageReaderOptions& options, Database* database);
112
+
113
+ Status Next(Camera* camera, Image* image, Bitmap* bitmap, Bitmap* mask);
114
+ size_t NextIndex() const;
115
+ size_t NumImages() const;
116
+
117
+ private:
118
+ // Image reader options.
119
+ ImageReaderOptions options_;
120
+ Database* database_;
121
+ // Index of previously processed image.
122
+ size_t image_index_;
123
+ // Previously processed camera.
124
+ Camera prev_camera_;
125
+ std::unordered_map<std::string, camera_t> camera_model_to_id_;
126
+ // Names of image sub-folders.
127
+ std::string prev_image_folder_;
128
+ std::unordered_set<std::string> image_folders_;
129
+ };
130
+
131
+ } // namespace colmap
132
+
133
+ #endif // COLMAP_SRC_BASE_IMAGE_READER_H_
colmap/include/colmap/base/line.h ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_LINE_H_
33
+ #define COLMAP_SRC_BASE_LINE_H_
34
+
35
+ #include <Eigen/Core>
36
+
37
+ #include "util/alignment.h"
38
+ #include "util/bitmap.h"
39
+
40
+ namespace colmap {
41
+
42
+ struct LineSegment {
43
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
44
+ Eigen::Vector2d start;
45
+ Eigen::Vector2d end;
46
+ };
47
+
48
+ enum class LineSegmentOrientation {
49
+ HORIZONTAL = 1,
50
+ VERTICAL = -1,
51
+ UNDEFINED = 0,
52
+ };
53
+
54
+ // Detect line segments in the given bitmap image.
55
+ std::vector<LineSegment> DetectLineSegments(const Bitmap& bitmap,
56
+ const double min_length = 3);
57
+
58
+ // Classify line segments into horizontal/vertical.
59
+ std::vector<LineSegmentOrientation> ClassifyLineSegmentOrientations(
60
+ const std::vector<LineSegment>& segments, const double tolerance = 0.25);
61
+
62
+ } // namespace colmap
63
+
64
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::LineSegment)
65
+
66
+ #endif // COLMAP_SRC_BASE_LINE_H_
colmap/include/colmap/base/point2d.h ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_POINT2D_H_
33
+ #define COLMAP_SRC_BASE_POINT2D_H_
34
+
35
+ #include <Eigen/Core>
36
+
37
+ #include "util/alignment.h"
38
+ #include "util/types.h"
39
+
40
+ namespace colmap {
41
+
42
+ // 2D point class corresponds to a feature in an image. It may or may not have a
43
+ // corresponding 3D point if it is part of a triangulated track.
44
+ class Point2D {
45
+ public:
46
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
47
+
48
+ Point2D();
49
+
50
+ // The coordinate in image space in pixels.
51
+ inline const Eigen::Vector2d& XY() const;
52
+ inline Eigen::Vector2d& XY();
53
+ inline double X() const;
54
+ inline double Y() const;
55
+ inline void SetXY(const Eigen::Vector2d& xy);
56
+
57
+ // The identifier of the observed 3D point. If the image point does not
58
+ // observe a 3D point, the identifier is `kInvalidPoint3Did`.
59
+ inline point3D_t Point3DId() const;
60
+ inline bool HasPoint3D() const;
61
+ inline void SetPoint3DId(const point3D_t point3D_id);
62
+
63
+ private:
64
+ // The image coordinates in pixels, starting at upper left corner with 0.
65
+ Eigen::Vector2d xy_;
66
+
67
+ // The identifier of the 3D point. If the 2D point is not part of a 3D point
68
+ // track the identifier is `kInvalidPoint3DId` and `HasPoint3D() = false`.
69
+ point3D_t point3D_id_;
70
+ };
71
+
72
+ ////////////////////////////////////////////////////////////////////////////////
73
+ // Implementation
74
+ ////////////////////////////////////////////////////////////////////////////////
75
+
76
+ const Eigen::Vector2d& Point2D::XY() const { return xy_; }
77
+
78
+ Eigen::Vector2d& Point2D::XY() { return xy_; }
79
+
80
+ double Point2D::X() const { return xy_.x(); }
81
+
82
+ double Point2D::Y() const { return xy_.y(); }
83
+
84
+ void Point2D::SetXY(const Eigen::Vector2d& xy) { xy_ = xy; }
85
+
86
+ point3D_t Point2D::Point3DId() const { return point3D_id_; }
87
+
88
+ bool Point2D::HasPoint3D() const { return point3D_id_ != kInvalidPoint3DId; }
89
+
90
+ void Point2D::SetPoint3DId(const point3D_t point3D_id) {
91
+ point3D_id_ = point3D_id;
92
+ }
93
+
94
+ } // namespace colmap
95
+
96
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::Point2D)
97
+
98
+ #endif // COLMAP_SRC_BASE_POINT2D_H_
colmap/include/colmap/base/point3d.h ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_POINT3D_H_
33
+ #define COLMAP_SRC_BASE_POINT3D_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "base/track.h"
40
+ #include "util/logging.h"
41
+ #include "util/types.h"
42
+
43
+ namespace colmap {
44
+
45
+ // 3D point class that holds information about triangulated 2D points.
46
+ class Point3D {
47
+ public:
48
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
49
+
50
+ Point3D();
51
+
52
+ // The point coordinate in world space.
53
+ inline const Eigen::Vector3d& XYZ() const;
54
+ inline Eigen::Vector3d& XYZ();
55
+ inline double XYZ(const size_t idx) const;
56
+ inline double& XYZ(const size_t idx);
57
+ inline double X() const;
58
+ inline double Y() const;
59
+ inline double Z() const;
60
+ inline void SetXYZ(const Eigen::Vector3d& xyz);
61
+
62
+ // The RGB color of the point.
63
+ inline const Eigen::Vector3ub& Color() const;
64
+ inline Eigen::Vector3ub& Color();
65
+ inline uint8_t Color(const size_t idx) const;
66
+ inline uint8_t& Color(const size_t idx);
67
+ inline void SetColor(const Eigen::Vector3ub& color);
68
+
69
+ // The mean reprojection error in image space.
70
+ inline double Error() const;
71
+ inline bool HasError() const;
72
+ inline void SetError(const double error);
73
+
74
+ inline const class Track& Track() const;
75
+ inline class Track& Track();
76
+ inline void SetTrack(class Track track);
77
+
78
+ private:
79
+ // The 3D position of the point.
80
+ Eigen::Vector3d xyz_;
81
+
82
+ // The color of the point in the range [0, 255].
83
+ Eigen::Vector3ub color_;
84
+
85
+ // The mean reprojection error in pixels.
86
+ double error_;
87
+
88
+ // The track of the point as a list of image observations.
89
+ class Track track_;
90
+ };
91
+
92
+ ////////////////////////////////////////////////////////////////////////////////
93
+ // Implementation
94
+ ////////////////////////////////////////////////////////////////////////////////
95
+
96
+ const Eigen::Vector3d& Point3D::XYZ() const { return xyz_; }
97
+
98
+ Eigen::Vector3d& Point3D::XYZ() { return xyz_; }
99
+
100
+ double Point3D::XYZ(const size_t idx) const { return xyz_(idx); }
101
+
102
+ double& Point3D::XYZ(const size_t idx) { return xyz_(idx); }
103
+
104
+ double Point3D::X() const { return xyz_.x(); }
105
+
106
+ double Point3D::Y() const { return xyz_.y(); }
107
+
108
+ double Point3D::Z() const { return xyz_.z(); }
109
+
110
+ void Point3D::SetXYZ(const Eigen::Vector3d& xyz) { xyz_ = xyz; }
111
+
112
+ const Eigen::Vector3ub& Point3D::Color() const { return color_; }
113
+
114
+ Eigen::Vector3ub& Point3D::Color() { return color_; }
115
+
116
+ uint8_t Point3D::Color(const size_t idx) const { return color_(idx); }
117
+
118
+ uint8_t& Point3D::Color(const size_t idx) { return color_(idx); }
119
+
120
+ void Point3D::SetColor(const Eigen::Vector3ub& color) { color_ = color; }
121
+
122
+ double Point3D::Error() const { return error_; }
123
+
124
+ bool Point3D::HasError() const { return error_ != -1.0; }
125
+
126
+ void Point3D::SetError(const double error) { error_ = error; }
127
+
128
+ const class Track& Point3D::Track() const { return track_; }
129
+
130
+ class Track& Point3D::Track() {
131
+ return track_;
132
+ }
133
+
134
+ void Point3D::SetTrack(class Track track) { track_ = std::move(track); }
135
+
136
+ } // namespace colmap
137
+
138
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::Point3D)
139
+
140
+ #endif // COLMAP_SRC_BASE_POINT3D_H_
colmap/include/colmap/base/polynomial.h ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_POLYNOMIAL_H_
33
+ #define COLMAP_SRC_BASE_POLYNOMIAL_H_
34
+
35
+ #include <Eigen/Core>
36
+
37
+ namespace colmap {
38
+
39
+ // All polynomials are assumed to be the form:
40
+ //
41
+ // sum_{i=0}^N polynomial(i) x^{N-i}.
42
+ //
43
+ // and are given by a vector of coefficients of size N + 1.
44
+ //
45
+ // The implementation is based on COLMAP's old polynomial functionality and is
46
+ // inspired by Ceres-Solver's/Theia's implementation to support complex
47
+ // polynomials. The companion matrix implementation is based on NumPy.
48
+
49
+ // Evaluate the polynomial for the given coefficients at x using the Horner
50
+ // scheme. This function is templated such that the polynomial may be evaluated
51
+ // at real and/or imaginary points.
52
+ template <typename T>
53
+ T EvaluatePolynomial(const Eigen::VectorXd& coeffs, const T& x);
54
+
55
+ // Find the root of polynomials of the form: a * x + b = 0.
56
+ // The real and/or imaginary variable may be NULL if the output is not needed.
57
+ bool FindLinearPolynomialRoots(const Eigen::VectorXd& coeffs,
58
+ Eigen::VectorXd* real, Eigen::VectorXd* imag);
59
+
60
+ // Find the roots of polynomials of the form: a * x^2 + b * x + c = 0.
61
+ // The real and/or imaginary variable may be NULL if the output is not needed.
62
+ bool FindQuadraticPolynomialRoots(const Eigen::VectorXd& coeffs,
63
+ Eigen::VectorXd* real, Eigen::VectorXd* imag);
64
+
65
+ // Find the roots of a polynomial using the Durand-Kerner method, based on:
66
+ //
67
+ // https://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method
68
+ //
69
+ // The Durand-Kerner is comparatively fast but often unstable/inaccurate.
70
+ // The real and/or imaginary variable may be NULL if the output is not needed.
71
+ bool FindPolynomialRootsDurandKerner(const Eigen::VectorXd& coeffs,
72
+ Eigen::VectorXd* real,
73
+ Eigen::VectorXd* imag);
74
+
75
+ // Find the roots of a polynomial using the companion matrix method, based on:
76
+ //
77
+ // R. A. Horn & C. R. Johnson, Matrix Analysis. Cambridge,
78
+ // UK: Cambridge University Press, 1999, pp. 146-7.
79
+ //
80
+ // Compared to Durand-Kerner, this method is slower but more stable/accurate.
81
+ // The real and/or imaginary variable may be NULL if the output is not needed.
82
+ bool FindPolynomialRootsCompanionMatrix(const Eigen::VectorXd& coeffs,
83
+ Eigen::VectorXd* real,
84
+ Eigen::VectorXd* imag);
85
+
86
+ ////////////////////////////////////////////////////////////////////////////////
87
+ // Implementation
88
+ ////////////////////////////////////////////////////////////////////////////////
89
+
90
+ template <typename T>
91
+ T EvaluatePolynomial(const Eigen::VectorXd& coeffs, const T& x) {
92
+ T value = 0.0;
93
+ for (Eigen::VectorXd::Index i = 0; i < coeffs.size(); ++i) {
94
+ value = value * x + coeffs(i);
95
+ }
96
+ return value;
97
+ }
98
+
99
+ } // namespace colmap
100
+
101
+ #endif // COLMAP_SRC_BASE_POLYNOMIAL_H_
colmap/include/colmap/base/pose.h ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_POSE_H_
33
+ #define COLMAP_SRC_BASE_POSE_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ // Compose the skew symmetric cross product matrix from a vector.
45
+ Eigen::Matrix3d CrossProductMatrix(const Eigen::Vector3d& vector);
46
+
47
+ // Convert 3D rotation matrix to Euler angles.
48
+ //
49
+ // The convention `R = Rx * Ry * Rz` is used,
50
+ // using a right-handed coordinate system.
51
+ //
52
+ // @param R 3x3 rotation matrix.
53
+ // @param rx, ry, rz Euler angles in radians.
54
+ void RotationMatrixToEulerAngles(const Eigen::Matrix3d& R, double* rx,
55
+ double* ry, double* rz);
56
+
57
+ // Convert Euler angles to 3D rotation matrix.
58
+ //
59
+ // The convention `R = Rz * Ry * Rx` is used,
60
+ // using a right-handed coordinate system.
61
+ //
62
+ // @param rx, ry, rz Euler angles in radians.
63
+ //
64
+ // @return 3x3 rotation matrix.
65
+ Eigen::Matrix3d EulerAnglesToRotationMatrix(const double rx, const double ry,
66
+ const double rz);
67
+
68
+ // Convert 3D rotation matrix to Quaternion representation.
69
+ //
70
+ // @param rot_mat 3x3 rotation matrix.
71
+ //
72
+ // @return Unit Quaternion rotation coefficients (w, x, y, z).
73
+ Eigen::Vector4d RotationMatrixToQuaternion(const Eigen::Matrix3d& rot_mat);
74
+
75
+ // Convert Quaternion representation to 3D rotation matrix.
76
+ //
77
+ // @param qvec Unit Quaternion rotation coefficients (w, x, y, z).
78
+ //
79
+ // @return 3x3 rotation matrix.
80
+ Eigen::Matrix3d QuaternionToRotationMatrix(const Eigen::Vector4d& qvec);
81
+
82
+ // Compose the Quaternion vector corresponding to a identity transformation.
83
+ inline Eigen::Vector4d ComposeIdentityQuaternion();
84
+
85
+ // Normalize Quaternion vector.
86
+ //
87
+ // @param qvec Quaternion rotation coefficients (w, x, y, z).
88
+ //
89
+ // @return Unit Quaternion rotation coefficients (w, x, y, z).
90
+ Eigen::Vector4d NormalizeQuaternion(const Eigen::Vector4d& qvec);
91
+
92
+ // Invert Quaternion vector to return Quaternion of inverse rotation.
93
+ //
94
+ // @param qvec Quaternion rotation coefficients (w, x, y, z).
95
+ //
96
+ // @return Inverse Quaternion rotation coefficients (w, x, y, z).
97
+ Eigen::Vector4d InvertQuaternion(const Eigen::Vector4d& qvec);
98
+
99
+ // Concatenate Quaternion rotations such that the rotation of `qvec1` is applied
100
+ // before the rotation of `qvec2`.
101
+ //
102
+ // @param qvec1 Quaternion rotation coefficients (w, x, y, z).
103
+ // @param qvec2 Quaternion rotation coefficients (w, x, y, z).
104
+ //
105
+ // @return Concatenated Quaternion coefficients (w, x, y, z).
106
+ Eigen::Vector4d ConcatenateQuaternions(const Eigen::Vector4d& qvec1,
107
+ const Eigen::Vector4d& qvec2);
108
+
109
+ // Transform point by quaternion rotation.
110
+ //
111
+ // @param qvec Quaternion rotation coefficients (w, x, y, z).
112
+ // @param point Point to rotate.
113
+ //
114
+ // @return Rotated point.
115
+ Eigen::Vector3d QuaternionRotatePoint(const Eigen::Vector4d& qvec,
116
+ const Eigen::Vector3d& point);
117
+
118
+ // Compute the weighted average of multiple Quaternions according to:
119
+ //
120
+ // Markley, F. Landis, et al. "Averaging quaternions."
121
+ // Journal of Guidance, Control, and Dynamics 30.4 (2007): 1193-1197.
122
+ //
123
+ // @param qvecs The Quaternions to be averaged.
124
+ // @param weights Non-negative weights.
125
+ //
126
+ // @return The average Quaternion.
127
+ Eigen::Vector4d AverageQuaternions(const std::vector<Eigen::Vector4d>& qvecs,
128
+ const std::vector<double>& weights);
129
+
130
+ // Compose rotation matrix that rotates unit vector 1 to unit vector 2.
131
+ // Note that when vector 1 points into the opposite direction of vector 2,
132
+ // the function returns an identity rotation.
133
+ Eigen::Matrix3d RotationFromUnitVectors(const Eigen::Vector3d& vec1,
134
+ const Eigen::Vector3d& vec2);
135
+
136
+ // Extract camera projection center from projection matrix, i.e. the projection
137
+ // center in world coordinates `-R^T t`.
138
+ Eigen::Vector3d ProjectionCenterFromMatrix(
139
+ const Eigen::Matrix3x4d& proj_matrix);
140
+
141
+ // Extract camera projection center from projection parameters.
142
+ //
143
+ // @param qvec Unit Quaternion rotation coefficients (w, x, y, z).
144
+ // @param tvec 3x1 translation vector.
145
+ //
146
+ // @return 3x1 camera projection center.
147
+ Eigen::Vector3d ProjectionCenterFromPose(const Eigen::Vector4d& qvec,
148
+ const Eigen::Vector3d& tvec);
149
+
150
+ // Compute the relative transformation from pose 1 to 2.
151
+ //
152
+ // @param qvec1, tvec1 First camera pose.
153
+ // @param qvec2, tvec2 Second camera pose.
154
+ // @param qvec12, tvec12 Relative pose.
155
+ void ComputeRelativePose(const Eigen::Vector4d& qvec1,
156
+ const Eigen::Vector3d& tvec1,
157
+ const Eigen::Vector4d& qvec2,
158
+ const Eigen::Vector3d& tvec2, Eigen::Vector4d* qvec12,
159
+ Eigen::Vector3d* tvec12);
160
+
161
+ // Concatenate the transformations of the two poses.
162
+ //
163
+ // @param qvec1, tvec1 First camera pose.
164
+ // @param qvec2, tvec2 Second camera pose.
165
+ // @param qvec12, tvec12 Concatenated pose.
166
+ void ConcatenatePoses(const Eigen::Vector4d& qvec1,
167
+ const Eigen::Vector3d& tvec1,
168
+ const Eigen::Vector4d& qvec2,
169
+ const Eigen::Vector3d& tvec2, Eigen::Vector4d* qvec12,
170
+ Eigen::Vector3d* tvec12);
171
+
172
+ // Invert transformation of the pose.
173
+ // @param qvec, tvec Input camera pose.
174
+ // @param inv_qvec, inv_tvec Inverse camera pose.
175
+ void InvertPose(const Eigen::Vector4d& qvec, const Eigen::Vector3d& tvec,
176
+ Eigen::Vector4d* inv_qvec, Eigen::Vector3d* inv_tvec);
177
+
178
+ // Linearly interpolate camera pose.
179
+ //
180
+ // @param qvec1, tvec1 Camera pose at t0 = 0.
181
+ // @param qvec2, tvec2 Camera pose at t1 = 1.
182
+ // @param t Interpolation time.
183
+ // @param qveci, tveci Camera pose at time t.
184
+ void InterpolatePose(const Eigen::Vector4d& qvec1, const Eigen::Vector3d& tvec1,
185
+ const Eigen::Vector4d& qvec2, const Eigen::Vector3d& tvec2,
186
+ const double t, Eigen::Vector4d* qveci,
187
+ Eigen::Vector3d* tveci);
188
+
189
+ // Calculate baseline vector from first to second pose.
190
+ //
191
+ // The given rotation and orientation is expected as the
192
+ // world to camera transformation.
193
+ //
194
+ // @param qvec1 Unit Quaternion rotation coefficients (w, x, y, z).
195
+ // @param tvec1 3x1 translation vector.
196
+ // @param qvec2 Unit Quaternion rotation coefficients (w, x, y, z).
197
+ // @param tvec2 3x1 translation vector.
198
+ //
199
+ // @return Baseline vector from 1 to 2.
200
+ Eigen::Vector3d CalculateBaseline(const Eigen::Vector4d& qvec1,
201
+ const Eigen::Vector3d& tvec1,
202
+ const Eigen::Vector4d& qvec2,
203
+ const Eigen::Vector3d& tvec2);
204
+
205
+ // Perform cheirality constraint test, i.e., determine which of the triangulated
206
+ // correspondences lie in front of of both cameras. The first camera has the
207
+ // projection matrix P1 = [I | 0] and the second camera has the projection
208
+ // matrix P2 = [R | t].
209
+ //
210
+ // @param R 3x3 rotation matrix of second projection matrix.
211
+ // @param t 3x1 translation vector of second projection matrix.
212
+ // @param points1 First set of corresponding points.
213
+ // @param points2 Second set of corresponding points.
214
+ // @param points3D Points that lie in front of both cameras.
215
+ bool CheckCheirality(const Eigen::Matrix3d& R, const Eigen::Vector3d& t,
216
+ const std::vector<Eigen::Vector2d>& points1,
217
+ const std::vector<Eigen::Vector2d>& points2,
218
+ std::vector<Eigen::Vector3d>* points3D);
219
+
220
+ ////////////////////////////////////////////////////////////////////////////////
221
+ // Implementation
222
+ ////////////////////////////////////////////////////////////////////////////////
223
+
224
+ Eigen::Vector4d ComposeIdentityQuaternion() {
225
+ return Eigen::Vector4d(1, 0, 0, 0);
226
+ }
227
+
228
+ } // namespace colmap
229
+
230
+ #endif // COLMAP_SRC_BASE_POSE_H_
colmap/include/colmap/base/projection.h ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_PROJECTION_H_
33
+ #define COLMAP_SRC_BASE_PROJECTION_H_
34
+
35
+ #include <limits>
36
+ #include <vector>
37
+
38
+ #include <Eigen/Core>
39
+ #include <Eigen/Geometry>
40
+
41
+ #include "base/camera.h"
42
+
43
+ namespace colmap {
44
+
45
+ // Compose projection matrix from rotation and translation components.
46
+ //
47
+ // The projection matrix transforms 3D world to image points.
48
+ //
49
+ // @param qvec Unit Quaternion rotation coefficients (w, x, y, z).
50
+ // @param tvec 3x1 translation vector.
51
+ //
52
+ // @return 3x4 projection matrix.
53
+ Eigen::Matrix3x4d ComposeProjectionMatrix(const Eigen::Vector4d& qvec,
54
+ const Eigen::Vector3d& tvec);
55
+
56
+ // Compose projection matrix from rotation matrix and translation components).
57
+ //
58
+ // The projection matrix transforms 3D world to image points.
59
+ //
60
+ // @param R 3x3 rotation matrix.
61
+ // @param t 3x1 translation vector.
62
+ //
63
+ // @return 3x4 projection matrix.
64
+ Eigen::Matrix3x4d ComposeProjectionMatrix(const Eigen::Matrix3d& R,
65
+ const Eigen::Vector3d& T);
66
+
67
+ // Invert projection matrix, defined as:
68
+ //
69
+ // P = [R | t] with R \in SO(3) and t \in R^3
70
+ //
71
+ // and the inverse projection matrix as:
72
+ //
73
+ // P' = [R^T | -R^T t]
74
+ //
75
+ // @param proj_matrix 3x4 projection matrix.
76
+ //
77
+ // @return 3x4 inverse projection matrix.
78
+ Eigen::Matrix3x4d InvertProjectionMatrix(const Eigen::Matrix3x4d& proj_matrix);
79
+
80
+ // Compute the closes rotation matrix with the closest Frobenius norm by setting
81
+ // the singular values of the given matrix to 1.
82
+ Eigen::Matrix3d ComputeClosestRotationMatrix(const Eigen::Matrix3d& matrix);
83
+
84
+ // Decompose projection matrix into intrinsic camera matrix, rotation matrix and
85
+ // translation vector. Returns false if decomposition fails. This implementation
86
+ // is inspired by the OpenCV implementation with some additional checks.
87
+ bool DecomposeProjectionMatrix(const Eigen::Matrix3x4d& proj_matrix,
88
+ Eigen::Matrix3d* K, Eigen::Matrix3d* R,
89
+ Eigen::Vector3d* T);
90
+
91
+ // Project 3D point to image.
92
+ //
93
+ // @param points3D 3D world point as 3x1 vector.
94
+ // @param proj_matrix 3x4 projection matrix.
95
+ // @param camera Camera used to project to image plane.
96
+ //
97
+ // @return Projected image point.
98
+ Eigen::Vector2d ProjectPointToImage(const Eigen::Vector3d& point3D,
99
+ const Eigen::Matrix3x4d& proj_matrix,
100
+ const Camera& camera);
101
+
102
+ // Calculate the reprojection error.
103
+ //
104
+ // The reprojection error is the Euclidean distance between the observation
105
+ // in the image and the projection of the 3D point into the image. If the
106
+ // 3D point is behind the camera, then this function returns DBL_MAX.
107
+ double CalculateSquaredReprojectionError(const Eigen::Vector2d& point2D,
108
+ const Eigen::Vector3d& point3D,
109
+ const Eigen::Vector4d& qvec,
110
+ const Eigen::Vector3d& tvec,
111
+ const Camera& camera);
112
+ double CalculateSquaredReprojectionError(const Eigen::Vector2d& point2D,
113
+ const Eigen::Vector3d& point3D,
114
+ const Eigen::Matrix3x4d& proj_matrix,
115
+ const Camera& camera);
116
+
117
+ // Calculate the angular error.
118
+ //
119
+ // The angular error is the angle between the observed viewing ray and the
120
+ // actual viewing ray from the camera center to the 3D point.
121
+ double CalculateAngularError(const Eigen::Vector2d& point2D,
122
+ const Eigen::Vector3d& point3D,
123
+ const Eigen::Vector4d& qvec,
124
+ const Eigen::Vector3d& tvec, const Camera& camera);
125
+ double CalculateAngularError(const Eigen::Vector2d& point2D,
126
+ const Eigen::Vector3d& point3D,
127
+ const Eigen::Matrix3x4d& proj_matrix,
128
+ const Camera& camera);
129
+
130
+ // Calculate angulate error using normalized image points.
131
+ //
132
+ // The angular error is the angle between the observed viewing ray and the
133
+ // actual viewing ray from the camera center to the 3D point.
134
+ double CalculateNormalizedAngularError(const Eigen::Vector2d& point2D,
135
+ const Eigen::Vector3d& point3D,
136
+ const Eigen::Vector4d& qvec,
137
+ const Eigen::Vector3d& tvec);
138
+ double CalculateNormalizedAngularError(const Eigen::Vector2d& point2D,
139
+ const Eigen::Vector3d& point3D,
140
+ const Eigen::Matrix3x4d& proj_matrix);
141
+
142
+ // Calculate depth of 3D point with respect to camera.
143
+ //
144
+ // The depth is defined as the Euclidean distance of a 3D point from the
145
+ // camera and is positive if the 3D point is in front and negative if
146
+ // behind of the camera.
147
+ //
148
+ // @param proj_matrix 3x4 projection matrix.
149
+ // @param point3D 3D point as 3x1 vector.
150
+ //
151
+ // @return Depth of 3D point.
152
+ double CalculateDepth(const Eigen::Matrix3x4d& proj_matrix,
153
+ const Eigen::Vector3d& point3D);
154
+
155
+ // Check if 3D point passes cheirality constraint,
156
+ // i.e. it lies in front of the camera and not in the image plane.
157
+ //
158
+ // @param proj_matrix 3x4 projection matrix.
159
+ // @param point3D 3D point as 3x1 vector.
160
+ //
161
+ // @return True if point lies in front of camera.
162
+ bool HasPointPositiveDepth(const Eigen::Matrix3x4d& proj_matrix,
163
+ const Eigen::Vector3d& point3D);
164
+
165
+ } // namespace colmap
166
+
167
+ #endif // COLMAP_SRC_BASE_PROJECTION_H_
colmap/include/colmap/base/reconstruction.h ADDED
@@ -0,0 +1,651 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_RECONSTRUCTION_H_
33
+ #define COLMAP_SRC_BASE_RECONSTRUCTION_H_
34
+
35
+ #include <tuple>
36
+ #include <unordered_map>
37
+ #include <unordered_set>
38
+ #include <vector>
39
+
40
+ #include <Eigen/Core>
41
+
42
+ #include "base/camera.h"
43
+ #include "base/database.h"
44
+ #include "base/image.h"
45
+ #include "base/point2d.h"
46
+ #include "base/point3d.h"
47
+ #include "base/similarity_transform.h"
48
+ #include "base/track.h"
49
+ #include "estimators/similarity_transform.h"
50
+ #include "optim/loransac.h"
51
+ #include "util/alignment.h"
52
+ #include "util/types.h"
53
+
54
+ namespace colmap {
55
+
56
+ struct PlyPoint;
57
+ struct RANSACOptions;
58
+ class DatabaseCache;
59
+ class CorrespondenceGraph;
60
+
61
+ // Reconstruction class holds all information about a single reconstructed
62
+ // model. It is used by the mapping and bundle adjustment classes and can be
63
+ // written to and read from disk.
64
+ class Reconstruction {
65
+ public:
66
+ struct ImagePairStat {
67
+ // The number of triangulated correspondences between two images.
68
+ size_t num_tri_corrs = 0;
69
+ // The number of total correspondences/matches between two images.
70
+ size_t num_total_corrs = 0;
71
+ };
72
+
73
+ Reconstruction();
74
+
75
+ // Get number of objects.
76
+ inline size_t NumCameras() const;
77
+ inline size_t NumImages() const;
78
+ inline size_t NumRegImages() const;
79
+ inline size_t NumPoints3D() const;
80
+ inline size_t NumImagePairs() const;
81
+
82
+ // Get const objects.
83
+ inline const class Camera& Camera(const camera_t camera_id) const;
84
+ inline const class Image& Image(const image_t image_id) const;
85
+ inline const class Point3D& Point3D(const point3D_t point3D_id) const;
86
+ inline const ImagePairStat& ImagePair(const image_pair_t pair_id) const;
87
+ inline ImagePairStat& ImagePair(const image_t image_id1,
88
+ const image_t image_id2);
89
+
90
+ // Get mutable objects.
91
+ inline class Camera& Camera(const camera_t camera_id);
92
+ inline class Image& Image(const image_t image_id);
93
+ inline class Point3D& Point3D(const point3D_t point3D_id);
94
+ inline ImagePairStat& ImagePair(const image_pair_t pair_id);
95
+ inline const ImagePairStat& ImagePair(const image_t image_id1,
96
+ const image_t image_id2) const;
97
+
98
+ // Get reference to all objects.
99
+ inline const EIGEN_STL_UMAP(camera_t, class Camera) & Cameras() const;
100
+ inline const EIGEN_STL_UMAP(image_t, class Image) & Images() const;
101
+ inline const std::vector<image_t>& RegImageIds() const;
102
+ inline const EIGEN_STL_UMAP(point3D_t, class Point3D) & Points3D() const;
103
+ inline const std::unordered_map<image_pair_t, ImagePairStat>& ImagePairs()
104
+ const;
105
+
106
+ // Identifiers of all 3D points.
107
+ std::unordered_set<point3D_t> Point3DIds() const;
108
+
109
+ // Check whether specific object exists.
110
+ inline bool ExistsCamera(const camera_t camera_id) const;
111
+ inline bool ExistsImage(const image_t image_id) const;
112
+ inline bool ExistsPoint3D(const point3D_t point3D_id) const;
113
+ inline bool ExistsImagePair(const image_pair_t pair_id) const;
114
+
115
+ // Load data from given `DatabaseCache`.
116
+ void Load(const DatabaseCache& database_cache);
117
+
118
+ // Setup all relevant data structures before reconstruction. Note the
119
+ // correspondence graph object must live until `TearDown` is called.
120
+ void SetUp(const CorrespondenceGraph* correspondence_graph);
121
+
122
+ // Finalize the Reconstruction after the reconstruction has finished.
123
+ //
124
+ // Once a scene has been finalized, it cannot be used for reconstruction.
125
+ //
126
+ // This removes all not yet registered images and unused cameras, in order to
127
+ // save memory.
128
+ void TearDown();
129
+
130
+ // Add new camera. There is only one camera per image, while multiple images
131
+ // might be taken by the same camera.
132
+ void AddCamera(class Camera camera);
133
+
134
+ // Add new image.
135
+ void AddImage(class Image image);
136
+
137
+ // Add new 3D object, and return its unique ID.
138
+ point3D_t AddPoint3D(
139
+ const Eigen::Vector3d& xyz, Track track,
140
+ const Eigen::Vector3ub& color = Eigen::Vector3ub::Zero());
141
+
142
+ // Add observation to existing 3D point.
143
+ void AddObservation(const point3D_t point3D_id, const TrackElement& track_el);
144
+
145
+ // Merge two 3D points and return new identifier of new 3D point.
146
+ // The location of the merged 3D point is a weighted average of the two
147
+ // original 3D point's locations according to their track lengths.
148
+ point3D_t MergePoints3D(const point3D_t point3D_id1,
149
+ const point3D_t point3D_id2);
150
+
151
+ // Delete a 3D point, and all its references in the observed images.
152
+ void DeletePoint3D(const point3D_t point3D_id);
153
+
154
+ // Delete one observation from an image and the corresponding 3D point.
155
+ // Note that this deletes the entire 3D point, if the track has two elements
156
+ // prior to calling this method.
157
+ void DeleteObservation(const image_t image_id, const point2D_t point2D_idx);
158
+
159
+ // Delete all 2D points of all images and all 3D points.
160
+ void DeleteAllPoints2DAndPoints3D();
161
+
162
+ // Register an existing image.
163
+ void RegisterImage(const image_t image_id);
164
+
165
+ // De-register an existing image, and all its references.
166
+ void DeRegisterImage(const image_t image_id);
167
+
168
+ // Check if image is registered.
169
+ inline bool IsImageRegistered(const image_t image_id) const;
170
+
171
+ // Normalize scene by scaling and translation to avoid degenerate
172
+ // visualization after bundle adjustment and to improve numerical
173
+ // stability of algorithms.
174
+ //
175
+ // Translates scene such that the mean of the camera centers or point
176
+ // locations are at the origin of the coordinate system.
177
+ //
178
+ // Scales scene such that the minimum and maximum camera centers are at the
179
+ // given `extent`, whereas `p0` and `p1` determine the minimum and
180
+ // maximum percentiles of the camera centers considered.
181
+ void Normalize(const double extent = 10.0, const double p0 = 0.1,
182
+ const double p1 = 0.9, const bool use_images = true);
183
+
184
+ // Compute the centroid of the 3D points
185
+ Eigen::Vector3d ComputeCentroid(const double p0 = 0.1,
186
+ const double p1 = 0.9) const;
187
+
188
+ // Compute the bounding box corners of the 3D points
189
+ std::pair<Eigen::Vector3d, Eigen::Vector3d> ComputeBoundingBox(
190
+ const double p0 = 0.0, const double p1 = 1.0) const;
191
+
192
+ // Apply the 3D similarity transformation to all images and points.
193
+ void Transform(const SimilarityTransform3& tform);
194
+
195
+ // Creates a cropped reconstruction using the input bounds as corner points
196
+ // of the bounding box containing the included 3D points of the new
197
+ // reconstruction. Only the cameras and images of the included points are
198
+ // registered.
199
+ Reconstruction Crop(
200
+ const std::pair<Eigen::Vector3d, Eigen::Vector3d>& bbox) const;
201
+
202
+ // Merge the given reconstruction into this reconstruction by registering the
203
+ // images registered in the given but not in this reconstruction and by
204
+ // merging the two clouds and their tracks. The coordinate frames of the two
205
+ // reconstructions are aligned using the projection centers of common
206
+ // registered images. Return true if the two reconstructions could be merged.
207
+ bool Merge(const Reconstruction& reconstruction,
208
+ const double max_reproj_error);
209
+
210
+ // Align the given reconstruction with a set of pre-defined camera positions.
211
+ // Assuming that locations[i] gives the 3D coordinates of the center
212
+ // of projection of the image with name image_names[i].
213
+ template <bool kEstimateScale = true>
214
+ bool Align(const std::vector<std::string>& image_names,
215
+ const std::vector<Eigen::Vector3d>& locations,
216
+ const int min_common_images,
217
+ SimilarityTransform3* tform = nullptr);
218
+
219
+ // Robust alignment using RANSAC.
220
+ template <bool kEstimateScale = true>
221
+ bool AlignRobust(const std::vector<std::string>& image_names,
222
+ const std::vector<Eigen::Vector3d>& locations,
223
+ const int min_common_images,
224
+ const RANSACOptions& ransac_options,
225
+ SimilarityTransform3* tform = nullptr);
226
+
227
+ // Find specific image by name. Note that this uses linear search.
228
+ const class Image* FindImageWithName(const std::string& name) const;
229
+
230
+ // Find images that are both present in this and the given reconstruction.
231
+ std::vector<image_t> FindCommonRegImageIds(
232
+ const Reconstruction& reconstruction) const;
233
+
234
+ // Update the image identifiers to match the ones in the database by matching
235
+ // the names of the images.
236
+ void TranscribeImageIdsToDatabase(const Database& database);
237
+
238
+ // Filter 3D points with large reprojection error, negative depth, or
239
+ // insufficient triangulation angle.
240
+ //
241
+ // @param max_reproj_error The maximum reprojection error.
242
+ // @param min_tri_angle The minimum triangulation angle.
243
+ // @param point3D_ids The points to be filtered.
244
+ //
245
+ // @return The number of filtered observations.
246
+ size_t FilterPoints3D(const double max_reproj_error,
247
+ const double min_tri_angle,
248
+ const std::unordered_set<point3D_t>& point3D_ids);
249
+ size_t FilterPoints3DInImages(const double max_reproj_error,
250
+ const double min_tri_angle,
251
+ const std::unordered_set<image_t>& image_ids);
252
+ size_t FilterAllPoints3D(const double max_reproj_error,
253
+ const double min_tri_angle);
254
+
255
+ // Filter observations that have negative depth.
256
+ //
257
+ // @return The number of filtered observations.
258
+ size_t FilterObservationsWithNegativeDepth();
259
+
260
+ // Filter images without observations or bogus camera parameters.
261
+ //
262
+ // @return The identifiers of the filtered images.
263
+ std::vector<image_t> FilterImages(const double min_focal_length_ratio,
264
+ const double max_focal_length_ratio,
265
+ const double max_extra_param);
266
+
267
+ // Compute statistics for scene.
268
+ size_t ComputeNumObservations() const;
269
+ double ComputeMeanTrackLength() const;
270
+ double ComputeMeanObservationsPerRegImage() const;
271
+ double ComputeMeanReprojectionError() const;
272
+
273
+ // Read data from text or binary file. Prefer binary data if it exists.
274
+ void Read(const std::string& path);
275
+ void Write(const std::string& path) const;
276
+
277
+ // Read data from binary/text file.
278
+ void ReadText(const std::string& path);
279
+ void ReadBinary(const std::string& path);
280
+
281
+ // Write data from binary/text file.
282
+ void WriteText(const std::string& path) const;
283
+ void WriteBinary(const std::string& path) const;
284
+
285
+ // Convert 3D points in reconstruction to PLY point cloud.
286
+ std::vector<PlyPoint> ConvertToPLY() const;
287
+
288
+ // Import from other data formats. Note that these import functions are
289
+ // only intended for visualization of data and usable for reconstruction.
290
+ void ImportPLY(const std::string& path);
291
+ void ImportPLY(const std::vector<PlyPoint>& ply_points);
292
+
293
+ // Export to other data formats.
294
+
295
+ // Exports in NVM format http://ccwu.me/vsfm/doc.html#nvm. Only supports
296
+ // SIMPLE_RADIAL camera model when exporting distortion parameters. When
297
+ // skip_distortion == true it supports all camera models with the caveat that
298
+ // it's using the mean focal length which will be inaccurate for camera models
299
+ // with two focal lengths and distortion.
300
+ bool ExportNVM(const std::string& path, bool skip_distortion = false) const;
301
+
302
+ // Exports in CAM format which is a simple text file that contains pose
303
+ // information and camera intrinsics for each image and exports one file per
304
+ // image; it does not include information on the 3D points. The format is as
305
+ // follows (2 lines of text with space separated numbers):
306
+ // <Tvec; 3 values> <Rotation matrix in row-major format; 9 values>
307
+ // <focal_length> <k1> <k2> 1.0 <principal point X> <principal point Y>
308
+ // Note that focal length is relative to the image max(width, height),
309
+ // and principal points x and y are relative to width and height respectively.
310
+ //
311
+ // Only supports SIMPLE_RADIAL and RADIAL camera models when exporting
312
+ // distortion parameters. When skip_distortion == true it supports all camera
313
+ // models with the caveat that it's using the mean focal length which will be
314
+ // inaccurate for camera models with two focal lengths and distortion.
315
+ bool ExportCam(const std::string& path, bool skip_distortion = false) const;
316
+
317
+ // Exports in Recon3D format which consists of three text files with the
318
+ // following format and content:
319
+ // 1) imagemap_0.txt: a list of image numeric IDs with one entry per line.
320
+ // 2) urd-images.txt: A list of images with one entry per line as:
321
+ // <image file name> <width> <height>
322
+ // 3) synth_0.out: Contains information for image poses, camera intrinsics,
323
+ // and 3D points as:
324
+ // <N; num images> <M; num points>
325
+ // <N lines of image entries>
326
+ // <M lines of point entries>
327
+ //
328
+ // Each image entry consists of 5 lines as:
329
+ // <focal length> <k1> <k2>
330
+ // <Rotation matrix; 3x3 array>
331
+ // <Tvec; 3 values>
332
+ // Note that the focal length is scaled by 1 / max(width, height)
333
+ //
334
+ // Each point entry consists of 3 lines as:
335
+ // <point x, y, z coordinates>
336
+ // <point RGB color>
337
+ // <K; num track elements> <Track Element 1> ... <Track Element K>
338
+ //
339
+ // Each track elemenet is a sequence of 5 values as:
340
+ // <image ID> <2D point ID> -1.0 <X> <Y>
341
+ // Note that the 2D point coordinates are centered around the principal
342
+ // point and scaled by 1 / max(width, height).
343
+ //
344
+ // When skip_distortion == true it supports all camera models with the
345
+ // caveat that it's using the mean focal length which will be inaccurate
346
+ // for camera models with two focal lengths and distortion.
347
+ bool ExportRecon3D(const std::string& path,
348
+ bool skip_distortion = false) const;
349
+
350
+ // Exports in Bundler format https://www.cs.cornell.edu/~snavely/bundler/.
351
+ // Supports SIMPLE_PINHOLE, PINHOLE, SIMPLE_RADIAL and RADIAL camera models
352
+ // when exporting distortion parameters. When skip_distortion == true it
353
+ // supports all camera models with the caveat that it's using the mean focal
354
+ // length which will be inaccurate for camera models with two focal lengths
355
+ // and distortion.
356
+ bool ExportBundler(const std::string& path, const std::string& list_path,
357
+ bool skip_distortion = false) const;
358
+
359
+ // Exports 3D points only in PLY format.
360
+ void ExportPLY(const std::string& path) const;
361
+
362
+ // Exports in VRML format https://en.wikipedia.org/wiki/VRML.
363
+ void ExportVRML(const std::string& images_path,
364
+ const std::string& points3D_path, const double image_scale,
365
+ const Eigen::Vector3d& image_rgb) const;
366
+
367
+ // Extract colors for 3D points of given image. Colors will be extracted
368
+ // only for 3D points which are completely black.
369
+ //
370
+ // @param image_id Identifier of the image for which to extract colors.
371
+ // @param path Absolute or relative path to root folder of image.
372
+ // The image path is determined by concatenating the
373
+ // root path and the name of the image.
374
+ //
375
+ // @return True if image could be read at given path.
376
+ bool ExtractColorsForImage(const image_t image_id, const std::string& path);
377
+
378
+ // Extract colors for all 3D points by computing the mean color of all images.
379
+ //
380
+ // @param path Absolute or relative path to root folder of image.
381
+ // The image path is determined by concatenating the
382
+ // root path and the name of the image.
383
+ void ExtractColorsForAllImages(const std::string& path);
384
+
385
+ // Create all image sub-directories in the given path.
386
+ void CreateImageDirs(const std::string& path) const;
387
+
388
+ private:
389
+ size_t FilterPoints3DWithSmallTriangulationAngle(
390
+ const double min_tri_angle,
391
+ const std::unordered_set<point3D_t>& point3D_ids);
392
+ size_t FilterPoints3DWithLargeReprojectionError(
393
+ const double max_reproj_error,
394
+ const std::unordered_set<point3D_t>& point3D_ids);
395
+
396
+ std::tuple<Eigen::Vector3d, Eigen::Vector3d, Eigen::Vector3d>
397
+ ComputeBoundsAndCentroid(const double p0, const double p1,
398
+ const bool use_images) const;
399
+
400
+ void ReadCamerasText(const std::string& path);
401
+ void ReadImagesText(const std::string& path);
402
+ void ReadPoints3DText(const std::string& path);
403
+ void ReadCamerasBinary(const std::string& path);
404
+ void ReadImagesBinary(const std::string& path);
405
+ void ReadPoints3DBinary(const std::string& path);
406
+
407
+ void WriteCamerasText(const std::string& path) const;
408
+ void WriteImagesText(const std::string& path) const;
409
+ void WritePoints3DText(const std::string& path) const;
410
+ void WriteCamerasBinary(const std::string& path) const;
411
+ void WriteImagesBinary(const std::string& path) const;
412
+ void WritePoints3DBinary(const std::string& path) const;
413
+
414
+ void SetObservationAsTriangulated(const image_t image_id,
415
+ const point2D_t point2D_idx,
416
+ const bool is_continued_point3D);
417
+ void ResetTriObservations(const image_t image_id, const point2D_t point2D_idx,
418
+ const bool is_deleted_point3D);
419
+
420
+ const CorrespondenceGraph* correspondence_graph_;
421
+
422
+ EIGEN_STL_UMAP(camera_t, class Camera) cameras_;
423
+ EIGEN_STL_UMAP(image_t, class Image) images_;
424
+ EIGEN_STL_UMAP(point3D_t, class Point3D) points3D_;
425
+
426
+ std::unordered_map<image_pair_t, ImagePairStat> image_pair_stats_;
427
+
428
+ // { image_id, ... } where `images_.at(image_id).registered == true`.
429
+ std::vector<image_t> reg_image_ids_;
430
+
431
+ // Total number of added 3D points, used to generate unique identifiers.
432
+ point3D_t num_added_points3D_;
433
+ };
434
+
435
+ ////////////////////////////////////////////////////////////////////////////////
436
+ // Implementation
437
+ ////////////////////////////////////////////////////////////////////////////////
438
+
439
+ size_t Reconstruction::NumCameras() const { return cameras_.size(); }
440
+
441
+ size_t Reconstruction::NumImages() const { return images_.size(); }
442
+
443
+ size_t Reconstruction::NumRegImages() const { return reg_image_ids_.size(); }
444
+
445
+ size_t Reconstruction::NumPoints3D() const { return points3D_.size(); }
446
+
447
+ size_t Reconstruction::NumImagePairs() const {
448
+ return image_pair_stats_.size();
449
+ }
450
+
451
+ const class Camera& Reconstruction::Camera(const camera_t camera_id) const {
452
+ return cameras_.at(camera_id);
453
+ }
454
+
455
+ const class Image& Reconstruction::Image(const image_t image_id) const {
456
+ return images_.at(image_id);
457
+ }
458
+
459
+ const class Point3D& Reconstruction::Point3D(const point3D_t point3D_id) const {
460
+ return points3D_.at(point3D_id);
461
+ }
462
+
463
+ const Reconstruction::ImagePairStat& Reconstruction::ImagePair(
464
+ const image_pair_t pair_id) const {
465
+ return image_pair_stats_.at(pair_id);
466
+ }
467
+
468
+ const Reconstruction::ImagePairStat& Reconstruction::ImagePair(
469
+ const image_t image_id1, const image_t image_id2) const {
470
+ const auto pair_id = Database::ImagePairToPairId(image_id1, image_id2);
471
+ return image_pair_stats_.at(pair_id);
472
+ }
473
+
474
+ class Camera& Reconstruction::Camera(const camera_t camera_id) {
475
+ return cameras_.at(camera_id);
476
+ }
477
+
478
+ class Image& Reconstruction::Image(const image_t image_id) {
479
+ return images_.at(image_id);
480
+ }
481
+
482
+ class Point3D& Reconstruction::Point3D(const point3D_t point3D_id) {
483
+ return points3D_.at(point3D_id);
484
+ }
485
+
486
+ Reconstruction::ImagePairStat& Reconstruction::ImagePair(
487
+ const image_pair_t pair_id) {
488
+ return image_pair_stats_.at(pair_id);
489
+ }
490
+
491
+ Reconstruction::ImagePairStat& Reconstruction::ImagePair(
492
+ const image_t image_id1, const image_t image_id2) {
493
+ const auto pair_id = Database::ImagePairToPairId(image_id1, image_id2);
494
+ return image_pair_stats_.at(pair_id);
495
+ }
496
+
497
+ const EIGEN_STL_UMAP(camera_t, Camera) & Reconstruction::Cameras() const {
498
+ return cameras_;
499
+ }
500
+
501
+ const EIGEN_STL_UMAP(image_t, class Image) & Reconstruction::Images() const {
502
+ return images_;
503
+ }
504
+
505
+ const std::vector<image_t>& Reconstruction::RegImageIds() const {
506
+ return reg_image_ids_;
507
+ }
508
+
509
+ const EIGEN_STL_UMAP(point3D_t, Point3D) & Reconstruction::Points3D() const {
510
+ return points3D_;
511
+ }
512
+
513
+ const std::unordered_map<image_pair_t, Reconstruction::ImagePairStat>&
514
+ Reconstruction::ImagePairs() const {
515
+ return image_pair_stats_;
516
+ }
517
+
518
+ bool Reconstruction::ExistsCamera(const camera_t camera_id) const {
519
+ return cameras_.find(camera_id) != cameras_.end();
520
+ }
521
+
522
+ bool Reconstruction::ExistsImage(const image_t image_id) const {
523
+ return images_.find(image_id) != images_.end();
524
+ }
525
+
526
+ bool Reconstruction::ExistsPoint3D(const point3D_t point3D_id) const {
527
+ return points3D_.find(point3D_id) != points3D_.end();
528
+ }
529
+
530
+ bool Reconstruction::ExistsImagePair(const image_pair_t pair_id) const {
531
+ return image_pair_stats_.find(pair_id) != image_pair_stats_.end();
532
+ }
533
+
534
+ bool Reconstruction::IsImageRegistered(const image_t image_id) const {
535
+ return Image(image_id).IsRegistered();
536
+ }
537
+
538
+ template <bool kEstimateScale>
539
+ bool Reconstruction::Align(const std::vector<std::string>& image_names,
540
+ const std::vector<Eigen::Vector3d>& locations,
541
+ const int min_common_images,
542
+ SimilarityTransform3* tform) {
543
+ CHECK_GE(min_common_images, 3);
544
+ CHECK_EQ(image_names.size(), locations.size());
545
+
546
+ // Find out which images are contained in the reconstruction and get the
547
+ // positions of their camera centers.
548
+ std::unordered_set<image_t> common_image_ids;
549
+ std::vector<Eigen::Vector3d> src;
550
+ std::vector<Eigen::Vector3d> dst;
551
+ for (size_t i = 0; i < image_names.size(); ++i) {
552
+ const class Image* image = FindImageWithName(image_names[i]);
553
+ if (image == nullptr) {
554
+ continue;
555
+ }
556
+
557
+ if (!IsImageRegistered(image->ImageId())) {
558
+ continue;
559
+ }
560
+
561
+ // Ignore duplicate images.
562
+ if (common_image_ids.count(image->ImageId()) > 0) {
563
+ continue;
564
+ }
565
+
566
+ common_image_ids.insert(image->ImageId());
567
+ src.push_back(image->ProjectionCenter());
568
+ dst.push_back(locations[i]);
569
+ }
570
+
571
+ // Only compute the alignment if there are enough correspondences.
572
+ if (common_image_ids.size() < static_cast<size_t>(min_common_images)) {
573
+ return false;
574
+ }
575
+
576
+ SimilarityTransform3 transform;
577
+ if (!transform.Estimate<kEstimateScale>(src, dst)) {
578
+ return false;
579
+ }
580
+
581
+ Transform(transform);
582
+
583
+ if (tform != nullptr) {
584
+ *tform = transform;
585
+ }
586
+
587
+ return true;
588
+ }
589
+
590
+ template <bool kEstimateScale>
591
+ bool Reconstruction::AlignRobust(const std::vector<std::string>& image_names,
592
+ const std::vector<Eigen::Vector3d>& locations,
593
+ const int min_common_images,
594
+ const RANSACOptions& ransac_options,
595
+ SimilarityTransform3* tform) {
596
+ CHECK_GE(min_common_images, 3);
597
+ CHECK_EQ(image_names.size(), locations.size());
598
+
599
+ // Find out which images are contained in the reconstruction and get the
600
+ // positions of their camera centers.
601
+ std::unordered_set<image_t> common_image_ids;
602
+ std::vector<Eigen::Vector3d> src;
603
+ std::vector<Eigen::Vector3d> dst;
604
+ for (size_t i = 0; i < image_names.size(); ++i) {
605
+ const class Image* image = FindImageWithName(image_names[i]);
606
+ if (image == nullptr) {
607
+ continue;
608
+ }
609
+
610
+ if (!IsImageRegistered(image->ImageId())) {
611
+ continue;
612
+ }
613
+
614
+ // Ignore duplicate images.
615
+ if (common_image_ids.count(image->ImageId()) > 0) {
616
+ continue;
617
+ }
618
+
619
+ common_image_ids.insert(image->ImageId());
620
+ src.push_back(image->ProjectionCenter());
621
+ dst.push_back(locations[i]);
622
+ }
623
+
624
+ // Only compute the alignment if there are enough correspondences.
625
+ if (common_image_ids.size() < static_cast<size_t>(min_common_images)) {
626
+ return false;
627
+ }
628
+
629
+ LORANSAC<SimilarityTransformEstimator<3, kEstimateScale>,
630
+ SimilarityTransformEstimator<3, kEstimateScale>>
631
+ ransac(ransac_options);
632
+
633
+ const auto report = ransac.Estimate(src, dst);
634
+
635
+ if (report.support.num_inliers < static_cast<size_t>(min_common_images)) {
636
+ return false;
637
+ }
638
+
639
+ SimilarityTransform3 transform = SimilarityTransform3(report.model);
640
+ Transform(transform);
641
+
642
+ if (tform != nullptr) {
643
+ *tform = transform;
644
+ }
645
+
646
+ return true;
647
+ }
648
+
649
+ } // namespace colmap
650
+
651
+ #endif // COLMAP_SRC_BASE_RECONSTRUCTION_H_
colmap/include/colmap/base/reconstruction_manager.h ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_RECONSTRUCTION_MANAGER_H_
33
+ #define COLMAP_SRC_BASE_RECONSTRUCTION_MANAGER_H_
34
+
35
+ #include "base/reconstruction.h"
36
+
37
+ namespace colmap {
38
+
39
+ class OptionManager;
40
+
41
+ class ReconstructionManager {
42
+ public:
43
+ ReconstructionManager();
44
+
45
+ // Move constructor and assignment.
46
+ ReconstructionManager(ReconstructionManager&& other);
47
+ ReconstructionManager& operator=(ReconstructionManager&& other);
48
+
49
+ // The number of reconstructions managed.
50
+ size_t Size() const;
51
+
52
+ // Get a reference to a specific reconstruction.
53
+ const Reconstruction& Get(const size_t idx) const;
54
+ Reconstruction& Get(const size_t idx);
55
+
56
+ // Add a new empty reconstruction and return its index.
57
+ size_t Add();
58
+
59
+ // Delete a specific reconstruction.
60
+ void Delete(const size_t idx);
61
+
62
+ // Delete all reconstructions.
63
+ void Clear();
64
+
65
+ // Read and add a new reconstruction and return its index.
66
+ size_t Read(const std::string& path);
67
+
68
+ // Write all managed reconstructions into sub-folders "0", "1", "2", ...
69
+ // If the option manager object is not null, the options are written
70
+ // to each respective reconstruction folder as well.
71
+ void Write(const std::string& path, const OptionManager* options) const;
72
+
73
+ private:
74
+ NON_COPYABLE(ReconstructionManager)
75
+
76
+ std::vector<std::unique_ptr<Reconstruction>> reconstructions_;
77
+ };
78
+
79
+ } // namespace colmap
80
+
81
+ #endif // COLMAP_SRC_BASE_RECONSTRUCTION_MANAGER_H_
colmap/include/colmap/base/scene_clustering.h ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_SCENE_CLUSTERING_H_
33
+ #define COLMAP_SRC_BASE_SCENE_CLUSTERING_H_
34
+
35
+ #include <list>
36
+ #include <vector>
37
+
38
+ #include "base/database.h"
39
+ #include "util/types.h"
40
+
41
+ namespace colmap {
42
+
43
+ // Scene clustering approach using normalized cuts on the scene graph. The scene
44
+ // is hierarchically partitioned into overlapping clusters until a maximum
45
+ // number of images is in a leaf node.
46
+ class SceneClustering {
47
+ public:
48
+ struct Options {
49
+ // Flag for hierarchical vs flat clustering
50
+ bool is_hierarchical = true;
51
+
52
+ // The branching factor of the hierarchical clustering.
53
+ int branching = 2;
54
+
55
+ // The number of overlapping images between child clusters.
56
+ int image_overlap = 50;
57
+
58
+ // The max related images matches to look for in a flat cluster
59
+ int num_image_matches = 20;
60
+
61
+ // The maximum number of images in a leaf node cluster, otherwise the
62
+ // cluster is further partitioned using the given branching factor. Note
63
+ // that a cluster leaf node will have at most `leaf_max_num_images +
64
+ // overlap` images to satisfy the overlap constraint.
65
+ int leaf_max_num_images = 500;
66
+
67
+ bool Check() const;
68
+ };
69
+
70
+ struct Cluster {
71
+ std::vector<image_t> image_ids;
72
+ std::vector<Cluster> child_clusters;
73
+ };
74
+
75
+ SceneClustering(const Options& options);
76
+
77
+ void Partition(const std::vector<std::pair<image_t, image_t>>& image_pairs,
78
+ const std::vector<int>& num_inliers);
79
+
80
+ const Cluster* GetRootCluster() const;
81
+ std::vector<const Cluster*> GetLeafClusters() const;
82
+
83
+ static SceneClustering Create(const Options& options,
84
+ const Database& database);
85
+
86
+ private:
87
+ void PartitionHierarchicalCluster(
88
+ const std::vector<std::pair<int, int>>& edges,
89
+ const std::vector<int>& weights, Cluster* cluster);
90
+
91
+ void PartitionFlatCluster(const std::vector<std::pair<int, int>>& edges,
92
+ const std::vector<int>& weights);
93
+
94
+ const Options options_;
95
+ std::unique_ptr<Cluster> root_cluster_;
96
+ };
97
+
98
+ } // namespace colmap
99
+
100
+ #endif // COLMAP_SRC_BASE_SCENE_CLUSTERING_H_
colmap/include/colmap/base/similarity_transform.h ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_SIMILARITY_TRANSFORM_H_
33
+ #define COLMAP_SRC_BASE_SIMILARITY_TRANSFORM_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+ #include <Eigen/Geometry>
39
+
40
+ #include "estimators/similarity_transform.h"
41
+ #include "util/alignment.h"
42
+ #include "util/types.h"
43
+
44
+ namespace colmap {
45
+
46
+ struct RANSACOptions;
47
+ class Reconstruction;
48
+
49
+ // 3D similarity transformation with 7 degrees of freedom.
50
+ class SimilarityTransform3 {
51
+ public:
52
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
53
+
54
+ SimilarityTransform3();
55
+
56
+ explicit SimilarityTransform3(const Eigen::Matrix3x4d& matrix);
57
+
58
+ explicit SimilarityTransform3(
59
+ const Eigen::Transform<double, 3, Eigen::Affine>& transform);
60
+
61
+ SimilarityTransform3(const double scale, const Eigen::Vector4d& qvec,
62
+ const Eigen::Vector3d& tvec);
63
+
64
+ void Write(const std::string& path);
65
+
66
+ template <bool kEstimateScale = true>
67
+ bool Estimate(const std::vector<Eigen::Vector3d>& src,
68
+ const std::vector<Eigen::Vector3d>& dst);
69
+
70
+ SimilarityTransform3 Inverse() const;
71
+
72
+ void TransformPoint(Eigen::Vector3d* xyz) const;
73
+ void TransformPose(Eigen::Vector4d* qvec, Eigen::Vector3d* tvec) const;
74
+
75
+ Eigen::Matrix4d Matrix() const;
76
+ double Scale() const;
77
+ Eigen::Vector4d Rotation() const;
78
+ Eigen::Vector3d Translation() const;
79
+
80
+ static SimilarityTransform3 FromFile(const std::string& path);
81
+
82
+ private:
83
+ Eigen::Transform<double, 3, Eigen::Affine> transform_;
84
+ };
85
+
86
+ // Robustly compute alignment between reconstructions by finding images that
87
+ // are registered in both reconstructions. The alignment is then estimated
88
+ // robustly inside RANSAC from corresponding projection centers. An alignment
89
+ // is verified by reprojecting common 3D point observations.
90
+ // The min_inlier_observations threshold determines how many observations
91
+ // in a common image must reproject within the given threshold.
92
+ bool ComputeAlignmentBetweenReconstructions(
93
+ const Reconstruction& src_reconstruction,
94
+ const Reconstruction& ref_reconstruction,
95
+ const double min_inlier_observations, const double max_reproj_error,
96
+ Eigen::Matrix3x4d* alignment);
97
+
98
+ ////////////////////////////////////////////////////////////////////////////////
99
+ // Implementation
100
+ ////////////////////////////////////////////////////////////////////////////////
101
+
102
+ template <bool kEstimateScale>
103
+ bool SimilarityTransform3::Estimate(const std::vector<Eigen::Vector3d>& src,
104
+ const std::vector<Eigen::Vector3d>& dst) {
105
+ const auto results =
106
+ SimilarityTransformEstimator<3, kEstimateScale>().Estimate(src, dst);
107
+ if (results.empty()) {
108
+ return false;
109
+ }
110
+
111
+ CHECK_EQ(results.size(), 1);
112
+ transform_.matrix().topLeftCorner<3, 4>() = results[0];
113
+
114
+ return true;
115
+ }
116
+
117
+ } // namespace colmap
118
+
119
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::SimilarityTransform3)
120
+
121
+ #endif // COLMAP_SRC_BASE_SIMILARITY_TRANSFORM_H_
colmap/include/colmap/base/track.h ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_TRACK_H_
33
+ #define COLMAP_SRC_BASE_TRACK_H_
34
+
35
+ #include <vector>
36
+
37
+ #include "util/logging.h"
38
+ #include "util/types.h"
39
+
40
+ namespace colmap {
41
+
42
+ // Track class stores all observations of a 3D point.
43
+ struct TrackElement {
44
+ TrackElement();
45
+ TrackElement(const image_t image_id, const point2D_t point2D_idx);
46
+ // The image in which the track element is observed.
47
+ image_t image_id;
48
+ // The point in the image that the track element is observed.
49
+ point2D_t point2D_idx;
50
+ };
51
+
52
+ class Track {
53
+ public:
54
+ Track();
55
+
56
+ // The number of track elements.
57
+ inline size_t Length() const;
58
+
59
+ // Access all elements.
60
+ inline const std::vector<TrackElement>& Elements() const;
61
+ inline std::vector<TrackElement>& Elements();
62
+ inline void SetElements(std::vector<TrackElement> elements);
63
+
64
+ // Access specific elements.
65
+ inline const TrackElement& Element(const size_t idx) const;
66
+ inline TrackElement& Element(const size_t idx);
67
+ inline void SetElement(const size_t idx, const TrackElement& element);
68
+
69
+ // Append new elements.
70
+ inline void AddElement(const TrackElement& element);
71
+ inline void AddElement(const image_t image_id, const point2D_t point2D_idx);
72
+ inline void AddElements(const std::vector<TrackElement>& elements);
73
+
74
+ // Delete existing element.
75
+ inline void DeleteElement(const size_t idx);
76
+ void DeleteElement(const image_t image_id, const point2D_t point2D_idx);
77
+
78
+ // Requests that the track capacity be at least enough to contain the
79
+ // specified number of elements.
80
+ inline void Reserve(const size_t num_elements);
81
+
82
+ // Shrink the capacity of track vector to fit its size to save memory.
83
+ inline void Compress();
84
+
85
+ private:
86
+ std::vector<TrackElement> elements_;
87
+ };
88
+
89
+ ////////////////////////////////////////////////////////////////////////////////
90
+ // Implementation
91
+ ////////////////////////////////////////////////////////////////////////////////
92
+
93
+ size_t Track::Length() const { return elements_.size(); }
94
+
95
+ const std::vector<TrackElement>& Track::Elements() const { return elements_; }
96
+
97
+ std::vector<TrackElement>& Track::Elements() { return elements_; }
98
+
99
+ void Track::SetElements(std::vector<TrackElement> elements) {
100
+ elements_ = std::move(elements);
101
+ }
102
+
103
+ // Access specific elements.
104
+ const TrackElement& Track::Element(const size_t idx) const {
105
+ return elements_.at(idx);
106
+ }
107
+
108
+ TrackElement& Track::Element(const size_t idx) { return elements_.at(idx); }
109
+
110
+ void Track::SetElement(const size_t idx, const TrackElement& element) {
111
+ elements_.at(idx) = element;
112
+ }
113
+
114
+ void Track::AddElement(const TrackElement& element) {
115
+ elements_.push_back(element);
116
+ }
117
+
118
+ void Track::AddElement(const image_t image_id, const point2D_t point2D_idx) {
119
+ elements_.emplace_back(image_id, point2D_idx);
120
+ }
121
+
122
+ void Track::AddElements(const std::vector<TrackElement>& elements) {
123
+ elements_.insert(elements_.end(), elements.begin(), elements.end());
124
+ }
125
+
126
+ void Track::DeleteElement(const size_t idx) {
127
+ CHECK_LT(idx, elements_.size());
128
+ elements_.erase(elements_.begin() + idx);
129
+ }
130
+
131
+ void Track::Reserve(const size_t num_elements) {
132
+ elements_.reserve(num_elements);
133
+ }
134
+
135
+ void Track::Compress() { elements_.shrink_to_fit(); }
136
+
137
+ } // namespace colmap
138
+
139
+ #endif // COLMAP_SRC_BASE_TRACK_H_
colmap/include/colmap/base/triangulation.h ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_TRIANGULATION_H_
33
+ #define COLMAP_SRC_BASE_TRIANGULATION_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "base/camera.h"
40
+ #include "util/alignment.h"
41
+ #include "util/math.h"
42
+ #include "util/types.h"
43
+
44
+ namespace colmap {
45
+
46
+ // Triangulate 3D point from corresponding image point observations.
47
+ //
48
+ // Implementation of the direct linear transform triangulation method in
49
+ // R. Hartley and A. Zisserman, Multiple View Geometry in Computer Vision,
50
+ // Cambridge Univ. Press, 2003.
51
+ //
52
+ // @param proj_matrix1 Projection matrix of the first image as 3x4 matrix.
53
+ // @param proj_matrix2 Projection matrix of the second image as 3x4 matrix.
54
+ // @param point1 Corresponding 2D point in first image.
55
+ // @param point2 Corresponding 2D point in second image.
56
+ //
57
+ // @return Triangulated 3D point.
58
+ Eigen::Vector3d TriangulatePoint(const Eigen::Matrix3x4d& proj_matrix1,
59
+ const Eigen::Matrix3x4d& proj_matrix2,
60
+ const Eigen::Vector2d& point1,
61
+ const Eigen::Vector2d& point2);
62
+
63
+ // Triangulate multiple 3D points from multiple image correspondences.
64
+ std::vector<Eigen::Vector3d> TriangulatePoints(
65
+ const Eigen::Matrix3x4d& proj_matrix1,
66
+ const Eigen::Matrix3x4d& proj_matrix2,
67
+ const std::vector<Eigen::Vector2d>& points1,
68
+ const std::vector<Eigen::Vector2d>& points2);
69
+
70
+ // Triangulate point from multiple views minimizing the L2 error.
71
+ //
72
+ // @param proj_matrices Projection matrices of multi-view observations.
73
+ // @param points Image observations of multi-view observations.
74
+ //
75
+ // @return Estimated 3D point.
76
+ Eigen::Vector3d TriangulateMultiViewPoint(
77
+ const std::vector<Eigen::Matrix3x4d>& proj_matrices,
78
+ const std::vector<Eigen::Vector2d>& points);
79
+
80
+ // Triangulate optimal 3D point from corresponding image point observations by
81
+ // finding the optimal image observations.
82
+ //
83
+ // Note that camera poses should be very good in order for this method to yield
84
+ // good results. Otherwise just use `TriangulatePoint`.
85
+ //
86
+ // Implementation of the method described in
87
+ // P. Lindstrom, "Triangulation Made Easy," IEEE Computer Vision and Pattern
88
+ // Recognition 2010, pp. 1554-1561, June 2010.
89
+ //
90
+ // @param proj_matrix1 Projection matrix of the first image as 3x4 matrix.
91
+ // @param proj_matrix2 Projection matrix of the second image as 3x4 matrix.
92
+ // @param point1 Corresponding 2D point in first image.
93
+ // @param point2 Corresponding 2D point in second image.
94
+ //
95
+ // @return Triangulated optimal 3D point.
96
+ Eigen::Vector3d TriangulateOptimalPoint(const Eigen::Matrix3x4d& proj_matrix1,
97
+ const Eigen::Matrix3x4d& proj_matrix2,
98
+ const Eigen::Vector2d& point1,
99
+ const Eigen::Vector2d& point2);
100
+
101
+ // Triangulate multiple optimal 3D points from multiple image correspondences.
102
+ std::vector<Eigen::Vector3d> TriangulateOptimalPoints(
103
+ const Eigen::Matrix3x4d& proj_matrix1,
104
+ const Eigen::Matrix3x4d& proj_matrix2,
105
+ const std::vector<Eigen::Vector2d>& points1,
106
+ const std::vector<Eigen::Vector2d>& points2);
107
+
108
+ // Calculate angle in radians between the two rays of a triangulated point.
109
+ double CalculateTriangulationAngle(const Eigen::Vector3d& proj_center1,
110
+ const Eigen::Vector3d& proj_center2,
111
+ const Eigen::Vector3d& point3D);
112
+ std::vector<double> CalculateTriangulationAngles(
113
+ const Eigen::Vector3d& proj_center1, const Eigen::Vector3d& proj_center2,
114
+ const std::vector<Eigen::Vector3d>& points3D);
115
+
116
+ } // namespace colmap
117
+
118
+ #endif // COLMAP_SRC_BASE_TRIANGULATION_H_
colmap/include/colmap/base/undistortion.h ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_UNDISTORTION_H_
33
+ #define COLMAP_SRC_BASE_UNDISTORTION_H_
34
+
35
+ #include "base/reconstruction.h"
36
+ #include "util/alignment.h"
37
+ #include "util/bitmap.h"
38
+ #include "util/misc.h"
39
+ #include "util/threading.h"
40
+
41
+ namespace colmap {
42
+
43
+ struct UndistortCameraOptions {
44
+ // The amount of blank pixels in the undistorted image in the range [0, 1].
45
+ double blank_pixels = 0.0;
46
+
47
+ // Minimum and maximum scale change of camera used to satisfy the blank
48
+ // pixel constraint.
49
+ double min_scale = 0.2;
50
+ double max_scale = 2.0;
51
+
52
+ // Maximum image size in terms of width or height of the undistorted camera.
53
+ int max_image_size = -1;
54
+
55
+ // The 4 factors in the range [0, 1] that define the ROI (region of interest)
56
+ // in original image. The bounding box pixel coordinates are calculated as
57
+ // (roi_min_x * Width, roi_min_y * Height) and
58
+ // (roi_max_x * Width, roi_max_y * Height).
59
+ double roi_min_x = 0.0;
60
+ double roi_min_y = 0.0;
61
+ double roi_max_x = 1.0;
62
+ double roi_max_y = 1.0;
63
+ };
64
+
65
+ // Undistort images and export undistorted cameras, as required by the
66
+ // mvs::PatchMatchController class.
67
+ class COLMAPUndistorter : public Thread {
68
+ public:
69
+ COLMAPUndistorter(
70
+ const UndistortCameraOptions& options,
71
+ const Reconstruction& reconstruction, const std::string& image_path,
72
+ const std::string& output_path, const int num_related_images = 20,
73
+ const CopyType copy_type = CopyType::COPY,
74
+ const std::vector<image_t>& image_ids = std::vector<image_t>());
75
+
76
+ private:
77
+ void Run();
78
+
79
+ bool Undistort(const image_t image_id) const;
80
+ void WritePatchMatchConfig() const;
81
+ void WriteFusionConfig() const;
82
+ void WriteScript(const bool geometric) const;
83
+
84
+ UndistortCameraOptions options_;
85
+ const std::string image_path_;
86
+ const std::string output_path_;
87
+ const CopyType copy_type_;
88
+ const int num_patch_match_src_images_;
89
+ const Reconstruction& reconstruction_;
90
+ const std::vector<image_t> image_ids_;
91
+ std::vector<std::string> image_names_;
92
+ };
93
+
94
+ // Undistort images and prepare data for CMVS/PMVS.
95
+ class PMVSUndistorter : public Thread {
96
+ public:
97
+ PMVSUndistorter(const UndistortCameraOptions& options,
98
+ const Reconstruction& reconstruction,
99
+ const std::string& image_path,
100
+ const std::string& output_path);
101
+
102
+ private:
103
+ void Run();
104
+
105
+ bool Undistort(const size_t reg_image_idx) const;
106
+ void WriteVisibilityData() const;
107
+ void WriteOptionFile() const;
108
+ void WritePMVSScript() const;
109
+ void WriteCMVSPMVSScript() const;
110
+ void WriteCOLMAPScript(const bool geometric) const;
111
+ void WriteCMVSCOLMAPScript(const bool geometric) const;
112
+
113
+ UndistortCameraOptions options_;
114
+ std::string image_path_;
115
+ std::string output_path_;
116
+ const Reconstruction& reconstruction_;
117
+ };
118
+
119
+ // Undistort images and prepare data for CMP-MVS.
120
+ class CMPMVSUndistorter : public Thread {
121
+ public:
122
+ CMPMVSUndistorter(const UndistortCameraOptions& options,
123
+ const Reconstruction& reconstruction,
124
+ const std::string& image_path,
125
+ const std::string& output_path);
126
+
127
+ private:
128
+ void Run();
129
+
130
+ bool Undistort(const size_t reg_image_idx) const;
131
+
132
+ UndistortCameraOptions options_;
133
+ std::string image_path_;
134
+ std::string output_path_;
135
+ const Reconstruction& reconstruction_;
136
+ };
137
+
138
+ // Undistort images and export undistorted cameras without the need for a
139
+ // reconstruction. Instead, the image names and camera model information are
140
+ // read from a text file.
141
+ class PureImageUndistorter : public Thread {
142
+ public:
143
+ PureImageUndistorter(const UndistortCameraOptions& options,
144
+ const std::string& image_path,
145
+ const std::string& output_path,
146
+ const std::vector<std::pair<std::string, Camera>>&
147
+ image_names_and_cameras);
148
+
149
+ private:
150
+ void Run();
151
+
152
+ bool Undistort(const size_t reg_image_idx) const;
153
+
154
+ UndistortCameraOptions options_;
155
+ std::string image_path_;
156
+ std::string output_path_;
157
+ const std::vector<std::pair<std::string, Camera>>& image_names_and_cameras_;
158
+ };
159
+
160
+ // Rectify stereo image pairs.
161
+ class StereoImageRectifier : public Thread {
162
+ public:
163
+ StereoImageRectifier(
164
+ const UndistortCameraOptions& options,
165
+ const Reconstruction& reconstruction, const std::string& image_path,
166
+ const std::string& output_path,
167
+ const std::vector<std::pair<image_t, image_t>>& stereo_pairs);
168
+
169
+ private:
170
+ void Run();
171
+
172
+ void Rectify(const image_t image_id1, const image_t image_id2) const;
173
+
174
+ UndistortCameraOptions options_;
175
+ std::string image_path_;
176
+ std::string output_path_;
177
+ const std::vector<std::pair<image_t, image_t>>& stereo_pairs_;
178
+ const Reconstruction& reconstruction_;
179
+ };
180
+
181
+ // Undistort camera by resizing the image and shifting the principal point.
182
+ //
183
+ // The scaling factor is computed such that no blank pixels are in the
184
+ // undistorted image (blank_pixels=0) or all pixels in distorted image are
185
+ // contained in output image (blank_pixels=1).
186
+ //
187
+ // The focal length of the image is preserved and the dimensions of the
188
+ // undistorted pinhole camera are adjusted such that either all pixels in
189
+ // the undistorted image have a corresponding pixel in the distorted image
190
+ // (i.e. no blank pixels at the borders, for `blank_pixels=0`), or all pixels
191
+ // in the distorted image project have a corresponding pixel in the undistorted
192
+ // image (i.e. blank pixels at the borders, for `blank_pixels=1`). Intermediate
193
+ // states can be achieved by setting `blank_pixels` between 0 and 1.
194
+ //
195
+ // The relative location of the principal point of the distorted camera is
196
+ // preserved. The scaling of the image dimensions is subject to the `min_scale`,
197
+ // `max_scale`, and `max_image_size` constraints.
198
+ Camera UndistortCamera(const UndistortCameraOptions& options,
199
+ const Camera& camera);
200
+
201
+ // Undistort image such that the viewing geometry of the undistorted image
202
+ // follows a pinhole camera model. See `UndistortCamera` for more details
203
+ // on the undistortion conventions.
204
+ void UndistortImage(const UndistortCameraOptions& options,
205
+ const Bitmap& distorted_image,
206
+ const Camera& distorted_camera, Bitmap* undistorted_image,
207
+ Camera* undistorted_camera);
208
+
209
+ // Undistort all cameras in the reconstruction and accordingly all
210
+ // observations in their corresponding images.
211
+ void UndistortReconstruction(const UndistortCameraOptions& options,
212
+ Reconstruction* reconstruction);
213
+
214
+ // Compute stereo rectification homographies that transform two images,
215
+ // such that corresponding pixels in one image lie on the same scanline in the
216
+ // other image. The matrix Q transforms disparity values to world coordinates
217
+ // as [x, y, disparity, 1] * Q = [X, Y, Z, 1] * w. Note that this function
218
+ // assumes that the two cameras are already undistorted.
219
+ void RectifyStereoCameras(const Camera& camera1, const Camera& camera2,
220
+ const Eigen::Vector4d& qvec,
221
+ const Eigen::Vector3d& tvec, Eigen::Matrix3d* H1,
222
+ Eigen::Matrix3d* H2, Eigen::Matrix4d* Q);
223
+
224
+ // Rectify and undistort the stereo image pair using the given geometry.
225
+ void RectifyAndUndistortStereoImages(
226
+ const UndistortCameraOptions& options, const Bitmap& distorted_image1,
227
+ const Bitmap& distorted_image2, const Camera& distorted_camera1,
228
+ const Camera& distorted_camera2, const Eigen::Vector4d& qvec,
229
+ const Eigen::Vector3d& tvec, Bitmap* undistorted_image1,
230
+ Bitmap* undistorted_image2, Camera* undistorted_camera, Eigen::Matrix4d* Q);
231
+
232
+ } // namespace colmap
233
+
234
+ #endif // COLMAP_SRC_BASE_UNDISTORTION_H_
colmap/include/colmap/base/visibility_pyramid.h ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_VISIBILITY_PYRAMID_H_
33
+ #define COLMAP_SRC_BASE_VISIBILITY_PYRAMID_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+
41
+ namespace colmap {
42
+
43
+ // A class that captures the distribution of points in a 2D grid.
44
+ // For example, to capture the distribution of visible 3D points in an image.
45
+ //
46
+ // The class captures the distribution of points by a score. A higher score
47
+ // corresponds to a more uniform distribution of the points in the grid.
48
+ //
49
+ // The score is computed by the number of populated cells in a multi-resolution
50
+ // pyramid. A populated cell contributes to the overall score if it is
51
+ // populated by at least one point and the contributed score is according
52
+ // to its resolution in the pyramid. A cell in a higher resolution level
53
+ // contributes a higher score to the overall score.
54
+ class VisibilityPyramid {
55
+ public:
56
+ VisibilityPyramid();
57
+ VisibilityPyramid(const size_t num_levels, const size_t width,
58
+ const size_t height);
59
+
60
+ void SetPoint(const double x, const double y);
61
+ void ResetPoint(const double x, const double y);
62
+
63
+ inline size_t NumLevels() const;
64
+ inline size_t Width() const;
65
+ inline size_t Height() const;
66
+
67
+ inline size_t Score() const;
68
+ inline size_t MaxScore() const;
69
+
70
+ private:
71
+ void CellForPoint(const double x, const double y, size_t* cx,
72
+ size_t* cy) const;
73
+
74
+ // Range of the input points.
75
+ size_t width_;
76
+ size_t height_;
77
+
78
+ // The overall visibility score.
79
+ size_t score_;
80
+
81
+ // The maximum score when all cells are populated.
82
+ size_t max_score_;
83
+
84
+ // The visibilty pyramid with multiple levels.
85
+ std::vector<Eigen::MatrixXi> pyramid_;
86
+ };
87
+
88
+ ////////////////////////////////////////////////////////////////////////////////
89
+ // Implementation
90
+ ////////////////////////////////////////////////////////////////////////////////
91
+
92
+ size_t VisibilityPyramid::NumLevels() const { return pyramid_.size(); }
93
+
94
+ size_t VisibilityPyramid::Width() const { return width_; }
95
+
96
+ size_t VisibilityPyramid::Height() const { return height_; }
97
+
98
+ size_t VisibilityPyramid::Score() const { return score_; }
99
+
100
+ size_t VisibilityPyramid::MaxScore() const { return max_score_; }
101
+
102
+ } // namespace colmap
103
+
104
+ #endif // COLMAP_SRC_BASE_VISIBILITY_PYRAMID_H_
colmap/include/colmap/base/warp.h ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_WARP_H_
33
+ #define COLMAP_SRC_BASE_WARP_H_
34
+
35
+ #include "base/camera.h"
36
+ #include "util/alignment.h"
37
+ #include "util/bitmap.h"
38
+
39
+ namespace colmap {
40
+
41
+ // Warp source image to target image by projecting the pixels of the target
42
+ // image up to infinity and projecting it down into the source image
43
+ // (i.e. an inverse mapping). The function allocates the target image.
44
+ void WarpImageBetweenCameras(const Camera& source_camera,
45
+ const Camera& target_camera,
46
+ const Bitmap& source_image, Bitmap* target_image);
47
+
48
+ // Warp an image with the given homography, where H defines the pixel mapping
49
+ // from the target to source image. Note that the pixel centers are assumed to
50
+ // have coordinates (0.5, 0.5).
51
+ void WarpImageWithHomography(const Eigen::Matrix3d& H,
52
+ const Bitmap& source_image, Bitmap* target_image);
53
+
54
+ // First, warp source image to target image by projecting the pixels of the
55
+ // target image up to infinity and projecting it down into the source image
56
+ // (i.e. an inverse mapping). Second, warp the coordinates from the first
57
+ // warping with the given homography. The function allocates the target image.
58
+ void WarpImageWithHomographyBetweenCameras(const Eigen::Matrix3d& H,
59
+ const Camera& source_camera,
60
+ const Camera& target_camera,
61
+ const Bitmap& source_image,
62
+ Bitmap* target_image);
63
+
64
+ // Resample row-major image using bilinear interpolation.
65
+ void ResampleImageBilinear(const float* data, const int rows, const int cols,
66
+ const int new_rows, const int new_cols,
67
+ float* resampled);
68
+
69
+ // Smooth row-major image using a Gaussian filter kernel.
70
+ void SmoothImage(const float* data, const int rows, const int cols,
71
+ const float sigma_r, const float sigma_c, float* smoothed);
72
+
73
+ // Downsample row-major image by first smoothing and then resampling.
74
+ void DownsampleImage(const float* data, const int rows, const int cols,
75
+ const int new_rows, const int new_cols,
76
+ float* downsampled);
77
+
78
+ } // namespace colmap
79
+
80
+ #endif // COLMAP_SRC_BASE_WARP_H_
colmap/include/colmap/controllers/automatic_reconstruction.h ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_CONTROLLERS_AUTOMATIC_RECONSTRUCTION_H_
33
+ #define COLMAP_SRC_CONTROLLERS_AUTOMATIC_RECONSTRUCTION_H_
34
+
35
+ #include <string>
36
+
37
+ #include "base/reconstruction_manager.h"
38
+ #include "util/option_manager.h"
39
+ #include "util/threading.h"
40
+
41
+ namespace colmap {
42
+
43
+ class AutomaticReconstructionController : public Thread {
44
+ public:
45
+ enum class DataType { INDIVIDUAL, VIDEO, INTERNET };
46
+ enum class Quality { LOW, MEDIUM, HIGH, EXTREME };
47
+ enum class Mesher { POISSON, DELAUNAY };
48
+
49
+ struct Options {
50
+ // The path to the workspace folder in which all results are stored.
51
+ std::string workspace_path;
52
+
53
+ // The path to the image folder which are used as input.
54
+ std::string image_path;
55
+
56
+ // The path to the mask folder which are used as input.
57
+ std::string mask_path;
58
+
59
+ // The path to the vocabulary tree for feature matching.
60
+ std::string vocab_tree_path;
61
+
62
+ // The type of input data used to choose optimal mapper settings.
63
+ DataType data_type = DataType::INDIVIDUAL;
64
+
65
+ // Whether to perform low- or high-quality reconstruction.
66
+ Quality quality = Quality::HIGH;
67
+
68
+ // Whether to use shared intrinsics or not.
69
+ bool single_camera = false;
70
+
71
+ // Which camera model to use for images.
72
+ std::string camera_model = "SIMPLE_RADIAL";
73
+
74
+ // Whether to perform sparse mapping.
75
+ bool sparse = true;
76
+
77
+ // Whether to perform dense mapping.
78
+ #ifdef CUDA_ENABLED
79
+ bool dense = true;
80
+ #else
81
+ bool dense = false;
82
+ #endif
83
+
84
+ // The meshing algorithm to be used.
85
+ Mesher mesher = Mesher::POISSON;
86
+
87
+ // The number of threads to use in all stages.
88
+ int num_threads = -1;
89
+
90
+ // Whether to use the GPU in feature extraction and matching.
91
+ bool use_gpu = true;
92
+
93
+ // Index of the GPU used for GPU stages. For multi-GPU computation,
94
+ // you should separate multiple GPU indices by comma, e.g., "0,1,2,3".
95
+ // By default, all GPUs will be used in all stages.
96
+ std::string gpu_index = "-1";
97
+ };
98
+
99
+ AutomaticReconstructionController(
100
+ const Options& options, ReconstructionManager* reconstruction_manager);
101
+
102
+ void Stop() override;
103
+
104
+ private:
105
+ void Run() override;
106
+ void RunFeatureExtraction();
107
+ void RunFeatureMatching();
108
+ void RunSparseMapper();
109
+ void RunDenseMapper();
110
+
111
+ const Options options_;
112
+ OptionManager option_manager_;
113
+ ReconstructionManager* reconstruction_manager_;
114
+ Thread* active_thread_;
115
+ std::unique_ptr<Thread> feature_extractor_;
116
+ std::unique_ptr<Thread> exhaustive_matcher_;
117
+ std::unique_ptr<Thread> sequential_matcher_;
118
+ std::unique_ptr<Thread> vocab_tree_matcher_;
119
+ };
120
+
121
+ } // namespace colmap
122
+
123
+ #endif // COLMAP_SRC_CONTROLLERS_AUTOMATIC_RECONSTRUCTION_H_
colmap/include/colmap/controllers/bundle_adjustment.h ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_CONTROLLERS_BUNDLE_ADJUSTMENT_H_
33
+ #define COLMAP_SRC_CONTROLLERS_BUNDLE_ADJUSTMENT_H_
34
+
35
+ #include "base/reconstruction.h"
36
+ #include "util/option_manager.h"
37
+ #include "util/threading.h"
38
+
39
+ namespace colmap {
40
+
41
+ // Class that controls the global bundle adjustment procedure.
42
+ class BundleAdjustmentController : public Thread {
43
+ public:
44
+ BundleAdjustmentController(const OptionManager& options,
45
+ Reconstruction* reconstruction);
46
+
47
+ private:
48
+ void Run();
49
+
50
+ const OptionManager options_;
51
+ Reconstruction* reconstruction_;
52
+ };
53
+
54
+ } // namespace colmap
55
+
56
+ #endif // COLMAP_SRC_CONTROLLERS_BUNDLE_ADJUSTMENT_H_
colmap/include/colmap/controllers/hierarchical_mapper.h ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_CONTROLLERS_HIERARCHICAL_MAPPER_H_
33
+ #define COLMAP_SRC_CONTROLLERS_HIERARCHICAL_MAPPER_H_
34
+
35
+ #include "base/reconstruction_manager.h"
36
+ #include "base/scene_clustering.h"
37
+ #include "controllers/incremental_mapper.h"
38
+ #include "util/threading.h"
39
+
40
+ namespace colmap {
41
+
42
+ // Hierarchical mapping first hierarchically partitions the scene into multiple
43
+ // overlapping clusters, then reconstructs them separately using incremental
44
+ // mapping, and finally merges them all into a globally consistent
45
+ // reconstruction. This is especially useful for larger-scale scenes, since
46
+ // incremental mapping becomes slow with an increasing number of images.
47
+ class HierarchicalMapperController : public Thread {
48
+ public:
49
+ struct Options {
50
+ // The path to the image folder which are used as input.
51
+ std::string image_path;
52
+
53
+ // The path to the database file which is used as input.
54
+ std::string database_path;
55
+
56
+ // The maximum number of trials to initialize a cluster.
57
+ int init_num_trials = 10;
58
+
59
+ // The number of workers used to reconstruct clusters in parallel.
60
+ int num_workers = -1;
61
+
62
+ bool Check() const;
63
+ };
64
+
65
+ HierarchicalMapperController(
66
+ const Options& options,
67
+ const SceneClustering::Options& clustering_options,
68
+ const IncrementalMapperOptions& mapper_options,
69
+ ReconstructionManager* reconstruction_manager);
70
+
71
+ private:
72
+ void Run() override;
73
+
74
+ const Options options_;
75
+ const SceneClustering::Options clustering_options_;
76
+ const IncrementalMapperOptions mapper_options_;
77
+ ReconstructionManager* reconstruction_manager_;
78
+ };
79
+
80
+ } // namespace colmap
81
+
82
+ #endif // COLMAP_SRC_CONTROLLERS_HIERARCHICAL_MAPPER_H_
colmap/include/colmap/controllers/incremental_mapper.h ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_CONTROLLERS_INCREMENTAL_MAPPER_H_
33
+ #define COLMAP_SRC_CONTROLLERS_INCREMENTAL_MAPPER_H_
34
+
35
+ #include "base/reconstruction_manager.h"
36
+ #include "sfm/incremental_mapper.h"
37
+ #include "util/threading.h"
38
+
39
+ namespace colmap {
40
+
41
+ struct IncrementalMapperOptions {
42
+ public:
43
+ // The minimum number of matches for inlier matches to be considered.
44
+ int min_num_matches = 15;
45
+
46
+ // Whether to ignore the inlier matches of watermark image pairs.
47
+ bool ignore_watermarks = false;
48
+
49
+ // Whether to reconstruct multiple sub-models.
50
+ bool multiple_models = true;
51
+
52
+ // The number of sub-models to reconstruct.
53
+ int max_num_models = 50;
54
+
55
+ // The maximum number of overlapping images between sub-models. If the
56
+ // current sub-models shares more than this number of images with another
57
+ // model, then the reconstruction is stopped.
58
+ int max_model_overlap = 20;
59
+
60
+ // The minimum number of registered images of a sub-model, otherwise the
61
+ // sub-model is discarded.
62
+ int min_model_size = 10;
63
+
64
+ // The image identifiers used to initialize the reconstruction. Note that
65
+ // only one or both image identifiers can be specified. In the former case,
66
+ // the second image is automatically determined.
67
+ int init_image_id1 = -1;
68
+ int init_image_id2 = -1;
69
+
70
+ // The number of trials to initialize the reconstruction.
71
+ int init_num_trials = 200;
72
+
73
+ // Whether to extract colors for reconstructed points.
74
+ bool extract_colors = true;
75
+
76
+ // The number of threads to use during reconstruction.
77
+ int num_threads = -1;
78
+
79
+ // Thresholds for filtering images with degenerate intrinsics.
80
+ double min_focal_length_ratio = 0.1;
81
+ double max_focal_length_ratio = 10.0;
82
+ double max_extra_param = 1.0;
83
+
84
+ // Which intrinsic parameters to optimize during the reconstruction.
85
+ bool ba_refine_focal_length = true;
86
+ bool ba_refine_principal_point = false;
87
+ bool ba_refine_extra_params = true;
88
+
89
+ // The minimum number of residuals per bundle adjustment problem to
90
+ // enable multi-threading solving of the problems.
91
+ int ba_min_num_residuals_for_multi_threading = 50000;
92
+
93
+ // The number of images to optimize in local bundle adjustment.
94
+ int ba_local_num_images = 6;
95
+
96
+ // Ceres solver function tolerance for local bundle adjustment
97
+ double ba_local_function_tolerance = 0.0;
98
+
99
+ // The maximum number of local bundle adjustment iterations.
100
+ int ba_local_max_num_iterations = 25;
101
+
102
+ // Whether to use PBA in global bundle adjustment.
103
+ bool ba_global_use_pba = false;
104
+
105
+ // The GPU index for PBA bundle adjustment.
106
+ int ba_global_pba_gpu_index = -1;
107
+
108
+ // The growth rates after which to perform global bundle adjustment.
109
+ double ba_global_images_ratio = 1.1;
110
+ double ba_global_points_ratio = 1.1;
111
+ int ba_global_images_freq = 500;
112
+ int ba_global_points_freq = 250000;
113
+
114
+ // Ceres solver function tolerance for global bundle adjustment
115
+ double ba_global_function_tolerance = 0.0;
116
+
117
+ // The maximum number of global bundle adjustment iterations.
118
+ int ba_global_max_num_iterations = 50;
119
+
120
+ // The thresholds for iterative bundle adjustment refinements.
121
+ int ba_local_max_refinements = 2;
122
+ double ba_local_max_refinement_change = 0.001;
123
+ int ba_global_max_refinements = 5;
124
+ double ba_global_max_refinement_change = 0.0005;
125
+
126
+ // Path to a folder with reconstruction snapshots during incremental
127
+ // reconstruction. Snapshots will be saved according to the specified
128
+ // frequency of registered images.
129
+ std::string snapshot_path = "";
130
+ int snapshot_images_freq = 0;
131
+
132
+ // Which images to reconstruct. If no images are specified, all images will
133
+ // be reconstructed by default.
134
+ std::unordered_set<std::string> image_names;
135
+
136
+ // If reconstruction is provided as input, fix the existing image poses.
137
+ bool fix_existing_images = false;
138
+
139
+ IncrementalMapper::Options Mapper() const;
140
+ IncrementalTriangulator::Options Triangulation() const;
141
+ BundleAdjustmentOptions LocalBundleAdjustment() const;
142
+ BundleAdjustmentOptions GlobalBundleAdjustment() const;
143
+ ParallelBundleAdjuster::Options ParallelGlobalBundleAdjustment() const;
144
+
145
+ bool Check() const;
146
+
147
+ private:
148
+ friend class OptionManager;
149
+ friend class MapperGeneralOptionsWidget;
150
+ friend class MapperTriangulationOptionsWidget;
151
+ friend class MapperRegistrationOptionsWidget;
152
+ friend class MapperInitializationOptionsWidget;
153
+ friend class MapperBundleAdjustmentOptionsWidget;
154
+ friend class MapperFilteringOptionsWidget;
155
+ friend class ReconstructionOptionsWidget;
156
+ IncrementalMapper::Options mapper;
157
+ IncrementalTriangulator::Options triangulation;
158
+ };
159
+
160
+ // Class that controls the incremental mapping procedure by iteratively
161
+ // initializing reconstructions from the same scene graph.
162
+ class IncrementalMapperController : public Thread {
163
+ public:
164
+ enum {
165
+ INITIAL_IMAGE_PAIR_REG_CALLBACK,
166
+ NEXT_IMAGE_REG_CALLBACK,
167
+ LAST_IMAGE_REG_CALLBACK,
168
+ };
169
+
170
+ IncrementalMapperController(const IncrementalMapperOptions* options,
171
+ const std::string& image_path,
172
+ const std::string& database_path,
173
+ ReconstructionManager* reconstruction_manager);
174
+
175
+ private:
176
+ void Run();
177
+ bool LoadDatabase();
178
+ void Reconstruct(const IncrementalMapper::Options& init_mapper_options);
179
+
180
+ const IncrementalMapperOptions* options_;
181
+ const std::string image_path_;
182
+ const std::string database_path_;
183
+ ReconstructionManager* reconstruction_manager_;
184
+ DatabaseCache database_cache_;
185
+ };
186
+
187
+ // Globally filter points and images in mapper.
188
+ size_t FilterPoints(const IncrementalMapperOptions& options,
189
+ IncrementalMapper* mapper);
190
+ size_t FilterImages(const IncrementalMapperOptions& options,
191
+ IncrementalMapper* mapper);
192
+
193
+ // Globally complete and merge tracks in mapper.
194
+ size_t CompleteAndMergeTracks(const IncrementalMapperOptions& options,
195
+ IncrementalMapper* mapper);
196
+
197
+ } // namespace colmap
198
+
199
+ #endif // COLMAP_SRC_CONTROLLERS_INCREMENTAL_MAPPER_H_
colmap/include/colmap/estimators/absolute_pose.h ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_ABSOLUTE_POSE_H_
33
+ #define COLMAP_SRC_ESTIMATORS_ABSOLUTE_POSE_H_
34
+
35
+ #include <array>
36
+ #include <vector>
37
+
38
+ #include <Eigen/Core>
39
+
40
+ #include "util/alignment.h"
41
+ #include "util/types.h"
42
+
43
+ namespace colmap {
44
+
45
+ // Analytic solver for the P3P (Perspective-Three-Point) problem.
46
+ //
47
+ // The algorithm is based on the following paper:
48
+ //
49
+ // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang. Complete Solution
50
+ // Classification for the Perspective-Three-Point Problem.
51
+ // http://www.mmrc.iss.ac.cn/~xgao/paper/ieee.pdf
52
+ class P3PEstimator {
53
+ public:
54
+ // The 2D image feature observations.
55
+ typedef Eigen::Vector2d X_t;
56
+ // The observed 3D features in the world frame.
57
+ typedef Eigen::Vector3d Y_t;
58
+ // The transformation from the world to the camera frame.
59
+ typedef Eigen::Matrix3x4d M_t;
60
+
61
+ // The minimum number of samples needed to estimate a model.
62
+ static const int kMinNumSamples = 3;
63
+
64
+ // Estimate the most probable solution of the P3P problem from a set of
65
+ // three 2D-3D point correspondences.
66
+ //
67
+ // @param points2D Normalized 2D image points as 3x2 matrix.
68
+ // @param points3D 3D world points as 3x3 matrix.
69
+ //
70
+ // @return Most probable pose as length-1 vector of a 3x4 matrix.
71
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points2D,
72
+ const std::vector<Y_t>& points3D);
73
+
74
+ // Calculate the squared reprojection error given a set of 2D-3D point
75
+ // correspondences and a projection matrix.
76
+ //
77
+ // @param points2D Normalized 2D image points as Nx2 matrix.
78
+ // @param points3D 3D world points as Nx3 matrix.
79
+ // @param proj_matrix 3x4 projection matrix.
80
+ // @param residuals Output vector of residuals.
81
+ static void Residuals(const std::vector<X_t>& points2D,
82
+ const std::vector<Y_t>& points3D,
83
+ const M_t& proj_matrix, std::vector<double>* residuals);
84
+ };
85
+
86
+ // EPNP solver for the PNP (Perspective-N-Point) problem. The solver needs a
87
+ // minimum of 4 2D-3D correspondences.
88
+ //
89
+ // The algorithm is based on the following paper:
90
+ //
91
+ // Lepetit, Vincent, Francesc Moreno-Noguer, and Pascal Fua.
92
+ // "Epnp: An accurate o (n) solution to the pnp problem."
93
+ // International journal of computer vision 81.2 (2009): 155-166.
94
+ //
95
+ // The implementation is based on their original open-source release, but is
96
+ // ported to Eigen and contains several improvements over the original code.
97
+ class EPNPEstimator {
98
+ public:
99
+ // The 2D image feature observations.
100
+ typedef Eigen::Vector2d X_t;
101
+ // The observed 3D features in the world frame.
102
+ typedef Eigen::Vector3d Y_t;
103
+ // The transformation from the world to the camera frame.
104
+ typedef Eigen::Matrix3x4d M_t;
105
+
106
+ // The minimum number of samples needed to estimate a model.
107
+ static const int kMinNumSamples = 4;
108
+
109
+ // Estimate the most probable solution of the P3P problem from a set of
110
+ // three 2D-3D point correspondences.
111
+ //
112
+ // @param points2D Normalized 2D image points as 3x2 matrix.
113
+ // @param points3D 3D world points as 3x3 matrix.
114
+ //
115
+ // @return Most probable pose as length-1 vector of a 3x4 matrix.
116
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points2D,
117
+ const std::vector<Y_t>& points3D);
118
+
119
+ // Calculate the squared reprojection error given a set of 2D-3D point
120
+ // correspondences and a projection matrix.
121
+ //
122
+ // @param points2D Normalized 2D image points as Nx2 matrix.
123
+ // @param points3D 3D world points as Nx3 matrix.
124
+ // @param proj_matrix 3x4 projection matrix.
125
+ // @param residuals Output vector of residuals.
126
+ static void Residuals(const std::vector<X_t>& points2D,
127
+ const std::vector<Y_t>& points3D,
128
+ const M_t& proj_matrix, std::vector<double>* residuals);
129
+
130
+ private:
131
+ bool ComputePose(const std::vector<Eigen::Vector2d>& points2D,
132
+ const std::vector<Eigen::Vector3d>& points3D,
133
+ Eigen::Matrix3x4d* proj_matrix);
134
+
135
+ void ChooseControlPoints();
136
+ bool ComputeBarycentricCoordinates();
137
+
138
+ Eigen::Matrix<double, Eigen::Dynamic, 12> ComputeM();
139
+ Eigen::Matrix<double, 6, 10> ComputeL6x10(
140
+ const Eigen::Matrix<double, 12, 12>& Ut);
141
+ Eigen::Matrix<double, 6, 1> ComputeRho();
142
+
143
+ void FindBetasApprox1(const Eigen::Matrix<double, 6, 10>& L_6x10,
144
+ const Eigen::Matrix<double, 6, 1>& rho,
145
+ Eigen::Vector4d* betas);
146
+ void FindBetasApprox2(const Eigen::Matrix<double, 6, 10>& L_6x10,
147
+ const Eigen::Matrix<double, 6, 1>& rho,
148
+ Eigen::Vector4d* betas);
149
+ void FindBetasApprox3(const Eigen::Matrix<double, 6, 10>& L_6x10,
150
+ const Eigen::Matrix<double, 6, 1>& rho,
151
+ Eigen::Vector4d* betas);
152
+
153
+ void RunGaussNewton(const Eigen::Matrix<double, 6, 10>& L_6x10,
154
+ const Eigen::Matrix<double, 6, 1>& rho,
155
+ Eigen::Vector4d* betas);
156
+
157
+ double ComputeRT(const Eigen::Matrix<double, 12, 12>& Ut,
158
+ const Eigen::Vector4d& betas, Eigen::Matrix3d* R,
159
+ Eigen::Vector3d* t);
160
+
161
+ void ComputeCcs(const Eigen::Vector4d& betas,
162
+ const Eigen::Matrix<double, 12, 12>& Ut);
163
+ void ComputePcs();
164
+
165
+ void SolveForSign();
166
+
167
+ void EstimateRT(Eigen::Matrix3d* R, Eigen::Vector3d* t);
168
+
169
+ double ComputeTotalReprojectionError(const Eigen::Matrix3d& R,
170
+ const Eigen::Vector3d& t);
171
+
172
+ const std::vector<Eigen::Vector2d>* points2D_ = nullptr;
173
+ const std::vector<Eigen::Vector3d>* points3D_ = nullptr;
174
+ std::vector<Eigen::Vector3d> pcs_;
175
+ std::vector<Eigen::Vector4d> alphas_;
176
+ std::array<Eigen::Vector3d, 4> cws_;
177
+ std::array<Eigen::Vector3d, 4> ccs_;
178
+ };
179
+
180
+ } // namespace colmap
181
+
182
+ #endif // COLMAP_SRC_ESTIMATORS_ABSOLUTE_POSE_H_
colmap/include/colmap/estimators/affine_transform.h ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_AFFINE_TRANSFORM_H_
33
+ #define COLMAP_SRC_ESTIMATORS_AFFINE_TRANSFORM_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ class AffineTransformEstimator {
45
+ public:
46
+ typedef Eigen::Vector2d X_t;
47
+ typedef Eigen::Vector2d Y_t;
48
+ typedef Eigen::Matrix<double, 2, 3> M_t;
49
+
50
+ // The minimum number of samples needed to estimate a model.
51
+ static const int kMinNumSamples = 3;
52
+
53
+ // Estimate the affine transformation from at least 3 correspondences.
54
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
55
+ const std::vector<Y_t>& points2);
56
+
57
+ // Compute the squared transformation error.
58
+ static void Residuals(const std::vector<X_t>& points1,
59
+ const std::vector<Y_t>& points2, const M_t& E,
60
+ std::vector<double>* residuals);
61
+ };
62
+
63
+ } // namespace colmap
64
+
65
+ #endif // COLMAP_SRC_ESTIMATORS_AFFINE_TRANSFORM_H_
colmap/include/colmap/estimators/coordinate_frame.h ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_COORDINATE_AXES_H_
33
+ #define COLMAP_SRC_ESTIMATORS_COORDINATE_AXES_H_
34
+
35
+ #include <Eigen/Core>
36
+
37
+ #include "base/reconstruction.h"
38
+
39
+ namespace colmap {
40
+
41
+ struct ManhattanWorldFrameEstimationOptions {
42
+ // The maximum image size for line detection.
43
+ int max_image_size = 1024;
44
+ // The minimum length of line segments in pixels.
45
+ double min_line_length = 3;
46
+ // The tolerance for classifying lines into horizontal/vertical.
47
+ double line_orientation_tolerance = 0.2;
48
+ // The maximum distance in pixels between lines and the vanishing points.
49
+ double max_line_vp_distance = 0.5;
50
+ // The maximum cosine distance between estimated axes to be inliers.
51
+ double max_axis_distance = 0.05;
52
+ };
53
+
54
+ // Estimate gravity vector by assuming gravity-aligned image orientation, i.e.
55
+ // the majority of images is assumed to have the gravity vector aligned with an
56
+ // upright image plane.
57
+ Eigen::Vector3d EstimateGravityVectorFromImageOrientation(
58
+ const Reconstruction& reconstruction,
59
+ const double max_axis_distance = 0.05);
60
+
61
+ // Estimate the coordinate frame of the reconstruction assuming a Manhattan
62
+ // world by finding the major vanishing points in each image. This function
63
+ // assumes that the majority of images is taken in upright direction, i.e.
64
+ // people are standing upright in the image. The orthonormal axes of the
65
+ // estimated coordinate frame will be given in the columns of the returned
66
+ // matrix. If one axis could not be determined, the respective column will be
67
+ // zero. The axes are specified in the world coordinate system in the order
68
+ // rightward, downward, forward.
69
+ Eigen::Matrix3d EstimateManhattanWorldFrame(
70
+ const ManhattanWorldFrameEstimationOptions& options,
71
+ const Reconstruction& reconstruction, const std::string& image_path);
72
+
73
+ // Aligns the reconstruction to the plane defined by running PCA on the 3D
74
+ // points. The model centroid is at the origin of the new coordinate system
75
+ // and the X axis is the first principal component with the Y axis being the
76
+ // second principal component
77
+ void AlignToPrincipalPlane(Reconstruction* recon, SimilarityTransform3* tform);
78
+
79
+ // Aligns the reconstruction to the local ENU plane orientation. Rotates the
80
+ // reconstruction such that the x-y plane aligns with the ENU tangent plane at
81
+ // the point cloud centroid and translates the origin to the centroid.
82
+ // If unscaled == true, then the original scale of the model remains unchanged.
83
+ void AlignToENUPlane(Reconstruction* recon, SimilarityTransform3* tform,
84
+ bool unscaled);
85
+
86
+ } // namespace colmap
87
+
88
+ #endif // COLMAP_SRC_ESTIMATORS_COORDINATE_AXES_H_
colmap/include/colmap/estimators/essential_matrix.h ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_ESSENTIAL_MATRIX_H_
33
+ #define COLMAP_SRC_ESTIMATORS_ESSENTIAL_MATRIX_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include <ceres/ceres.h>
40
+
41
+ #include "util/alignment.h"
42
+ #include "util/types.h"
43
+
44
+ namespace colmap {
45
+
46
+ // Essential matrix estimator from corresponding normalized point pairs.
47
+ //
48
+ // This algorithm solves the 5-Point problem based on the following paper:
49
+ //
50
+ // D. Nister, An efficient solution to the five-point relative pose problem,
51
+ // IEEE-T-PAMI, 26(6), 2004.
52
+ // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.86.8769
53
+ class EssentialMatrixFivePointEstimator {
54
+ public:
55
+ typedef Eigen::Vector2d X_t;
56
+ typedef Eigen::Vector2d Y_t;
57
+ typedef Eigen::Matrix3d M_t;
58
+
59
+ // The minimum number of samples needed to estimate a model.
60
+ static const int kMinNumSamples = 5;
61
+
62
+ // Estimate up to 10 possible essential matrix solutions from a set of
63
+ // corresponding points.
64
+ //
65
+ // The number of corresponding points must be at least 5.
66
+ //
67
+ // @param points1 First set of corresponding points.
68
+ // @param points2 Second set of corresponding points.
69
+ //
70
+ // @return Up to 10 solutions as a vector of 3x3 essential matrices.
71
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
72
+ const std::vector<Y_t>& points2);
73
+
74
+ // Calculate the residuals of a set of corresponding points and a given
75
+ // essential matrix.
76
+ //
77
+ // Residuals are defined as the squared Sampson error.
78
+ //
79
+ // @param points1 First set of corresponding points.
80
+ // @param points2 Second set of corresponding points.
81
+ // @param E 3x3 essential matrix.
82
+ // @param residuals Output vector of residuals.
83
+ static void Residuals(const std::vector<X_t>& points1,
84
+ const std::vector<Y_t>& points2, const M_t& E,
85
+ std::vector<double>* residuals);
86
+ };
87
+
88
+ // Essential matrix estimator from corresponding normalized point pairs.
89
+ //
90
+ // This algorithm solves the 8-Point problem based on the following paper:
91
+ //
92
+ // Hartley and Zisserman, Multiple View Geometry, algorithm 11.1, page 282.
93
+ class EssentialMatrixEightPointEstimator {
94
+ public:
95
+ typedef Eigen::Vector2d X_t;
96
+ typedef Eigen::Vector2d Y_t;
97
+ typedef Eigen::Matrix3d M_t;
98
+
99
+ // The minimum number of samples needed to estimate a model.
100
+ static const int kMinNumSamples = 8;
101
+
102
+ // Estimate essential matrix solutions from set of corresponding points.
103
+ //
104
+ // The number of corresponding points must be at least 8.
105
+ //
106
+ // @param points1 First set of corresponding points.
107
+ // @param points2 Second set of corresponding points.
108
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
109
+ const std::vector<Y_t>& points2);
110
+
111
+ // Calculate the residuals of a set of corresponding points and a given
112
+ // essential matrix.
113
+ //
114
+ // Residuals are defined as the squared Sampson error.
115
+ //
116
+ // @param points1 First set of corresponding points.
117
+ // @param points2 Second set of corresponding points.
118
+ // @param E 3x3 essential matrix.
119
+ // @param residuals Output vector of residuals.
120
+ static void Residuals(const std::vector<X_t>& points1,
121
+ const std::vector<Y_t>& points2, const M_t& E,
122
+ std::vector<double>* residuals);
123
+ };
124
+
125
+ } // namespace colmap
126
+
127
+ #endif // COLMAP_SRC_ESTIMATORS_ESSENTIAL_MATRIX_H_
colmap/include/colmap/estimators/essential_matrix_coeffs.h ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ {
33
+ const double* b = B.data();
34
+
35
+ coeffs(0) = b[0] * b[17] * b[34] + b[26] * b[4] * b[21] -
36
+ b[26] * b[17] * b[8] - b[13] * b[4] * b[34] -
37
+ b[0] * b[21] * b[30] + b[13] * b[30] * b[8];
38
+ coeffs(1) =
39
+ b[26] * b[4] * b[22] + b[14] * b[30] * b[8] + b[13] * b[31] * b[8] +
40
+ b[1] * b[17] * b[34] - b[13] * b[5] * b[34] + b[26] * b[5] * b[21] -
41
+ b[0] * b[21] * b[31] - b[26] * b[17] * b[9] - b[1] * b[21] * b[30] +
42
+ b[27] * b[4] * b[21] + b[0] * b[17] * b[35] - b[0] * b[22] * b[30] +
43
+ b[13] * b[30] * b[9] + b[0] * b[18] * b[34] - b[27] * b[17] * b[8] -
44
+ b[14] * b[4] * b[34] - b[13] * b[4] * b[35] - b[26] * b[18] * b[8];
45
+ coeffs(2) =
46
+ b[14] * b[30] * b[9] + b[14] * b[31] * b[8] + b[13] * b[31] * b[9] -
47
+ b[13] * b[4] * b[36] - b[13] * b[5] * b[35] + b[15] * b[30] * b[8] -
48
+ b[13] * b[6] * b[34] + b[13] * b[30] * b[10] + b[13] * b[32] * b[8] -
49
+ b[14] * b[4] * b[35] - b[14] * b[5] * b[34] + b[26] * b[4] * b[23] +
50
+ b[26] * b[5] * b[22] + b[26] * b[6] * b[21] - b[26] * b[17] * b[10] -
51
+ b[15] * b[4] * b[34] - b[26] * b[18] * b[9] - b[26] * b[19] * b[8] +
52
+ b[27] * b[4] * b[22] + b[27] * b[5] * b[21] - b[27] * b[17] * b[9] -
53
+ b[27] * b[18] * b[8] - b[1] * b[21] * b[31] - b[0] * b[23] * b[30] -
54
+ b[0] * b[21] * b[32] + b[28] * b[4] * b[21] - b[28] * b[17] * b[8] +
55
+ b[2] * b[17] * b[34] + b[0] * b[18] * b[35] - b[0] * b[22] * b[31] +
56
+ b[0] * b[17] * b[36] + b[0] * b[19] * b[34] - b[1] * b[22] * b[30] +
57
+ b[1] * b[18] * b[34] + b[1] * b[17] * b[35] - b[2] * b[21] * b[30];
58
+ coeffs(3) =
59
+ b[14] * b[30] * b[10] + b[14] * b[32] * b[8] - b[3] * b[21] * b[30] +
60
+ b[3] * b[17] * b[34] + b[13] * b[32] * b[9] + b[13] * b[33] * b[8] -
61
+ b[13] * b[4] * b[37] - b[13] * b[5] * b[36] + b[15] * b[30] * b[9] +
62
+ b[15] * b[31] * b[8] - b[16] * b[4] * b[34] - b[13] * b[6] * b[35] -
63
+ b[13] * b[7] * b[34] + b[13] * b[30] * b[11] + b[13] * b[31] * b[10] +
64
+ b[14] * b[31] * b[9] - b[14] * b[4] * b[36] - b[14] * b[5] * b[35] -
65
+ b[14] * b[6] * b[34] + b[16] * b[30] * b[8] - b[26] * b[20] * b[8] +
66
+ b[26] * b[4] * b[24] + b[26] * b[5] * b[23] + b[26] * b[6] * b[22] +
67
+ b[26] * b[7] * b[21] - b[26] * b[17] * b[11] - b[15] * b[4] * b[35] -
68
+ b[15] * b[5] * b[34] - b[26] * b[18] * b[10] - b[26] * b[19] * b[9] +
69
+ b[27] * b[4] * b[23] + b[27] * b[5] * b[22] + b[27] * b[6] * b[21] -
70
+ b[27] * b[17] * b[10] - b[27] * b[18] * b[9] - b[27] * b[19] * b[8] +
71
+ b[0] * b[17] * b[37] - b[0] * b[23] * b[31] - b[0] * b[24] * b[30] -
72
+ b[0] * b[21] * b[33] - b[29] * b[17] * b[8] + b[28] * b[4] * b[22] +
73
+ b[28] * b[5] * b[21] - b[28] * b[17] * b[9] - b[28] * b[18] * b[8] +
74
+ b[29] * b[4] * b[21] + b[1] * b[19] * b[34] - b[2] * b[21] * b[31] +
75
+ b[0] * b[20] * b[34] + b[0] * b[19] * b[35] + b[0] * b[18] * b[36] -
76
+ b[0] * b[22] * b[32] - b[1] * b[23] * b[30] - b[1] * b[21] * b[32] +
77
+ b[1] * b[18] * b[35] - b[1] * b[22] * b[31] - b[2] * b[22] * b[30] +
78
+ b[2] * b[17] * b[35] + b[1] * b[17] * b[36] + b[2] * b[18] * b[34];
79
+ coeffs(4) =
80
+ -b[14] * b[6] * b[35] - b[14] * b[7] * b[34] - b[3] * b[22] * b[30] -
81
+ b[3] * b[21] * b[31] + b[3] * b[17] * b[35] + b[3] * b[18] * b[34] +
82
+ b[13] * b[32] * b[10] + b[13] * b[33] * b[9] - b[13] * b[4] * b[38] -
83
+ b[13] * b[5] * b[37] - b[15] * b[6] * b[34] + b[15] * b[30] * b[10] +
84
+ b[15] * b[32] * b[8] - b[16] * b[4] * b[35] - b[13] * b[6] * b[36] -
85
+ b[13] * b[7] * b[35] + b[13] * b[31] * b[11] + b[13] * b[30] * b[12] +
86
+ b[14] * b[32] * b[9] + b[14] * b[33] * b[8] - b[14] * b[4] * b[37] -
87
+ b[14] * b[5] * b[36] + b[16] * b[30] * b[9] + b[16] * b[31] * b[8] -
88
+ b[26] * b[20] * b[9] + b[26] * b[4] * b[25] + b[26] * b[5] * b[24] +
89
+ b[26] * b[6] * b[23] + b[26] * b[7] * b[22] - b[26] * b[17] * b[12] +
90
+ b[14] * b[30] * b[11] + b[14] * b[31] * b[10] + b[15] * b[31] * b[9] -
91
+ b[15] * b[4] * b[36] - b[15] * b[5] * b[35] - b[26] * b[18] * b[11] -
92
+ b[26] * b[19] * b[10] - b[27] * b[20] * b[8] + b[27] * b[4] * b[24] +
93
+ b[27] * b[5] * b[23] + b[27] * b[6] * b[22] + b[27] * b[7] * b[21] -
94
+ b[27] * b[17] * b[11] - b[27] * b[18] * b[10] - b[27] * b[19] * b[9] -
95
+ b[16] * b[5] * b[34] - b[29] * b[17] * b[9] - b[29] * b[18] * b[8] +
96
+ b[28] * b[4] * b[23] + b[28] * b[5] * b[22] + b[28] * b[6] * b[21] -
97
+ b[28] * b[17] * b[10] - b[28] * b[18] * b[9] - b[28] * b[19] * b[8] +
98
+ b[29] * b[4] * b[22] + b[29] * b[5] * b[21] - b[2] * b[23] * b[30] +
99
+ b[2] * b[18] * b[35] - b[1] * b[22] * b[32] - b[2] * b[21] * b[32] +
100
+ b[2] * b[19] * b[34] + b[0] * b[19] * b[36] - b[0] * b[22] * b[33] +
101
+ b[0] * b[20] * b[35] - b[0] * b[23] * b[32] - b[0] * b[25] * b[30] +
102
+ b[0] * b[17] * b[38] + b[0] * b[18] * b[37] - b[0] * b[24] * b[31] +
103
+ b[1] * b[17] * b[37] - b[1] * b[23] * b[31] - b[1] * b[24] * b[30] -
104
+ b[1] * b[21] * b[33] + b[1] * b[20] * b[34] + b[1] * b[19] * b[35] +
105
+ b[1] * b[18] * b[36] + b[2] * b[17] * b[36] - b[2] * b[22] * b[31];
106
+ coeffs(5) =
107
+ -b[14] * b[6] * b[36] - b[14] * b[7] * b[35] + b[14] * b[31] * b[11] -
108
+ b[3] * b[23] * b[30] - b[3] * b[21] * b[32] + b[3] * b[18] * b[35] -
109
+ b[3] * b[22] * b[31] + b[3] * b[17] * b[36] + b[3] * b[19] * b[34] +
110
+ b[13] * b[32] * b[11] + b[13] * b[33] * b[10] - b[13] * b[5] * b[38] -
111
+ b[15] * b[6] * b[35] - b[15] * b[7] * b[34] + b[15] * b[30] * b[11] +
112
+ b[15] * b[31] * b[10] + b[16] * b[31] * b[9] - b[13] * b[6] * b[37] -
113
+ b[13] * b[7] * b[36] + b[13] * b[31] * b[12] + b[14] * b[32] * b[10] +
114
+ b[14] * b[33] * b[9] - b[14] * b[4] * b[38] - b[14] * b[5] * b[37] -
115
+ b[16] * b[6] * b[34] + b[16] * b[30] * b[10] + b[16] * b[32] * b[8] -
116
+ b[26] * b[20] * b[10] + b[26] * b[5] * b[25] + b[26] * b[6] * b[24] +
117
+ b[26] * b[7] * b[23] + b[14] * b[30] * b[12] + b[15] * b[32] * b[9] +
118
+ b[15] * b[33] * b[8] - b[15] * b[4] * b[37] - b[15] * b[5] * b[36] +
119
+ b[29] * b[5] * b[22] + b[29] * b[6] * b[21] - b[26] * b[18] * b[12] -
120
+ b[26] * b[19] * b[11] - b[27] * b[20] * b[9] + b[27] * b[4] * b[25] +
121
+ b[27] * b[5] * b[24] + b[27] * b[6] * b[23] + b[27] * b[7] * b[22] -
122
+ b[27] * b[17] * b[12] - b[27] * b[18] * b[11] - b[27] * b[19] * b[10] -
123
+ b[28] * b[20] * b[8] - b[16] * b[4] * b[36] - b[16] * b[5] * b[35] -
124
+ b[29] * b[17] * b[10] - b[29] * b[18] * b[9] - b[29] * b[19] * b[8] +
125
+ b[28] * b[4] * b[24] + b[28] * b[5] * b[23] + b[28] * b[6] * b[22] +
126
+ b[28] * b[7] * b[21] - b[28] * b[17] * b[11] - b[28] * b[18] * b[10] -
127
+ b[28] * b[19] * b[9] + b[29] * b[4] * b[23] - b[2] * b[22] * b[32] -
128
+ b[2] * b[21] * b[33] - b[1] * b[24] * b[31] + b[0] * b[18] * b[38] -
129
+ b[0] * b[24] * b[32] + b[0] * b[19] * b[37] + b[0] * b[20] * b[36] -
130
+ b[0] * b[25] * b[31] - b[0] * b[23] * b[33] + b[1] * b[19] * b[36] -
131
+ b[1] * b[22] * b[33] + b[1] * b[20] * b[35] + b[2] * b[19] * b[35] -
132
+ b[2] * b[24] * b[30] - b[2] * b[23] * b[31] + b[2] * b[20] * b[34] +
133
+ b[2] * b[17] * b[37] - b[1] * b[25] * b[30] + b[1] * b[18] * b[37] +
134
+ b[1] * b[17] * b[38] - b[1] * b[23] * b[32] + b[2] * b[18] * b[36];
135
+ coeffs(6) =
136
+ -b[14] * b[6] * b[37] - b[14] * b[7] * b[36] + b[14] * b[31] * b[12] +
137
+ b[3] * b[17] * b[37] - b[3] * b[23] * b[31] - b[3] * b[24] * b[30] -
138
+ b[3] * b[21] * b[33] + b[3] * b[20] * b[34] + b[3] * b[19] * b[35] +
139
+ b[3] * b[18] * b[36] - b[3] * b[22] * b[32] + b[13] * b[32] * b[12] +
140
+ b[13] * b[33] * b[11] - b[15] * b[6] * b[36] - b[15] * b[7] * b[35] +
141
+ b[15] * b[31] * b[11] + b[15] * b[30] * b[12] + b[16] * b[32] * b[9] +
142
+ b[16] * b[33] * b[8] - b[13] * b[6] * b[38] - b[13] * b[7] * b[37] +
143
+ b[14] * b[32] * b[11] + b[14] * b[33] * b[10] - b[14] * b[5] * b[38] -
144
+ b[16] * b[6] * b[35] - b[16] * b[7] * b[34] + b[16] * b[30] * b[11] +
145
+ b[16] * b[31] * b[10] - b[26] * b[19] * b[12] - b[26] * b[20] * b[11] +
146
+ b[26] * b[6] * b[25] + b[26] * b[7] * b[24] + b[15] * b[32] * b[10] +
147
+ b[15] * b[33] * b[9] - b[15] * b[4] * b[38] - b[15] * b[5] * b[37] +
148
+ b[29] * b[5] * b[23] + b[29] * b[6] * b[22] + b[29] * b[7] * b[21] -
149
+ b[27] * b[20] * b[10] + b[27] * b[5] * b[25] + b[27] * b[6] * b[24] +
150
+ b[27] * b[7] * b[23] - b[27] * b[18] * b[12] - b[27] * b[19] * b[11] -
151
+ b[28] * b[20] * b[9] - b[16] * b[4] * b[37] - b[16] * b[5] * b[36] +
152
+ b[0] * b[19] * b[38] - b[0] * b[24] * b[33] + b[0] * b[20] * b[37] -
153
+ b[29] * b[17] * b[11] - b[29] * b[18] * b[10] - b[29] * b[19] * b[9] +
154
+ b[28] * b[4] * b[25] + b[28] * b[5] * b[24] + b[28] * b[6] * b[23] +
155
+ b[28] * b[7] * b[22] - b[28] * b[17] * b[12] - b[28] * b[18] * b[11] -
156
+ b[28] * b[19] * b[10] - b[29] * b[20] * b[8] + b[29] * b[4] * b[24] +
157
+ b[2] * b[18] * b[37] - b[0] * b[25] * b[32] + b[1] * b[18] * b[38] -
158
+ b[1] * b[24] * b[32] + b[1] * b[19] * b[37] + b[1] * b[20] * b[36] -
159
+ b[1] * b[25] * b[31] + b[2] * b[17] * b[38] + b[2] * b[19] * b[36] -
160
+ b[2] * b[24] * b[31] - b[2] * b[22] * b[33] - b[2] * b[23] * b[32] +
161
+ b[2] * b[20] * b[35] - b[1] * b[23] * b[33] - b[2] * b[25] * b[30];
162
+ coeffs(7) =
163
+ -b[14] * b[6] * b[38] - b[14] * b[7] * b[37] + b[3] * b[19] * b[36] -
164
+ b[3] * b[22] * b[33] + b[3] * b[20] * b[35] - b[3] * b[23] * b[32] -
165
+ b[3] * b[25] * b[30] + b[3] * b[17] * b[38] + b[3] * b[18] * b[37] -
166
+ b[3] * b[24] * b[31] - b[15] * b[6] * b[37] - b[15] * b[7] * b[36] +
167
+ b[15] * b[31] * b[12] + b[16] * b[32] * b[10] + b[16] * b[33] * b[9] +
168
+ b[13] * b[33] * b[12] - b[13] * b[7] * b[38] + b[14] * b[32] * b[12] +
169
+ b[14] * b[33] * b[11] - b[16] * b[6] * b[36] - b[16] * b[7] * b[35] +
170
+ b[16] * b[31] * b[11] + b[16] * b[30] * b[12] + b[15] * b[32] * b[11] +
171
+ b[15] * b[33] * b[10] - b[15] * b[5] * b[38] + b[29] * b[5] * b[24] +
172
+ b[29] * b[6] * b[23] - b[26] * b[20] * b[12] + b[26] * b[7] * b[25] -
173
+ b[27] * b[19] * b[12] - b[27] * b[20] * b[11] + b[27] * b[6] * b[25] +
174
+ b[27] * b[7] * b[24] - b[28] * b[20] * b[10] - b[16] * b[4] * b[38] -
175
+ b[16] * b[5] * b[37] + b[29] * b[7] * b[22] - b[29] * b[17] * b[12] -
176
+ b[29] * b[18] * b[11] - b[29] * b[19] * b[10] + b[28] * b[5] * b[25] +
177
+ b[28] * b[6] * b[24] + b[28] * b[7] * b[23] - b[28] * b[18] * b[12] -
178
+ b[28] * b[19] * b[11] - b[29] * b[20] * b[9] + b[29] * b[4] * b[25] -
179
+ b[2] * b[24] * b[32] + b[0] * b[20] * b[38] - b[0] * b[25] * b[33] +
180
+ b[1] * b[19] * b[38] - b[1] * b[24] * b[33] + b[1] * b[20] * b[37] -
181
+ b[2] * b[25] * b[31] + b[2] * b[20] * b[36] - b[1] * b[25] * b[32] +
182
+ b[2] * b[19] * b[37] + b[2] * b[18] * b[38] - b[2] * b[23] * b[33];
183
+ coeffs(8) =
184
+ b[3] * b[18] * b[38] - b[3] * b[24] * b[32] + b[3] * b[19] * b[37] +
185
+ b[3] * b[20] * b[36] - b[3] * b[25] * b[31] - b[3] * b[23] * b[33] -
186
+ b[15] * b[6] * b[38] - b[15] * b[7] * b[37] + b[16] * b[32] * b[11] +
187
+ b[16] * b[33] * b[10] - b[16] * b[5] * b[38] - b[16] * b[6] * b[37] -
188
+ b[16] * b[7] * b[36] + b[16] * b[31] * b[12] + b[14] * b[33] * b[12] -
189
+ b[14] * b[7] * b[38] + b[15] * b[32] * b[12] + b[15] * b[33] * b[11] +
190
+ b[29] * b[5] * b[25] + b[29] * b[6] * b[24] - b[27] * b[20] * b[12] +
191
+ b[27] * b[7] * b[25] - b[28] * b[19] * b[12] - b[28] * b[20] * b[11] +
192
+ b[29] * b[7] * b[23] - b[29] * b[18] * b[12] - b[29] * b[19] * b[11] +
193
+ b[28] * b[6] * b[25] + b[28] * b[7] * b[24] - b[29] * b[20] * b[10] +
194
+ b[2] * b[19] * b[38] - b[1] * b[25] * b[33] + b[2] * b[20] * b[37] -
195
+ b[2] * b[24] * b[33] - b[2] * b[25] * b[32] + b[1] * b[20] * b[38];
196
+ coeffs(9) =
197
+ b[29] * b[7] * b[24] - b[29] * b[20] * b[11] + b[2] * b[20] * b[38] -
198
+ b[2] * b[25] * b[33] - b[28] * b[20] * b[12] + b[28] * b[7] * b[25] -
199
+ b[29] * b[19] * b[12] - b[3] * b[24] * b[33] + b[15] * b[33] * b[12] +
200
+ b[3] * b[19] * b[38] - b[16] * b[6] * b[38] + b[3] * b[20] * b[37] +
201
+ b[16] * b[32] * b[12] + b[29] * b[6] * b[25] - b[16] * b[7] * b[37] -
202
+ b[3] * b[25] * b[32] - b[15] * b[7] * b[38] + b[16] * b[33] * b[11];
203
+ coeffs(10) = -b[29] * b[20] * b[12] + b[29] * b[7] * b[25] +
204
+ b[16] * b[33] * b[12] - b[16] * b[7] * b[38] +
205
+ b[3] * b[20] * b[38] - b[3] * b[25] * b[33];
206
+ }
colmap/include/colmap/estimators/essential_matrix_poly.h ADDED
The diff for this file is too large to render. See raw diff
 
colmap/include/colmap/estimators/euclidean_transform.h ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_EUCLIDEAN_TRANSFORM_H_
33
+ #define COLMAP_SRC_ESTIMATORS_EUCLIDEAN_TRANSFORM_H_
34
+
35
+ #include "base/similarity_transform.h"
36
+ #include "util/alignment.h"
37
+
38
+ namespace colmap {
39
+
40
+ // N-D Euclidean transform estimator from corresponding point pairs in the
41
+ // source and destination coordinate systems.
42
+ //
43
+ // This algorithm is based on the following paper:
44
+ //
45
+ // S. Umeyama. Least-Squares Estimation of Transformation Parameters
46
+ // Between Two Point Patterns. IEEE Transactions on Pattern Analysis and
47
+ // Machine Intelligence, Volume 13 Issue 4, Page 376-380, 1991.
48
+ // http://www.stanford.edu/class/cs273/refs/umeyama.pdf
49
+ //
50
+ // and uses the Eigen implementation.
51
+ template <int kDim>
52
+ using EuclideanTransformEstimator = SimilarityTransformEstimator<kDim, false>;
53
+
54
+ } // namespace colmap
55
+
56
+ #endif // COLMAP_SRC_ESTIMATORS_EUCLIDEAN_TRANSFORM_H_
colmap/include/colmap/estimators/fundamental_matrix.h ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_FUNDAMENTAL_MATRIX_H_
33
+ #define COLMAP_SRC_ESTIMATORS_FUNDAMENTAL_MATRIX_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "estimators/homography_matrix.h"
40
+ #include "util/alignment.h"
41
+ #include "util/types.h"
42
+
43
+ namespace colmap {
44
+
45
+ // Fundamental matrix estimator from corresponding point pairs.
46
+ //
47
+ // This algorithm solves the 7-Point problem and is based on the following
48
+ // paper:
49
+ //
50
+ // Zhengyou Zhang and T. Kanade, Determining the Epipolar Geometry and its
51
+ // Uncertainty: A Review, International Journal of Computer Vision, 1998.
52
+ // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.33.4540
53
+ class FundamentalMatrixSevenPointEstimator {
54
+ public:
55
+ typedef Eigen::Vector2d X_t;
56
+ typedef Eigen::Vector2d Y_t;
57
+ typedef Eigen::Matrix3d M_t;
58
+
59
+ // The minimum number of samples needed to estimate a model.
60
+ static const int kMinNumSamples = 7;
61
+
62
+ // Estimate either 1 or 3 possible fundamental matrix solutions from a set of
63
+ // corresponding points.
64
+ //
65
+ // The number of corresponding points must be exactly 7.
66
+ //
67
+ // @param points1 First set of corresponding points.
68
+ // @param points2 Second set of corresponding points
69
+ //
70
+ // @return Up to 4 solutions as a vector of 3x3 fundamental matrices.
71
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
72
+ const std::vector<Y_t>& points2);
73
+
74
+ // Calculate the residuals of a set of corresponding points and a given
75
+ // fundamental matrix.
76
+ //
77
+ // Residuals are defined as the squared Sampson error.
78
+ //
79
+ // @param points1 First set of corresponding points as Nx2 matrix.
80
+ // @param points2 Second set of corresponding points as Nx2 matrix.
81
+ // @param F 3x3 fundamental matrix.
82
+ // @param residuals Output vector of residuals.
83
+ static void Residuals(const std::vector<X_t>& points1,
84
+ const std::vector<Y_t>& points2, const M_t& F,
85
+ std::vector<double>* residuals);
86
+ };
87
+
88
+ // Fundamental matrix estimator from corresponding point pairs.
89
+ //
90
+ // This algorithm solves the 8-Point problem based on the following paper:
91
+ //
92
+ // Hartley and Zisserman, Multiple View Geometry, algorithm 11.1, page 282.
93
+ class FundamentalMatrixEightPointEstimator {
94
+ public:
95
+ typedef Eigen::Vector2d X_t;
96
+ typedef Eigen::Vector2d Y_t;
97
+ typedef Eigen::Matrix3d M_t;
98
+
99
+ // The minimum number of samples needed to estimate a model.
100
+ static const int kMinNumSamples = 8;
101
+
102
+ // Estimate fundamental matrix solutions from a set of corresponding points.
103
+ //
104
+ // The number of corresponding points must be at least 8.
105
+ //
106
+ // @param points1 First set of corresponding points.
107
+ // @param points2 Second set of corresponding points
108
+ //
109
+ // @return Single solution as a vector of 3x3 fundamental matrices.
110
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
111
+ const std::vector<Y_t>& points2);
112
+
113
+ // Calculate the residuals of a set of corresponding points and a given
114
+ // fundamental matrix.
115
+ //
116
+ // Residuals are defined as the squared Sampson error.
117
+ //
118
+ // @param points1 First set of corresponding points as Nx2 matrix.
119
+ // @param points2 Second set of corresponding points as Nx2 matrix.
120
+ // @param F 3x3 fundamental matrix.
121
+ // @param residuals Output vector of residuals.
122
+ static void Residuals(const std::vector<X_t>& points1,
123
+ const std::vector<Y_t>& points2, const M_t& F,
124
+ std::vector<double>* residuals);
125
+ };
126
+
127
+ } // namespace colmap
128
+
129
+ #endif // COLMAP_SRC_ESTIMATORS_FUNDAMENTAL_MATRIX_H_
colmap/include/colmap/estimators/generalized_absolute_pose.h ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_GENERALIZED_ABSOLUTE_POSE_H_
33
+ #define COLMAP_SRC_ESTIMATORS_GENERALIZED_ABSOLUTE_POSE_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ // Solver for the Generalized P3P problem (NP3P or GP3P), based on:
45
+ //
46
+ // Lee, Gim Hee, et al. "Minimal solutions for pose estimation of a
47
+ // multi-camera system." Robotics Research. Springer International
48
+ // Publishing, 2016. 521-538.
49
+ //
50
+ // This class is based on an original implementation by Federico Camposeco.
51
+ class GP3PEstimator {
52
+ public:
53
+ // The generalized image observations, which is composed of the relative pose
54
+ // of the specific camera in the generalized camera and its image observation.
55
+ struct X_t {
56
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
57
+ // The relative transformation from the generalized camera to the camera
58
+ // frame of the observation.
59
+ Eigen::Matrix3x4d rel_tform;
60
+ // The 2D image feature observation.
61
+ Eigen::Vector2d xy;
62
+ };
63
+
64
+ // The observed 3D feature points in the world frame.
65
+ typedef Eigen::Vector3d Y_t;
66
+ // The transformation from the world to the generalized camera frame.
67
+ typedef Eigen::Matrix3x4d M_t;
68
+
69
+ // The minimum number of samples needed to estimate a model.
70
+ static const int kMinNumSamples = 3;
71
+
72
+ enum class ResidualType {
73
+ CosineDistance,
74
+ ReprojectionError,
75
+ };
76
+
77
+ // Whether to compute the cosine similarity or the reprojection error.
78
+ // [WARNING] The reprojection error being in normalized coordinates,
79
+ // the unique error threshold of RANSAC corresponds to different pixel values
80
+ // in the different cameras of the rig if they have different intrinsics.
81
+ ResidualType residual_type = ResidualType::CosineDistance;
82
+
83
+ // Estimate the most probable solution of the GP3P problem from a set of
84
+ // three 2D-3D point correspondences.
85
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points2D,
86
+ const std::vector<Y_t>& points3D);
87
+
88
+ // Calculate the squared cosine distance error between the rays given a set of
89
+ // 2D-3D point correspondences and a projection matrix of the generalized
90
+ // camera.
91
+ void Residuals(const std::vector<X_t>& points2D,
92
+ const std::vector<Y_t>& points3D,
93
+ const M_t& proj_matrix, std::vector<double>* residuals);
94
+ };
95
+
96
+ } // namespace colmap
97
+
98
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::GP3PEstimator::X_t)
99
+
100
+ #endif // COLMAP_SRC_ESTIMATORS_GENERALIZED_ABSOLUTE_POSE_H_
colmap/include/colmap/estimators/generalized_absolute_pose_coeffs.h ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_GENERALIZED_ABSOLUTE_POSE_COEFFS_H_
33
+ #define COLMAP_SRC_ESTIMATORS_GENERALIZED_ABSOLUTE_POSE_COEFFS_H_
34
+
35
+ #include <Eigen/Core>
36
+
37
+ namespace colmap {
38
+
39
+ Eigen::Matrix<double, 9, 1> ComputeDepthsSylvesterCoeffs(
40
+ const Eigen::Matrix<double, 3, 6>& K);
41
+
42
+ } // namespace colmap
43
+
44
+ #endif // COLMAP_SRC_ESTIMATORS_GENERALIZED_ABSOLUTE_POSE_COEFFS_H_
colmap/include/colmap/estimators/generalized_relative_pose.h ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_GENERALIZED_RELATIVE_POSE_H_
33
+ #define COLMAP_SRC_ESTIMATORS_GENERALIZED_RELATIVE_POSE_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ // Solver for the Generalized Relative Pose problem using a minimal of 8 2D-2D
45
+ // correspondences. This implementation is based on:
46
+ //
47
+ // "Efficient Computation of Relative Pose for Multi-Camera Systems",
48
+ // Kneip and Li. CVPR 2014.
49
+ //
50
+ // Note that the solution to this problem is degenerate in the case of pure
51
+ // translation and when all correspondences are observed from the same cameras.
52
+ //
53
+ // The implementation is a modified and improved version of Kneip's original
54
+ // implementation in OpenGV licensed under the BSD license.
55
+ class GR6PEstimator {
56
+ public:
57
+ // The generalized image observations of the left camera, which is composed of
58
+ // the relative pose of the specific camera in the generalized camera and its
59
+ // image observation.
60
+ struct X_t {
61
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
62
+ // The relative transformation from the generalized camera to the camera
63
+ // frame of the observation.
64
+ Eigen::Matrix3x4d rel_tform;
65
+ // The 2D image feature observation.
66
+ Eigen::Vector2d xy;
67
+ };
68
+
69
+ // The normalized image feature points in the left camera.
70
+ typedef X_t Y_t;
71
+ // The relative transformation between the two generalized cameras.
72
+ typedef Eigen::Matrix3x4d M_t;
73
+
74
+ // The minimum number of samples needed to estimate a model. Note that in
75
+ // theory the minimum required number of samples is 6 but Laurent Kneip showed
76
+ // in his paper that using 8 samples is more stable.
77
+ static const int kMinNumSamples = 8;
78
+
79
+ // Estimate the most probable solution of the GR6P problem from a set of
80
+ // six 2D-2D point correspondences.
81
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
82
+ const std::vector<Y_t>& points2);
83
+
84
+ // Calculate the squared Sampson error between corresponding points.
85
+ static void Residuals(const std::vector<X_t>& points1,
86
+ const std::vector<Y_t>& points2, const M_t& proj_matrix,
87
+ std::vector<double>* residuals);
88
+ };
89
+
90
+ } // namespace colmap
91
+
92
+ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_CUSTOM(colmap::GR6PEstimator::X_t)
93
+
94
+ #endif // COLMAP_SRC_ESTIMATORS_GENERALIZED_RELATIVE_POSE_H_
colmap/include/colmap/estimators/homography_matrix.h ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_HOMOGRAPHY_MATRIX_H_
33
+ #define COLMAP_SRC_ESTIMATORS_HOMOGRAPHY_MATRIX_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include "util/alignment.h"
40
+ #include "util/types.h"
41
+
42
+ namespace colmap {
43
+
44
+ // Direct linear transformation algorithm to compute the homography between
45
+ // point pairs. This algorithm computes the least squares estimate for
46
+ // the homography from at least 4 correspondences.
47
+ class HomographyMatrixEstimator {
48
+ public:
49
+ typedef Eigen::Vector2d X_t;
50
+ typedef Eigen::Vector2d Y_t;
51
+ typedef Eigen::Matrix3d M_t;
52
+
53
+ // The minimum number of samples needed to estimate a model.
54
+ static const int kMinNumSamples = 4;
55
+
56
+ // Estimate the projective transformation (homography).
57
+ //
58
+ // The number of corresponding points must be at least 4.
59
+ //
60
+ // @param points1 First set of corresponding points.
61
+ // @param points2 Second set of corresponding points.
62
+ //
63
+ // @return 3x3 homogeneous transformation matrix.
64
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
65
+ const std::vector<Y_t>& points2);
66
+
67
+ // Calculate the transformation error for each corresponding point pair.
68
+ //
69
+ // Residuals are defined as the squared transformation error when
70
+ // transforming the source to the destination coordinates.
71
+ //
72
+ // @param points1 First set of corresponding points.
73
+ // @param points2 Second set of corresponding points.
74
+ // @param H 3x3 projective matrix.
75
+ // @param residuals Output vector of residuals.
76
+ static void Residuals(const std::vector<X_t>& points1,
77
+ const std::vector<Y_t>& points2, const M_t& H,
78
+ std::vector<double>* residuals);
79
+ };
80
+
81
+ } // namespace colmap
82
+
83
+ #endif // COLMAP_SRC_ESTIMATORS_HOMOGRAPHY_MATRIX_H_
colmap/include/colmap/estimators/pose.h ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_POSE_H_
33
+ #define COLMAP_SRC_ESTIMATORS_POSE_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+
39
+ #include <ceres/ceres.h>
40
+
41
+ #include "base/camera.h"
42
+ #include "base/camera_models.h"
43
+ #include "optim/loransac.h"
44
+ #include "util/alignment.h"
45
+ #include "util/logging.h"
46
+ #include "util/threading.h"
47
+ #include "util/types.h"
48
+
49
+ namespace colmap {
50
+
51
+ struct AbsolutePoseEstimationOptions {
52
+ // Whether to estimate the focal length.
53
+ bool estimate_focal_length = false;
54
+
55
+ // Number of discrete samples for focal length estimation.
56
+ size_t num_focal_length_samples = 30;
57
+
58
+ // Minimum focal length ratio for discrete focal length sampling
59
+ // around focal length of given camera.
60
+ double min_focal_length_ratio = 0.2;
61
+
62
+ // Maximum focal length ratio for discrete focal length sampling
63
+ // around focal length of given camera.
64
+ double max_focal_length_ratio = 5;
65
+
66
+ // Number of threads for parallel estimation of focal length.
67
+ int num_threads = ThreadPool::kMaxNumThreads;
68
+
69
+ // Options used for P3P RANSAC.
70
+ RANSACOptions ransac_options;
71
+
72
+ void Check() const {
73
+ CHECK_GT(num_focal_length_samples, 0);
74
+ CHECK_GT(min_focal_length_ratio, 0);
75
+ CHECK_GT(max_focal_length_ratio, 0);
76
+ CHECK_LT(min_focal_length_ratio, max_focal_length_ratio);
77
+ ransac_options.Check();
78
+ }
79
+ };
80
+
81
+ struct AbsolutePoseRefinementOptions {
82
+ // Convergence criterion.
83
+ double gradient_tolerance = 1.0;
84
+
85
+ // Maximum number of solver iterations.
86
+ int max_num_iterations = 100;
87
+
88
+ // Scaling factor determines at which residual robustification takes place.
89
+ double loss_function_scale = 1.0;
90
+
91
+ // Whether to refine the focal length parameter group.
92
+ bool refine_focal_length = true;
93
+
94
+ // Whether to refine the extra parameter group.
95
+ bool refine_extra_params = true;
96
+
97
+ // Whether to print final summary.
98
+ bool print_summary = true;
99
+
100
+ void Check() const {
101
+ CHECK_GE(gradient_tolerance, 0.0);
102
+ CHECK_GE(max_num_iterations, 0);
103
+ CHECK_GE(loss_function_scale, 0.0);
104
+ }
105
+ };
106
+
107
+ // Estimate absolute pose (optionally focal length) from 2D-3D correspondences.
108
+ //
109
+ // Focal length estimation is performed using discrete sampling around the
110
+ // focal length of the given camera. The focal length that results in the
111
+ // maximal number of inliers is assigned to the given camera.
112
+ //
113
+ // @param options Absolute pose estimation options.
114
+ // @param points2D Corresponding 2D points.
115
+ // @param points3D Corresponding 3D points.
116
+ // @param qvec Estimated rotation component as
117
+ // unit Quaternion coefficients (w, x, y, z).
118
+ // @param tvec Estimated translation component.
119
+ // @param camera Camera for which to estimate pose. Modified
120
+ // in-place to store the estimated focal length.
121
+ // @param num_inliers Number of inliers in RANSAC.
122
+ // @param inlier_mask Inlier mask for 2D-3D correspondences.
123
+ //
124
+ // @return Whether pose is estimated successfully.
125
+ bool EstimateAbsolutePose(const AbsolutePoseEstimationOptions& options,
126
+ const std::vector<Eigen::Vector2d>& points2D,
127
+ const std::vector<Eigen::Vector3d>& points3D,
128
+ Eigen::Vector4d* qvec, Eigen::Vector3d* tvec,
129
+ Camera* camera, size_t* num_inliers,
130
+ std::vector<char>* inlier_mask);
131
+
132
+ // Estimate relative from 2D-2D correspondences.
133
+ //
134
+ // Pose of first camera is assumed to be at the origin without rotation. Pose
135
+ // of second camera is given as world-to-image transformation,
136
+ // i.e. `x2 = [R | t] * X2`.
137
+ //
138
+ // @param ransac_options RANSAC options.
139
+ // @param points1 Corresponding 2D points.
140
+ // @param points2 Corresponding 2D points.
141
+ // @param qvec Estimated rotation component as
142
+ // unit Quaternion coefficients (w, x, y, z).
143
+ // @param tvec Estimated translation component.
144
+ //
145
+ // @return Number of RANSAC inliers.
146
+ size_t EstimateRelativePose(const RANSACOptions& ransac_options,
147
+ const std::vector<Eigen::Vector2d>& points1,
148
+ const std::vector<Eigen::Vector2d>& points2,
149
+ Eigen::Vector4d* qvec, Eigen::Vector3d* tvec);
150
+
151
+ // Refine absolute pose (optionally focal length) from 2D-3D correspondences.
152
+ //
153
+ // @param options Refinement options.
154
+ // @param inlier_mask Inlier mask for 2D-3D correspondences.
155
+ // @param points2D Corresponding 2D points.
156
+ // @param points3D Corresponding 3D points.
157
+ // @param qvec Estimated rotation component as
158
+ // unit Quaternion coefficients (w, x, y, z).
159
+ // @param tvec Estimated translation component.
160
+ // @param camera Camera for which to estimate pose. Modified
161
+ // in-place to store the estimated focal length.
162
+ // @param rot_tvec_covariance Estimated 6x6 covariance matrix of
163
+ // the rotation (as axis-angle, in tangent space)
164
+ // and translation terms (optional).
165
+ //
166
+ // @return Whether the solution is usable.
167
+ bool RefineAbsolutePose(const AbsolutePoseRefinementOptions& options,
168
+ const std::vector<char>& inlier_mask,
169
+ const std::vector<Eigen::Vector2d>& points2D,
170
+ const std::vector<Eigen::Vector3d>& points3D,
171
+ Eigen::Vector4d* qvec, Eigen::Vector3d* tvec,
172
+ Camera* camera,
173
+ Eigen::Matrix6d* rot_tvec_covariance = nullptr);
174
+
175
+ // Refine relative pose of two cameras.
176
+ //
177
+ // Minimizes the Sampson error between corresponding normalized points using
178
+ // a robust cost function, i.e. the corresponding points need not necessarily
179
+ // be inliers given a sufficient initial guess for the relative pose.
180
+ //
181
+ // Assumes that first camera pose has projection matrix P = [I | 0], and
182
+ // pose of second camera is given as transformation from world to camera system.
183
+ //
184
+ // Assumes that the given translation vector is normalized, and refines
185
+ // the translation up to an unknown scale (i.e. refined translation vector
186
+ // is a unit vector again).
187
+ //
188
+ // @param options Solver options.
189
+ // @param points1 First set of corresponding points.
190
+ // @param points2 Second set of corresponding points.
191
+ // @param qvec Unit Quaternion rotation coefficients (w, x, y, z).
192
+ // @param tvec 3x1 translation vector.
193
+ //
194
+ // @return Flag indicating if solution is usable.
195
+ bool RefineRelativePose(const ceres::Solver::Options& options,
196
+ const std::vector<Eigen::Vector2d>& points1,
197
+ const std::vector<Eigen::Vector2d>& points2,
198
+ Eigen::Vector4d* qvec, Eigen::Vector3d* tvec);
199
+
200
+ // Refine generalized absolute pose (optionally focal lengths)
201
+ // from 2D-3D correspondences.
202
+ //
203
+ // @param options Refinement options.
204
+ // @param inlier_mask Inlier mask for 2D-3D correspondences.
205
+ // @param points2D Corresponding 2D points.
206
+ // @param points3D Corresponding 3D points.
207
+ // @param camera_idxs Index of the rig camera for each correspondence.
208
+ // @param rig_qvecs Relative rotations from rig to each camera frame
209
+ // @param rig_tvecs Relative translations from rig
210
+ // to each camera frame.
211
+ // @param qvec Estimated rotation component of the rig as
212
+ // unit Quaternion coefficients (w, x, y, z).
213
+ // @param tvec Estimated translation component of the rig.
214
+ // @param cameras Cameras for which to estimate pose. Modified
215
+ // in-place to store the estimated focal lengths.
216
+ // @param rot_tvec_covariance Estimated 6x6 covariance matrix of
217
+ // the rotation (as axis-angle, in tangent space)
218
+ // and translation terms (optional).
219
+ //
220
+ // @return Whether the solution is usable.
221
+ bool RefineGeneralizedAbsolutePose(
222
+ const AbsolutePoseRefinementOptions& options,
223
+ const std::vector<char>& inlier_mask,
224
+ const std::vector<Eigen::Vector2d>& points2D,
225
+ const std::vector<Eigen::Vector3d>& points3D,
226
+ const std::vector<size_t>& camera_idxs,
227
+ const std::vector<Eigen::Vector4d>& rig_qvecs,
228
+ const std::vector<Eigen::Vector3d>& rig_tvecs, Eigen::Vector4d* qvec,
229
+ Eigen::Vector3d* tvec, std::vector<Camera>* cameras,
230
+ Eigen::Matrix6d* rot_tvec_covariance = nullptr);
231
+
232
+ } // namespace colmap
233
+
234
+ #endif // COLMAP_SRC_ESTIMATORS_POSE_H_
colmap/include/colmap/estimators/similarity_transform.h ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_ESTIMATORS_SIMILARITY_TRANSFORM_H_
33
+ #define COLMAP_SRC_ESTIMATORS_SIMILARITY_TRANSFORM_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+ #include <Eigen/Geometry>
39
+
40
+ #include "base/projection.h"
41
+ #include "util/alignment.h"
42
+ #include "util/logging.h"
43
+ #include "util/types.h"
44
+
45
+ namespace colmap {
46
+
47
+ // N-D similarity transform estimator from corresponding point pairs in the
48
+ // source and destination coordinate systems.
49
+ //
50
+ // This algorithm is based on the following paper:
51
+ //
52
+ // S. Umeyama. Least-Squares Estimation of Transformation Parameters
53
+ // Between Two Point Patterns. IEEE Transactions on Pattern Analysis and
54
+ // Machine Intelligence, Volume 13 Issue 4, Page 376-380, 1991.
55
+ // http://www.stanford.edu/class/cs273/refs/umeyama.pdf
56
+ //
57
+ // and uses the Eigen implementation.
58
+ template <int kDim, bool kEstimateScale = true>
59
+ class SimilarityTransformEstimator {
60
+ public:
61
+ typedef Eigen::Matrix<double, kDim, 1> X_t;
62
+ typedef Eigen::Matrix<double, kDim, 1> Y_t;
63
+ typedef Eigen::Matrix<double, kDim, kDim + 1> M_t;
64
+
65
+ // The minimum number of samples needed to estimate a model. Note that
66
+ // this only returns the true minimal sample in the two-dimensional case.
67
+ // For higher dimensions, the system will alway be over-determined.
68
+ static const int kMinNumSamples = kDim;
69
+
70
+ // Estimate the similarity transform.
71
+ //
72
+ // @param src Set of corresponding source points.
73
+ // @param dst Set of corresponding destination points.
74
+ //
75
+ // @return 4x4 homogeneous transformation matrix.
76
+ static std::vector<M_t> Estimate(const std::vector<X_t>& src,
77
+ const std::vector<Y_t>& dst);
78
+
79
+ // Calculate the transformation error for each corresponding point pair.
80
+ //
81
+ // Residuals are defined as the squared transformation error when
82
+ // transforming the source to the destination coordinates.
83
+ //
84
+ // @param src Set of corresponding points in the source coordinate
85
+ // system as a Nx3 matrix.
86
+ // @param dst Set of corresponding points in the destination
87
+ // coordinate system as a Nx3 matrix.
88
+ // @param matrix 4x4 homogeneous transformation matrix.
89
+ // @param residuals Output vector of residuals for each point pair.
90
+ static void Residuals(const std::vector<X_t>& src,
91
+ const std::vector<Y_t>& dst, const M_t& matrix,
92
+ std::vector<double>* residuals);
93
+ };
94
+
95
+ ////////////////////////////////////////////////////////////////////////////////
96
+ // Implementation
97
+ ////////////////////////////////////////////////////////////////////////////////
98
+
99
+ template <int kDim, bool kEstimateScale>
100
+ std::vector<typename SimilarityTransformEstimator<kDim, kEstimateScale>::M_t>
101
+ SimilarityTransformEstimator<kDim, kEstimateScale>::Estimate(
102
+ const std::vector<X_t>& src, const std::vector<Y_t>& dst) {
103
+ CHECK_EQ(src.size(), dst.size());
104
+
105
+ Eigen::Matrix<double, kDim, Eigen::Dynamic> src_mat(kDim, src.size());
106
+ Eigen::Matrix<double, kDim, Eigen::Dynamic> dst_mat(kDim, dst.size());
107
+ for (size_t i = 0; i < src.size(); ++i) {
108
+ src_mat.col(i) = src[i];
109
+ dst_mat.col(i) = dst[i];
110
+ }
111
+
112
+ const M_t model = Eigen::umeyama(src_mat, dst_mat, kEstimateScale)
113
+ .topLeftCorner(kDim, kDim + 1);
114
+
115
+ if (model.array().isNaN().any()) {
116
+ return std::vector<M_t>{};
117
+ }
118
+
119
+ return {model};
120
+ }
121
+
122
+ template <int kDim, bool kEstimateScale>
123
+ void SimilarityTransformEstimator<kDim, kEstimateScale>::Residuals(
124
+ const std::vector<X_t>& src, const std::vector<Y_t>& dst, const M_t& matrix,
125
+ std::vector<double>* residuals) {
126
+ CHECK_EQ(src.size(), dst.size());
127
+
128
+ residuals->resize(src.size());
129
+
130
+ for (size_t i = 0; i < src.size(); ++i) {
131
+ const Y_t dst_transformed = matrix * src[i].homogeneous();
132
+ (*residuals)[i] = (dst[i] - dst_transformed).squaredNorm();
133
+ }
134
+ }
135
+
136
+ } // namespace colmap
137
+
138
+ #endif // COLMAP_SRC_ESTIMATORS_SIMILARITY_TRANSFORM_H_
colmap/include/colmap/estimators/translation_transform.h ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2023, 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
+ #ifndef COLMAP_SRC_BASE_SIMILARITY_TRANSFORM_H_
33
+ #define COLMAP_SRC_BASE_SIMILARITY_TRANSFORM_H_
34
+
35
+ #include <vector>
36
+
37
+ #include <Eigen/Core>
38
+ #include <Eigen/Geometry>
39
+
40
+ #include "util/alignment.h"
41
+ #include "util/logging.h"
42
+ #include "util/types.h"
43
+
44
+ namespace colmap {
45
+
46
+ // Estimate a N-D translation transformation between point pairs.
47
+ template <int kDim>
48
+ class TranslationTransformEstimator {
49
+ public:
50
+ typedef Eigen::Matrix<double, kDim, 1> X_t;
51
+ typedef Eigen::Matrix<double, kDim, 1> Y_t;
52
+ typedef Eigen::Matrix<double, kDim, 1> M_t;
53
+
54
+ // The minimum number of samples needed to estimate a model.
55
+ static const int kMinNumSamples = 1;
56
+
57
+ // Estimate the 2D translation transform.
58
+ //
59
+ // @param points1 Set of corresponding source 2D points.
60
+ // @param points2 Set of corresponding destination 2D points.
61
+ //
62
+ // @return Translation vector.
63
+ static std::vector<M_t> Estimate(const std::vector<X_t>& points1,
64
+ const std::vector<Y_t>& points2);
65
+
66
+ // Calculate the squared translation error.
67
+ //
68
+ // @param points1 Set of corresponding source 2D points.
69
+ // @param points2 Set of corresponding destination 2D points.
70
+ // @param translation Translation vector.
71
+ // @param residuals Output vector of residuals for each point pair.
72
+ static void Residuals(const std::vector<X_t>& points1,
73
+ const std::vector<Y_t>& points2, const M_t& translation,
74
+ std::vector<double>* residuals);
75
+ };
76
+
77
+ ////////////////////////////////////////////////////////////////////////////////
78
+ // Implementation
79
+ ////////////////////////////////////////////////////////////////////////////////
80
+
81
+ template <int kDim>
82
+ std::vector<typename TranslationTransformEstimator<kDim>::M_t>
83
+ TranslationTransformEstimator<kDim>::Estimate(const std::vector<X_t>& points1,
84
+ const std::vector<Y_t>& points2) {
85
+ CHECK_EQ(points1.size(), points2.size());
86
+
87
+ X_t mean_src = X_t::Zero();
88
+ Y_t mean_dst = Y_t::Zero();
89
+
90
+ for (size_t i = 0; i < points1.size(); ++i) {
91
+ mean_src += points1[i];
92
+ mean_dst += points2[i];
93
+ }
94
+
95
+ mean_src /= points1.size();
96
+ mean_dst /= points2.size();
97
+
98
+ std::vector<M_t> models(1);
99
+ models[0] = mean_dst - mean_src;
100
+
101
+ return models;
102
+ }
103
+
104
+ template <int kDim>
105
+ void TranslationTransformEstimator<kDim>::Residuals(
106
+ const std::vector<X_t>& points1, const std::vector<Y_t>& points2,
107
+ const M_t& translation, std::vector<double>* residuals) {
108
+ CHECK_EQ(points1.size(), points2.size());
109
+
110
+ residuals->resize(points1.size());
111
+
112
+ for (size_t i = 0; i < points1.size(); ++i) {
113
+ const M_t diff = points2[i] - points1[i] - translation;
114
+ (*residuals)[i] = diff.squaredNorm();
115
+ }
116
+ }
117
+
118
+ } // namespace colmap
119
+
120
+ #endif // COLMAP_SRC_BASE_SIMILARITY_TRANSFORM_H_