46 void SortAndAppendNextImages(std::vector<std::pair<image_t, float>> image_ranks,
47 std::vector<image_t>* sorted_images_ids) {
48 std::sort(image_ranks.begin(), image_ranks.end(),
49 [](
const std::pair<image_t, float>& image1,
50 const std::pair<image_t, float>& image2) {
51 return image1.second > image2.second;
54 sorted_images_ids->reserve(sorted_images_ids->size() + image_ranks.size());
55 for (
const auto&
image : image_ranks) {
56 sorted_images_ids->push_back(
image.first);
62 float RankNextImageMaxVisiblePointsNum(
const Image&
image) {
63 return static_cast<float>(
image.NumVisiblePoints3D());
66 float RankNextImageMaxVisiblePointsRatio(
const Image&
image) {
67 return static_cast<float>(
image.NumVisiblePoints3D()) /
68 static_cast<float>(
image.NumObservations());
71 float RankNextImageMinUncertainty(
const Image&
image) {
72 return static_cast<float>(
image.Point3DVisibilityScore());
100 : database_cache_(database_cache),
101 reconstruction_(nullptr),
102 triangulator_(nullptr),
103 num_total_reg_images_(0),
104 num_shared_reg_images_(0),
108 CHECK(reconstruction_ ==
nullptr);
109 reconstruction_ = reconstruction;
110 reconstruction_->
Load(*database_cache_);
115 num_shared_reg_images_ = 0;
116 num_reg_images_per_camera_.clear();
118 RegisterImageEvent(image_id);
121 existing_image_ids_ =
122 std::unordered_set<image_t>(reconstruction->
RegImageIds().begin(),
128 filtered_images_.clear();
129 num_reg_trials_.clear();
133 CHECK_NOTNULL(reconstruction_);
137 DeRegisterImageEvent(image_id);
142 reconstruction_ =
nullptr;
143 triangulator_.reset();
149 CHECK(options.
Check());
151 std::vector<image_t> image_ids1;
157 image_ids1.push_back(*image_id1);
163 image_ids1.push_back(*image_id2);
166 image_ids1 = FindFirstInitialImage(options);
170 for (
size_t i1 = 0; i1 < image_ids1.size(); ++i1) {
171 *image_id1 = image_ids1[i1];
173 const std::vector<image_t> image_ids2 =
174 FindSecondInitialImage(options, *image_id1);
176 for (
size_t i2 = 0; i2 < image_ids2.size(); ++i2) {
177 *image_id2 = image_ids2[i2];
183 if (init_image_pairs_.count(pair_id) > 0) {
187 init_image_pairs_.insert(pair_id);
189 if (EstimateInitialTwoViewGeometry(options, *image_id1,
204 CHECK_NOTNULL(reconstruction_);
205 CHECK(options.
Check());
207 std::function<
float(
const Image&)> rank_image_func;
210 rank_image_func = RankNextImageMaxVisiblePointsNum;
213 rank_image_func = RankNextImageMaxVisiblePointsRatio;
216 rank_image_func = RankNextImageMinUncertainty;
220 std::vector<std::pair<image_t, float>> image_ranks;
221 std::vector<std::pair<image_t, float>> other_image_ranks;
224 for (
const auto&
image : reconstruction_->
Images()) {
226 if (
image.second.IsRegistered()) {
231 if (
image.second.NumVisiblePoints3D() <
237 const size_t num_reg_trials = num_reg_trials_[
image.first];
238 if (num_reg_trials >=
static_cast<size_t>(options.
max_reg_trials)) {
244 const float rank = rank_image_func(
image.second);
245 if (filtered_images_.count(
image.first) == 0 && num_reg_trials == 0) {
246 image_ranks.emplace_back(
image.first, rank);
248 other_image_ranks.emplace_back(
image.first, rank);
252 std::vector<image_t> ranked_images_ids;
253 SortAndAppendNextImages(image_ranks, &ranked_images_ids);
254 SortAndAppendNextImages(other_image_ranks, &ranked_images_ids);
256 return ranked_images_ids;
262 CHECK_NOTNULL(reconstruction_);
265 CHECK(options.
Check());
267 init_num_reg_trials_[image_id1] += 1;
268 init_num_reg_trials_[image_id2] += 1;
269 num_reg_trials_[image_id1] += 1;
270 num_reg_trials_[image_id2] += 1;
274 init_image_pairs_.insert(pair_id);
276 Image& image1 = reconstruction_->
Image(image_id1);
279 Image& image2 = reconstruction_->
Image(image_id2);
286 if (!EstimateInitialTwoViewGeometry(options, image_id1, image_id2)) {
291 image1.
Tvec() = Eigen::Vector3d(0, 0, 0);
292 image2.
Qvec() = prev_init_two_view_geometry_.
qvec;
293 image2.
Tvec() = prev_init_two_view_geometry_.
tvec;
306 RegisterImageEvent(image_id1);
307 RegisterImageEvent(image_id2);
324 for (
const auto& corr : corrs) {
325 const Eigen::Vector2d point1_N =
327 const Eigen::Vector2d point2_N =
330 proj_matrix1, proj_matrix2, point1_N, point2_N);
331 const double tri_angle =
333 if (tri_angle >= min_tri_angle_rad &&
347 CHECK_NOTNULL(reconstruction_);
350 CHECK(options.
Check());
355 CHECK(!
image.IsRegistered()) <<
"Image cannot be registered multiple times";
357 num_reg_trials_[image_id] += 1;
360 if (
image.NumVisiblePoints3D() <
369 const int kCorrTransitivity = 1;
371 std::vector<std::pair<point2D_t, point3D_t>> tri_corrs;
372 std::vector<Eigen::Vector2d> tri_points2D;
373 std::vector<Eigen::Vector3d> tri_points3D;
375 for (
point2D_t point2D_idx = 0; point2D_idx <
image.NumPoints2D();
380 const std::vector<CorrespondenceGraph::Correspondence> corrs =
382 image_id, point2D_idx, kCorrTransitivity);
384 std::unordered_set<point3D_t> point3D_ids;
386 for (
const auto corr : corrs) {
387 if (!reconstruction_->
ExistsImage(corr.image_id)) {
388 std::cout <<
"[IncrementalMapper::RegisterNextImage] Image "
389 << corr.image_id <<
" does not exist" <<
std::endl;
393 const Image& corr_image = reconstruction_->
Image(corr.image_id);
398 const Point2D& corr_point2D = corr_image.
Point2D(corr.point2D_idx);
404 if (point3D_ids.count(corr_point2D.
Point3DId()) > 0) {
408 const Camera& corr_camera =
421 tri_corrs.emplace_back(point2D_idx, corr_point2D.
Point3DId());
422 point3D_ids.insert(corr_point2D.
Point3DId());
423 tri_points2D.push_back(point2D.
XY());
424 tri_points3D.push_back(point3D.
XYZ());
431 if (tri_points2D.size() <
460 if (num_reg_images_per_camera_[
image.CameraId()] > 0) {
498 std::vector<char> inlier_mask;
502 &num_inliers, &inlier_mask)) {
515 tri_points2D, tri_points3D, &
image.Qvec(),
516 &
image.Tvec(), &camera)) {
525 RegisterImageEvent(image_id);
527 for (
size_t i = 0; i < inlier_mask.size(); ++i) {
528 if (inlier_mask[i]) {
529 const point2D_t point2D_idx = tri_corrs[i].first;
532 const point3D_t point3D_id = tri_corrs[i].second;
535 triangulator_->AddModifiedPoint3D(point3D_id);
546 CHECK_NOTNULL(reconstruction_);
547 return triangulator_->TriangulateImage(tri_options, image_id);
552 CHECK_NOTNULL(reconstruction_);
553 return triangulator_->Retriangulate(tri_options);
558 CHECK_NOTNULL(reconstruction_);
559 return triangulator_->CompleteAllTracks(tri_options);
564 CHECK_NOTNULL(reconstruction_);
565 return triangulator_->MergeAllTracks(tri_options);
574 const std::unordered_set<point3D_t>& point3D_ids) {
575 CHECK_NOTNULL(reconstruction_);
576 CHECK(options.
Check());
581 const std::vector<image_t> local_bundle =
582 FindLocalBundle(options, image_id);
585 if (local_bundle.size() > 0) {
588 for (
const image_t local_image_id : local_bundle) {
594 for (
const image_t local_image_id : local_bundle) {
595 if (existing_image_ids_.count(local_image_id)) {
603 std::unordered_map<camera_t, size_t> num_images_per_camera;
606 num_images_per_camera[
image.CameraId()] += 1;
609 for (
const auto& camera_id_and_num_images_pair :
610 num_images_per_camera) {
611 const size_t num_reg_images_for_camera =
612 num_reg_images_per_camera_.at(
613 camera_id_and_num_images_pair.first);
614 if (camera_id_and_num_images_pair.second <
615 num_reg_images_for_camera) {
617 camera_id_and_num_images_pair.first);
623 if (local_bundle.size() == 1) {
626 }
else if (local_bundle.size() > 1) {
627 const image_t image_id1 = local_bundle[local_bundle.size() - 1];
628 const image_t image_id2 = local_bundle[local_bundle.size() - 2];
631 !existing_image_ids_.count(image_id2)) {
641 std::unordered_set<point3D_t> variable_point3D_ids;
642 for (
const point3D_t point3D_id : point3D_ids) {
644 const size_t kMaxTrackLength = 15;
648 variable_point3D_ids.insert(point3D_id);
654 bundle_adjuster.
Solve(reconstruction_);
657 bundle_adjuster.
Summary().num_residuals / 2;
661 triangulator_->MergeTracks(tri_options, variable_point3D_ids);
667 tri_options, variable_point3D_ids);
669 triangulator_->CompleteImage(tri_options, image_id);
676 std::unordered_set<image_t> filter_image_ids;
677 filter_image_ids.insert(image_id);
678 filter_image_ids.insert(local_bundle.begin(), local_bundle.end());
691 CHECK_NOTNULL(reconstruction_);
693 const std::vector<image_t>& reg_image_ids = reconstruction_->
RegImageIds();
695 CHECK_GE(reg_image_ids.size(), 2) <<
"At least two images must be "
696 "registered for global "
704 for (
const image_t image_id : reg_image_ids) {
710 for (
const image_t image_id : reg_image_ids) {
711 if (existing_image_ids_.count(image_id)) {
720 !existing_image_ids_.count(reg_image_ids[1])) {
726 if (!bundle_adjuster.
Solve(reconstruction_)) {
738 bool IncrementalMapper::AdjustParallelGlobalBundle(
740 const ParallelBundleAdjuster::Options& parallel_ba_options) {
741 CHECK_NOTNULL(reconstruction_);
743 const std::vector<image_t>& reg_image_ids = reconstruction_->
RegImageIds();
745 CHECK_GE(reg_image_ids.size(), 2)
746 <<
"At least two images must be registered for global "
754 for (
const image_t image_id : reg_image_ids) {
759 ParallelBundleAdjuster bundle_adjuster(parallel_ba_options, ba_options,
761 if (!bundle_adjuster.Solve(reconstruction_)) {
774 CHECK_NOTNULL(reconstruction_);
775 CHECK(options.
Check());
780 const size_t kMinNumImages = 20;
785 const std::vector<image_t> image_ids = reconstruction_->
FilterImages(
789 for (
const image_t image_id : image_ids) {
790 DeRegisterImageEvent(image_id);
791 filtered_images_.insert(image_id);
794 return image_ids.size();
798 CHECK_NOTNULL(reconstruction_);
799 CHECK(options.
Check());
805 CHECK_NOTNULL(reconstruction_);
806 return *reconstruction_;
810 return num_total_reg_images_;
814 return num_shared_reg_images_;
818 return triangulator_->GetModifiedPoints3D();
822 triangulator_->ClearModifiedPoints3D();
825 std::vector<image_t> IncrementalMapper::FindFirstInitialImage(
826 const Options& options)
const {
830 bool prior_focal_length;
834 const size_t init_max_reg_trials =
835 static_cast<size_t>(options.init_max_reg_trials);
839 std::vector<ImageInfo> image_infos;
840 image_infos.reserve(reconstruction_->
NumImages());
841 for (
const auto&
image : reconstruction_->
Images()) {
843 if (
image.second.NumCorrespondences() == 0) {
848 if (init_num_reg_trials_.count(
image.first) &&
849 init_num_reg_trials_.at(
image.first) >= init_max_reg_trials) {
855 if (num_registrations_.count(
image.first) > 0 &&
856 num_registrations_.at(
image.first) > 0) {
860 const class Camera& camera =
862 ImageInfo image_info;
863 image_info.image_id =
image.first;
864 image_info.prior_focal_length = camera.HasPriorFocalLength();
865 image_info.num_correspondences =
image.second.NumCorrespondences();
866 image_infos.push_back(image_info);
871 std::sort(image_infos.begin(), image_infos.end(),
872 [](
const ImageInfo& image_info1,
const ImageInfo& image_info2) {
873 if (image_info1.prior_focal_length &&
874 !image_info2.prior_focal_length) {
876 }
else if (!image_info1.prior_focal_length &&
877 image_info2.prior_focal_length) {
880 return image_info1.num_correspondences >
881 image_info2.num_correspondences;
886 std::vector<image_t> image_ids;
887 image_ids.reserve(image_infos.size());
888 for (
const ImageInfo& image_info : image_infos) {
889 image_ids.push_back(image_info.image_id);
895 std::vector<image_t> IncrementalMapper::FindSecondInitialImage(
896 const Options& options,
const image_t image_id1)
const {
897 const CorrespondenceGraph& correspondence_graph =
898 database_cache_->CorrespondenceGraph();
902 const class Image& image1 = reconstruction_->Image(image_id1);
903 std::unordered_map<image_t, point2D_t> num_correspondences;
904 for (
point2D_t point2D_idx = 0; point2D_idx < image1.NumPoints2D();
906 for (
const auto& corr :
907 correspondence_graph.FindCorrespondences(image_id1, point2D_idx)) {
908 if (num_registrations_.count(corr.image_id) == 0 ||
909 num_registrations_.at(corr.image_id) == 0) {
910 num_correspondences[corr.image_id] += 1;
918 bool prior_focal_length;
922 const size_t init_min_num_inliers =
923 static_cast<size_t>(options.init_min_num_inliers);
926 std::vector<ImageInfo> image_infos;
927 image_infos.reserve(reconstruction_->NumImages());
928 for (
const auto elem : num_correspondences) {
929 if (elem.second >= init_min_num_inliers) {
930 const class Image&
image = reconstruction_->Image(elem.first);
931 const class Camera& camera =
932 reconstruction_->Camera(
image.CameraId());
933 ImageInfo image_info;
934 image_info.image_id = elem.first;
935 image_info.prior_focal_length = camera.HasPriorFocalLength();
936 image_info.num_correspondences = elem.second;
937 image_infos.push_back(image_info);
943 std::sort(image_infos.begin(), image_infos.end(),
944 [](
const ImageInfo& image_info1,
const ImageInfo& image_info2) {
945 if (image_info1.prior_focal_length &&
946 !image_info2.prior_focal_length) {
948 }
else if (!image_info1.prior_focal_length &&
949 image_info2.prior_focal_length) {
952 return image_info1.num_correspondences >
953 image_info2.num_correspondences;
958 std::vector<image_t> image_ids;
959 image_ids.reserve(image_infos.size());
960 for (
const ImageInfo& image_info : image_infos) {
961 image_ids.push_back(image_info.image_id);
967 std::vector<image_t> IncrementalMapper::FindLocalBundle(
968 const Options& options,
const image_t image_id)
const {
969 CHECK(options.Check());
971 const Image&
image = reconstruction_->Image(image_id);
972 CHECK(
image.IsRegistered());
977 std::unordered_map<image_t, size_t> shared_observations;
979 std::unordered_set<point3D_t> point3D_ids;
980 point3D_ids.reserve(
image.NumPoints3D());
982 for (
const Point2D& point2D :
image.Points2D()) {
983 if (point2D.HasPoint3D()) {
984 point3D_ids.insert(point2D.Point3DId());
986 reconstruction_->
Point3D(point2D.Point3DId());
987 for (
const TrackElement& track_el : point3D.Track().Elements()) {
988 if (track_el.image_id != image_id) {
989 shared_observations[track_el.image_id] += 1;
997 std::vector<std::pair<image_t, size_t>> overlapping_images(
998 shared_observations.begin(), shared_observations.end());
999 std::sort(overlapping_images.begin(), overlapping_images.end(),
1000 [](
const std::pair<image_t, size_t>& image1,
1001 const std::pair<image_t, size_t>& image2) {
1002 return image1.second > image2.second;
1008 const size_t num_images =
1009 static_cast<size_t>(options.local_ba_num_images - 1);
1010 const size_t num_eff_images =
1011 std::min(num_images, overlapping_images.size());
1015 std::vector<image_t> local_bundle_image_ids;
1016 local_bundle_image_ids.reserve(num_eff_images);
1020 if (overlapping_images.size() == num_eff_images) {
1021 for (
const auto& overlapping_image : overlapping_images) {
1022 local_bundle_image_ids.push_back(overlapping_image.first);
1024 return local_bundle_image_ids;
1034 const double min_tri_angle_rad =
DegToRad(options.local_ba_min_tri_angle);
1038 const std::array<std::pair<double, double>, 8> selection_thresholds = {{
1049 const Eigen::Vector3d proj_center =
image.ProjectionCenter();
1050 std::vector<Eigen::Vector3d> shared_points3D;
1051 shared_points3D.reserve(
image.NumPoints3D());
1052 std::vector<double> tri_angles(overlapping_images.size(), -1.0);
1053 std::vector<char> used_overlapping_images(overlapping_images.size(),
false);
1055 for (
const auto& selection_threshold : selection_thresholds) {
1056 for (
size_t overlapping_image_idx = 0;
1057 overlapping_image_idx < overlapping_images.size();
1058 ++overlapping_image_idx) {
1062 if (overlapping_images[overlapping_image_idx].second <
1063 selection_threshold.second) {
1068 if (used_overlapping_images[overlapping_image_idx]) {
1072 const auto& overlapping_image = reconstruction_->Image(
1073 overlapping_images[overlapping_image_idx].first);
1074 const Eigen::Vector3d overlapping_proj_center =
1075 overlapping_image.ProjectionCenter();
1079 double& tri_angle = tri_angles[overlapping_image_idx];
1080 if (tri_angle < 0.0) {
1082 shared_points3D.clear();
1083 for (
const Point2D& point2D :
image.Points2D()) {
1084 if (point2D.HasPoint3D() &&
1085 point3D_ids.count(point2D.Point3DId())) {
1086 shared_points3D.push_back(
1087 reconstruction_->Point3D(point2D.Point3DId())
1093 const double kTriangulationAnglePercentile = 75;
1096 proj_center, overlapping_proj_center,
1098 kTriangulationAnglePercentile);
1102 if (tri_angle >= selection_threshold.first) {
1103 local_bundle_image_ids.push_back(overlapping_image.ImageId());
1104 used_overlapping_images[overlapping_image_idx] =
true;
1106 if (local_bundle_image_ids.size() >= num_eff_images) {
1113 if (local_bundle_image_ids.size() >= num_eff_images) {
1121 if (local_bundle_image_ids.size() < num_eff_images) {
1122 for (
size_t overlapping_image_idx = 0;
1123 overlapping_image_idx < overlapping_images.size();
1124 ++overlapping_image_idx) {
1126 if (!used_overlapping_images[overlapping_image_idx]) {
1127 local_bundle_image_ids.push_back(
1128 overlapping_images[overlapping_image_idx].first);
1129 used_overlapping_images[overlapping_image_idx] =
true;
1132 if (local_bundle_image_ids.size() >= num_eff_images) {
1139 return local_bundle_image_ids;
1142 void IncrementalMapper::RegisterImageEvent(
const image_t image_id) {
1143 const Image&
image = reconstruction_->Image(image_id);
1144 size_t& num_reg_images_for_camera =
1145 num_reg_images_per_camera_[
image.CameraId()];
1146 num_reg_images_for_camera += 1;
1148 size_t& num_regs_for_image = num_registrations_[image_id];
1149 num_regs_for_image += 1;
1150 if (num_regs_for_image == 1) {
1151 num_total_reg_images_ += 1;
1152 }
else if (num_regs_for_image > 1) {
1153 num_shared_reg_images_ += 1;
1157 void IncrementalMapper::DeRegisterImageEvent(
const image_t image_id) {
1158 const Image&
image = reconstruction_->Image(image_id);
1159 size_t& num_reg_images_for_camera =
1160 num_reg_images_per_camera_.at(
image.CameraId());
1161 CHECK_GT(num_reg_images_for_camera, 0);
1162 num_reg_images_for_camera -= 1;
1164 size_t& num_regs_for_image = num_registrations_[image_id];
1165 num_regs_for_image -= 1;
1166 if (num_regs_for_image == 0) {
1167 num_total_reg_images_ -= 1;
1168 }
else if (num_regs_for_image > 0) {
1169 num_shared_reg_images_ -= 1;
1173 bool IncrementalMapper::EstimateInitialTwoViewGeometry(
1174 const Options& options,
1178 Database::ImagePairToPairId(image_id1, image_id2);
1180 if (prev_init_image_pair_id_ == image_pair_id) {
1184 const Image& image1 = database_cache_->Image(image_id1);
1185 const Camera& camera1 = database_cache_->Camera(image1.CameraId());
1187 const Image& image2 = database_cache_->Image(image_id2);
1188 const Camera& camera2 = database_cache_->Camera(image2.CameraId());
1190 const CorrespondenceGraph& correspondence_graph =
1191 database_cache_->CorrespondenceGraph();
1193 correspondence_graph.FindCorrespondencesBetweenImages(image_id1,
1196 std::vector<Eigen::Vector2d> points1;
1197 points1.reserve(image1.NumPoints2D());
1198 for (
const auto& point : image1.Points2D()) {
1199 points1.push_back(point.XY());
1202 std::vector<Eigen::Vector2d> points2;
1203 points2.reserve(image2.NumPoints2D());
1204 for (
const auto& point : image2.Points2D()) {
1205 points2.push_back(point.XY());
1208 TwoViewGeometry two_view_geometry;
1209 TwoViewGeometry::Options two_view_geometry_options;
1210 two_view_geometry_options.ransac_options.min_num_trials = 30;
1211 two_view_geometry_options.ransac_options.max_error = options.init_max_error;
1212 two_view_geometry.EstimateCalibrated(camera1, points1, camera2, points2,
1213 matches, two_view_geometry_options);
1215 if (!two_view_geometry.EstimateRelativePose(camera1, points1, camera2,
1220 if (
static_cast<int>(two_view_geometry.inlier_matches.size()) >=
1221 options.init_min_num_inliers &&
1222 std::abs(two_view_geometry.tvec.z()) <
1223 options.init_max_forward_motion &&
1224 two_view_geometry.tri_angle >
DegToRad(options.init_min_tri_angle)) {
1225 prev_init_image_pair_id_ = image_pair_id;
1226 prev_init_two_view_geometry_ = two_view_geometry;
std::shared_ptr< core::Tensor > image
Point3D(T x=0., T y=0., T z=0.)
const ceres::Solver::Summary & Summary() const
bool Solve(Reconstruction *reconstruction)
void AddVariablePoint(const point3D_t point3D_id)
const std::unordered_set< image_t > & Images() const
void SetConstantCamera(const camera_t camera_id)
void SetConstantPose(const image_t image_id)
void AddImage(const image_t image_id)
void SetConstantTvec(const image_t image_id, const std::vector< int > &idxs)
Eigen::Vector2d ImageToWorld(const Eigen::Vector2d &image_point) const
const std::vector< double > & Params() const
void SetParams(const std::vector< double > ¶ms)
bool HasPriorFocalLength() const
bool HasBogusParams(const double min_focal_length_ratio, const double max_focal_length_ratio, const double max_extra_param) const
FeatureMatches FindCorrespondencesBetweenImages(const image_t image_id1, const image_t image_id2) const
std::vector< Correspondence > FindTransitiveCorrespondences(const image_t image_id, const point2D_t point2D_idx, const size_t transitivity) const
class Camera & Camera(const camera_t camera_id)
const class CorrespondenceGraph & CorrespondenceGraph() const
bool ExistsImage(const image_t image_id) const
static image_pair_t ImagePairToPairId(const image_t image_id1, const image_t image_id2)
Eigen::Matrix3x4d ProjectionMatrix() const
const Eigen::Vector3d & Tvec() const
const class Point2D & Point2D(const point2D_t point2D_idx) const
const Eigen::Vector4d & Qvec() const
bool IsRegistered() const
Eigen::Vector3d ProjectionCenter() const
camera_t CameraId() const
LocalBundleAdjustmentReport AdjustLocalBundle(const Options &options, const BundleAdjustmentOptions &ba_options, const IncrementalTriangulator::Options &tri_options, const image_t image_id, const std::unordered_set< point3D_t > &point3D_ids)
bool FindInitialImagePair(const Options &options, image_t *image_id1, image_t *image_id2)
size_t NumSharedRegImages() const
size_t NumTotalRegImages() const
void EndReconstruction(const bool discard)
size_t MergeTracks(const IncrementalTriangulator::Options &tri_options)
void BeginReconstruction(Reconstruction *reconstruction)
bool RegisterNextImage(const Options &options, const image_t image_id)
const std::unordered_set< point3D_t > & GetModifiedPoints3D()
bool RegisterInitialImagePair(const Options &options, const image_t image_id1, const image_t image_id2)
size_t Retriangulate(const IncrementalTriangulator::Options &tri_options)
bool AdjustGlobalBundle(const Options &options, const BundleAdjustmentOptions &ba_options)
size_t FilterImages(const Options &options)
std::vector< image_t > FindNextImages(const Options &options)
size_t TriangulateImage(const IncrementalTriangulator::Options &tri_options, const image_t image_id)
const Reconstruction & GetReconstruction() const
size_t CompleteTracks(const IncrementalTriangulator::Options &tri_options)
IncrementalMapper(const DatabaseCache *database_cache)
void ClearModifiedPoints3D()
size_t FilterPoints(const Options &options)
point3D_t Point3DId() const
const Eigen::Vector2d & XY() const
const Eigen::Vector3d & XYZ() const
const class Track & Track() const
size_t FilterAllPoints3D(const double max_reproj_error, const double min_tri_angle)
size_t NumRegImages() const
size_t FilterObservationsWithNegativeDepth()
void Normalize(const double extent=10.0, const double p0=0.1, const double p1=0.9, const bool use_images=true)
const std::unordered_map< image_t, class Image > & Images() const
std::vector< image_t > FilterImages(const double min_focal_length_ratio, const double max_focal_length_ratio, const double max_extra_param)
const class Image & Image(const image_t image_id) const
const class Camera & Camera(const camera_t camera_id) const
void Load(const DatabaseCache &database_cache)
void AddObservation(const point3D_t point3D_id, const TrackElement &track_el)
const std::vector< image_t > & RegImageIds() const
size_t FilterPoints3D(const double max_reproj_error, const double min_tri_angle, const std::unordered_set< point3D_t > &point3D_ids)
bool ExistsImage(const image_t image_id) const
void RegisterImage(const image_t image_id)
size_t FilterPoints3DInImages(const double max_reproj_error, const double min_tri_angle, const std::unordered_set< image_t > &image_ids)
const class Point3D & Point3D(const point3D_t point3D_id) const
point3D_t AddPoint3D(const Eigen::Vector3d &xyz, const Track &track, const Eigen::Vector3ub &color=Eigen::Vector3ub::Zero())
void SetUp(const CorrespondenceGraph *correspondence_graph)
void AddElement(const TrackElement &element)
void Reserve(const size_t num_elements)
const TrackElement & Element(const size_t idx) const
#define CHECK_OPTION_LE(val1, val2)
#define CHECK_OPTION_GT(val1, val2)
#define CHECK_OPTION_GE(val1, val2)
Matrix< double, 3, 4 > Matrix3x4d
QTextStream & endl(QTextStream &stream)
CLOUDVIEWER_HOST_DEVICE Pair< First, Second > make_pair(const First &_first, const Second &_second)
bool HasPointPositiveDepth(const Eigen::Matrix3x4d &proj_matrix, const Eigen::Vector3d &point3D)
Eigen::Vector4d ComposeIdentityQuaternion()
std::vector< double > CalculateTriangulationAngles(const Eigen::Vector3d &proj_center1, const Eigen::Vector3d &proj_center2, const std::vector< Eigen::Vector3d > &points3D)
bool EstimateAbsolutePose(const AbsolutePoseEstimationOptions &options, const std::vector< Eigen::Vector2d > &points2D, const std::vector< Eigen::Vector3d > &points3D, Eigen::Vector4d *qvec, Eigen::Vector3d *tvec, Camera *camera, size_t *num_inliers, std::vector< char > *inlier_mask)
Eigen::Vector3d TriangulatePoint(const Eigen::Matrix3x4d &proj_matrix1, const Eigen::Matrix3x4d &proj_matrix2, const Eigen::Vector2d &point1, const Eigen::Vector2d &point2)
const image_pair_t kInvalidImagePairId
bool RefineAbsolutePose(const AbsolutePoseRefinementOptions &options, const std::vector< char > &inlier_mask, const std::vector< Eigen::Vector2d > &points2D, const std::vector< Eigen::Vector3d > &points3D, Eigen::Vector4d *qvec, Eigen::Vector3d *tvec, Camera *camera)
const image_t kInvalidImageId
double CalculateTriangulationAngle(const Eigen::Vector3d &proj_center1, const Eigen::Vector3d &proj_center2, const Eigen::Vector3d &point3D)
float DegToRad(const float deg)
std::vector< FeatureMatch > FeatureMatches
T Percentile(const std::vector< T > &elems, const double p)
bool estimate_focal_length
RANSACOptions ransac_options
size_t num_focal_length_samples
double min_focal_length_ratio
double max_focal_length_ratio
size_t num_adjusted_observations
size_t num_merged_observations
size_t num_filtered_observations
size_t num_completed_observations
@ MAX_VISIBLE_POINTS_RATIO
double abs_pose_max_error
double local_ba_min_tri_angle
ImageSelectionMethod image_selection_method
double init_min_tri_angle
double init_max_forward_motion
double filter_min_tri_angle
int abs_pose_min_num_inliers
double max_focal_length_ratio
double filter_max_reproj_error
double min_focal_length_ratio
double abs_pose_min_inlier_ratio
bool abs_pose_refine_focal_length
bool abs_pose_refine_extra_params