From 243e4ac0b1fa1f6f5c0bdd83c7247ca84d248d84 Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Thu, 19 Jun 2025 18:23:15 +0200 Subject: [PATCH 1/8] d --- glomap/io/pose_io.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/glomap/io/pose_io.cc b/glomap/io/pose_io.cc index eeda2e6b..a6891d0a 100644 --- a/glomap/io/pose_io.cc +++ b/glomap/io/pose_io.cc @@ -64,10 +64,18 @@ void ReadRelPose(const std::string& file_path, std::getline(line_stream, item, ' '); pose_rel.translation[i] = std::stod(item); } - + if (!add_image) continue; + + counter++; + if (view_graph.image_pairs.find(pair_id) != + view_graph.image_pairs.end()) { + // If the pair already exists, update the relative pose + view_graph.image_pairs[pair_id].cam2_from_cam1 = pose_rel; + view_graph.image_pairs[pair_id].is_valid = true; + continue; + } view_graph.image_pairs.insert( std::make_pair(pair_id, ImagePair(index1, index2, pose_rel))); - counter++; } LOG(INFO) << counter << " relpose are loaded" << std::endl; } From 641d309c0c4de8136bce7b7fd0c12ccde6c37f40 Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Thu, 19 Jun 2025 18:52:20 +0200 Subject: [PATCH 2/8] add option to only reconstruct a list of images --- glomap/CMakeLists.txt | 2 ++ glomap/exe/global_mapper.cc | 14 ++++++++++++++ glomap/io/utils.cc | 20 ++++++++++++++++++++ glomap/io/utils.h | 15 +++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 glomap/io/utils.cc create mode 100644 glomap/io/utils.h diff --git a/glomap/CMakeLists.txt b/glomap/CMakeLists.txt index e191049a..05681b38 100644 --- a/glomap/CMakeLists.txt +++ b/glomap/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES io/colmap_converter.cc io/colmap_io.cc io/pose_io.cc + io/utils.cc math/gravity.cc math/rigid3d.cc math/tree.cc @@ -44,6 +45,7 @@ set(HEADERS io/colmap_converter.h io/colmap_io.h io/pose_io.h + io/utils.h math/gravity.h math/l1_solver.h math/rigid3d.h diff --git a/glomap/exe/global_mapper.cc b/glomap/exe/global_mapper.cc index fb1e512c..0f697266 100644 --- a/glomap/exe/global_mapper.cc +++ b/glomap/exe/global_mapper.cc @@ -2,6 +2,8 @@ #include "glomap/controllers/option_manager.h" #include "glomap/io/colmap_io.h" +#include "glomap/io/pose_io.h" +#include "glomap/io/utils.h" #include "glomap/types.h" #include @@ -19,11 +21,16 @@ int RunMapper(int argc, char** argv) { std::string image_path = ""; std::string constraint_type = "ONLY_POINTS"; std::string output_format = "bin"; + std::string image_list_path = ""; OptionManager options; options.AddRequiredOption("database_path", &database_path); options.AddRequiredOption("output_path", &output_path); options.AddDefaultOption("image_path", &image_path); + options.AddDefaultOption("image_list_path", + &image_list_path, + "Path to the image list file, if not provided, " + "all images in the database will be used"); options.AddDefaultOption("constraint_type", &constraint_type, "{ONLY_POINTS, ONLY_CAMERAS, " @@ -61,6 +68,13 @@ int RunMapper(int argc, char** argv) { return EXIT_FAILURE; } + if (image_list_path != "") { + if (!colmap::ExistsFile(image_list_path)) { + LOG(ERROR) << "`image_list_path` is not a file"; + return EXIT_FAILURE; + } + } + // Load the database ViewGraph view_graph; std::unordered_map cameras; diff --git a/glomap/io/utils.cc b/glomap/io/utils.cc new file mode 100644 index 00000000..23eb0c45 --- /dev/null +++ b/glomap/io/utils.cc @@ -0,0 +1,20 @@ +#include "glomap/io/utils.h" +#include "colmap/util/string.h" + +#include + +namespace glomap { +void ReadImageList(const std::string& file_path, + std::unordered_set& image_filenames) { + std::ifstream image_list_file(file_path); + std::string line; + while (std::getline(image_list_file, line)) { + if (!line.empty()) { + colmap::StringTrim(&line); + image_filenames.insert(line); + } + } + image_list_file.close(); +} + +} // namespace glomap \ No newline at end of file diff --git a/glomap/io/utils.h b/glomap/io/utils.h new file mode 100644 index 00000000..655835d0 --- /dev/null +++ b/glomap/io/utils.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +namespace glomap { +// Read a list of image filenames from a file. +// Required data structure: +// IMAGE_NAME_1 +// IMAGE_NAME_2 +// ... +// IMAGE_NAME_N +void ReadImageList(const std::string& file_path, + std::unordered_set& image_filenames); +} // namespace glomap From 8e0e223c5be28273a95f987bbe3667a494bcc13e Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Thu, 19 Jun 2025 18:55:24 +0200 Subject: [PATCH 3/8] d --- glomap/processors/view_graph_manipulation.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/glomap/processors/view_graph_manipulation.cc b/glomap/processors/view_graph_manipulation.cc index 38ec4dc6..84288e89 100644 --- a/glomap/processors/view_graph_manipulation.cc +++ b/glomap/processors/view_graph_manipulation.cc @@ -71,7 +71,10 @@ image_t ViewGraphManipulater::EstablishStrongClusters( StrongClusterCriteria criteria, double min_thres, int min_num_images) { - image_t num_img_before = view_graph.KeepLargestConnectedComponents(images); + // Mark all images as registered + for (auto& [image_id, image] : images) { + image.is_registered = true; + } // Construct the initial cluster by keeping the pairs with weight > min_thres UnionFind uf; From e256b1e7403d496150847497fcf699676a7c4dca Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Thu, 19 Jun 2025 19:02:37 +0200 Subject: [PATCH 4/8] d --- glomap/io/pose_io.cc | 19 +++++++++++++------ glomap/io/pose_io.h | 4 +++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/glomap/io/pose_io.cc b/glomap/io/pose_io.cc index a6891d0a..51f97c4d 100644 --- a/glomap/io/pose_io.cc +++ b/glomap/io/pose_io.cc @@ -7,7 +7,8 @@ namespace glomap { void ReadRelPose(const std::string& file_path, std::unordered_map& images, - ViewGraph& view_graph) { + ViewGraph& view_graph, + bool editable_images) { std::unordered_map name_idx; image_t max_image_id = 0; for (const auto& [image_id, image] : images) { @@ -35,21 +36,28 @@ void ReadRelPose(const std::string& file_path, std::getline(line_stream, item, ' '); file2 = item; + bool add_image = true; if (name_idx.find(file1) == name_idx.end()) { + if (!editable_images) { + add_image = false; + } max_image_id += 1; images.insert( std::make_pair(max_image_id, Image(max_image_id, -1, file1))); name_idx[file1] = max_image_id; } if (name_idx.find(file2) == name_idx.end()) { + if (!editable_images) { + add_image = false; + } max_image_id += 1; images.insert( std::make_pair(max_image_id, Image(max_image_id, -1, file2))); name_idx[file2] = max_image_id; } - image_t index1 = name_idx[file1]; - image_t index2 = name_idx[file2]; + image_t index1 = add_image ? name_idx[file1] : -1; + image_t index2 = add_image ? name_idx[file2] : -1; image_pair_t pair_id = ImagePair::ImagePairToPairId(index1, index2); @@ -65,10 +73,9 @@ void ReadRelPose(const std::string& file_path, pose_rel.translation[i] = std::stod(item); } if (!add_image) continue; - + counter++; - if (view_graph.image_pairs.find(pair_id) != - view_graph.image_pairs.end()) { + if (view_graph.image_pairs.find(pair_id) != view_graph.image_pairs.end()) { // If the pair already exists, update the relative pose view_graph.image_pairs[pair_id].cam2_from_cam1 = pose_rel; view_graph.image_pairs[pair_id].is_valid = true; diff --git a/glomap/io/pose_io.h b/glomap/io/pose_io.h index e98112f7..8c126fc5 100644 --- a/glomap/io/pose_io.h +++ b/glomap/io/pose_io.h @@ -7,9 +7,11 @@ namespace glomap { // Required data structures // IMAGE_NAME_1 IMAGE_NAME_2 QW QX QY QZ TX TY TZ +// editable_images: where the images can be added if they are not present void ReadRelPose(const std::string& file_path, std::unordered_map& images, - ViewGraph& view_graph); + ViewGraph& view_graph, + bool editable_images = true); // Required data structures // IMAGE_NAME_1 IMAGE_NAME_2 weight From a33098ccaa5cabd3ac5884f9e44eab968231a306 Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Thu, 19 Jun 2025 19:17:46 +0200 Subject: [PATCH 5/8] d --- glomap/exe/global_mapper.cc | 4 +++- glomap/io/colmap_converter.cc | 21 +++++++++++++++++---- glomap/io/colmap_converter.h | 10 ++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/glomap/exe/global_mapper.cc b/glomap/exe/global_mapper.cc index 0f697266..1aa57df8 100644 --- a/glomap/exe/global_mapper.cc +++ b/glomap/exe/global_mapper.cc @@ -68,11 +68,13 @@ int RunMapper(int argc, char** argv) { return EXIT_FAILURE; } + std::unordered_set image_filenames; if (image_list_path != "") { if (!colmap::ExistsFile(image_list_path)) { LOG(ERROR) << "`image_list_path` is not a file"; return EXIT_FAILURE; } + ReadImageList(image_list_path, image_filenames); } // Load the database @@ -82,7 +84,7 @@ int RunMapper(int argc, char** argv) { std::unordered_map tracks; const colmap::Database database(database_path); - ConvertDatabaseToGlomap(database, view_graph, cameras, images); + ConvertDatabaseToGlomap(database, view_graph, cameras, images, &image_filenames); if (view_graph.image_pairs.empty()) { LOG(ERROR) << "Can't continue without image pairs"; diff --git a/glomap/io/colmap_converter.cc b/glomap/io/colmap_converter.cc index abfe1ffc..18e1d6e7 100644 --- a/glomap/io/colmap_converter.cc +++ b/glomap/io/colmap_converter.cc @@ -176,10 +176,12 @@ void ConvertColmapPoints3DToGlomapTracks( // For ease of debug, go through the database twice: first extract the available // pairs, then read matches from pairs. -void ConvertDatabaseToGlomap(const colmap::Database& database, - ViewGraph& view_graph, - std::unordered_map& cameras, - std::unordered_map& images) { +void ConvertDatabaseToGlomap( + const colmap::Database& database, + ViewGraph& view_graph, + std::unordered_map& cameras, + std::unordered_map& images, + const std::unordered_set* image_filenames) { // Add the images std::vector images_colmap = database.ReadAllImages(); image_t counter = 0; @@ -188,6 +190,11 @@ void ConvertDatabaseToGlomap(const colmap::Database& database, << images_colmap.size() << std::flush; counter++; + if (image_filenames && + image_filenames->find(image.Name()) == image_filenames->end()) { + continue; // Skip images not in the specified set + } + const image_t image_id = image.ImageId(); if (image_id == colmap::kInvalidImageId) continue; auto ite = images.insert(std::make_pair( @@ -239,6 +246,12 @@ void ConvertDatabaseToGlomap(const colmap::Database& database, colmap::image_t image_id1 = image_pair_colmap.first; colmap::image_t image_id2 = image_pair_colmap.second; + if (images.find(image_id1) == images.end() || + images.find(image_id2) == images.end()) { + // If the image is not added to the images map, then skip + continue; + } + colmap::FeatureMatches& feature_matches = all_matches[match_idx].second; // Initialize the image pair diff --git a/glomap/io/colmap_converter.h b/glomap/io/colmap_converter.h index 5bd4457e..5cf37ab4 100644 --- a/glomap/io/colmap_converter.h +++ b/glomap/io/colmap_converter.h @@ -27,9 +27,11 @@ void ConvertColmapPoints3DToGlomapTracks( const colmap::Reconstruction& reconstruction, std::unordered_map& tracks); -void ConvertDatabaseToGlomap(const colmap::Database& database, - ViewGraph& view_graph, - std::unordered_map& cameras, - std::unordered_map& images); +void ConvertDatabaseToGlomap( + const colmap::Database& database, + ViewGraph& view_graph, + std::unordered_map& cameras, + std::unordered_map& images, + const std::unordered_set* image_filenames = nullptr); } // namespace glomap From 3efcc6fedb13caf950074f3cb9b3002d1b92fbe1 Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Fri, 20 Jun 2025 12:22:32 +0200 Subject: [PATCH 6/8] only retriangulate registered images --- glomap/controllers/track_retriangulation.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/glomap/controllers/track_retriangulation.cc b/glomap/controllers/track_retriangulation.cc index 92d73e0f..e2e26e8a 100644 --- a/glomap/controllers/track_retriangulation.cc +++ b/glomap/controllers/track_retriangulation.cc @@ -15,13 +15,20 @@ bool RetriangulateTracks(const TriangulatorOptions& options, std::unordered_map& cameras, std::unordered_map& images, std::unordered_map& tracks) { + // Collect the registered images + std::unordered_set registered_image_names; + for (const auto& [image_id, image] : images) { + if (image.is_registered) { + registered_image_names.insert(image.file_name); + } + } // Following code adapted from COLMAP - auto database_cache = - colmap::DatabaseCache::Create(database, - options.min_num_matches, - false, // ignore_watermarks - {} // reconstruct all possible images - ); + auto database_cache = colmap::DatabaseCache::Create( + database, + options.min_num_matches, + false, // ignore_watermarks + registered_image_names // reconstruct all possible images + ); // Check whether the image is in the database cache. If not, set the image // as not registered to avoid memory error. From 9c9b6355a1e2c80377f003035707d9eafdec5dbc Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Fri, 20 Jun 2025 12:23:04 +0200 Subject: [PATCH 7/8] f --- glomap/exe/global_mapper.cc | 3 ++- glomap/io/utils.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/glomap/exe/global_mapper.cc b/glomap/exe/global_mapper.cc index 1aa57df8..161b5c34 100644 --- a/glomap/exe/global_mapper.cc +++ b/glomap/exe/global_mapper.cc @@ -84,7 +84,8 @@ int RunMapper(int argc, char** argv) { std::unordered_map tracks; const colmap::Database database(database_path); - ConvertDatabaseToGlomap(database, view_graph, cameras, images, &image_filenames); + ConvertDatabaseToGlomap( + database, view_graph, cameras, images, &image_filenames); if (view_graph.image_pairs.empty()) { LOG(ERROR) << "Can't continue without image pairs"; diff --git a/glomap/io/utils.cc b/glomap/io/utils.cc index 23eb0c45..1cf03abb 100644 --- a/glomap/io/utils.cc +++ b/glomap/io/utils.cc @@ -1,8 +1,9 @@ #include "glomap/io/utils.h" -#include "colmap/util/string.h" #include +#include "colmap/util/string.h" + namespace glomap { void ReadImageList(const std::string& file_path, std::unordered_set& image_filenames) { From 38ea092e73358cb03967dc3e79766e696a68261c Mon Sep 17 00:00:00 2001 From: Linfei Pan Date: Mon, 23 Jun 2025 14:50:11 +0200 Subject: [PATCH 8/8] d --- glomap/io/colmap_converter.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glomap/io/colmap_converter.cc b/glomap/io/colmap_converter.cc index 18e1d6e7..e743f7b2 100644 --- a/glomap/io/colmap_converter.cc +++ b/glomap/io/colmap_converter.cc @@ -182,6 +182,7 @@ void ConvertDatabaseToGlomap( std::unordered_map& cameras, std::unordered_map& images, const std::unordered_set* image_filenames) { + bool has_image_filenames = image_filenames && !image_filenames->empty(); // Add the images std::vector images_colmap = database.ReadAllImages(); image_t counter = 0; @@ -190,7 +191,7 @@ void ConvertDatabaseToGlomap( << images_colmap.size() << std::flush; counter++; - if (image_filenames && + if (has_image_filenames && image_filenames->find(image.Name()) == image_filenames->end()) { continue; // Skip images not in the specified set }