17 const SceneClustering::Cluster& cluster,
18 std::unordered_map<const SceneClustering::Cluster*, ReconstructionManager>*
19 reconstruction_managers) {
21 std::vector<Reconstruction*> reconstructions;
22 for (
const auto& child_cluster : cluster.child_clusters) {
23 if (!child_cluster.child_clusters.empty()) {
24 MergeClusters(child_cluster, reconstruction_managers);
27 auto& reconstruction_manager = reconstruction_managers->at(&child_cluster);
28 for (
size_t i = 0; i < reconstruction_manager.Size(); ++i) {
29 reconstructions.push_back(&reconstruction_manager.Get(i));
34 while (reconstructions.size() > 1) {
35 bool merge_success =
false;
36 for (
size_t i = 0; i < reconstructions.size(); ++i) {
37 for (
size_t j = 0; j < i; ++j) {
38 const double kMaxReprojError = 8.0;
39 if (reconstructions[i]->Merge(*reconstructions[j], kMaxReprojError)) {
40 reconstructions.erase(reconstructions.begin() + j);
57 auto& reconstruction_manager = (*reconstruction_managers)[&cluster];
58 for (
const auto& reconstruction : reconstructions) {
59 reconstruction_manager.Add();
60 reconstruction_manager.Get(reconstruction_manager.Size() - 1) =
65 for (
const auto& child_cluster : cluster.child_clusters) {
66 reconstruction_managers->erase(&child_cluster);
83 clustering_options_(clustering_options),
84 mapper_options_(mapper_options),
85 reconstruction_manager_(reconstruction_manager) {
86 CHECK(options_.
Check());
87 CHECK(clustering_options_.
Check());
88 CHECK(mapper_options_.
Check());
89 CHECK_EQ(clustering_options_.
branching, 2);
92 void HierarchicalMapperController::Run() {
99 std::unordered_map<image_t, std::string> image_id_to_name;
103 std::cout <<
"Reading images..." <<
std::endl;
104 const auto images = database.ReadAllImages();
105 for (
const auto&
image : images) {
106 image_id_to_name.emplace(
image.ImageId(),
image.Name());
109 SceneClustering scene_clustering =
112 auto leaf_clusters = scene_clustering.GetLeafClusters();
114 size_t total_num_images = 0;
115 for (
size_t i = 0; i < leaf_clusters.size(); ++i) {
116 total_num_images += leaf_clusters[i]->image_ids.size();
117 std::cout <<
StringPrintf(
" Cluster %d with %d images", i + 1,
118 leaf_clusters[i]->image_ids.size())
122 std::cout <<
StringPrintf(
"Clusters have %d images", total_num_images)
132 const int kMaxNumThreads = -1;
134 const int kDefaultNumWorkers = 8;
135 const int num_eff_workers =
137 ? std::min(
static_cast<int>(leaf_clusters.size()),
138 std::min(kDefaultNumWorkers, num_eff_threads))
139 : options_.num_workers;
140 const int num_threads_per_worker =
141 std::max(1, num_eff_threads / num_eff_workers);
144 auto ReconstructCluster = [&,
this](
145 const SceneClustering::Cluster& cluster,
146 ReconstructionManager* reconstruction_manager) {
147 if (cluster.image_ids.empty()) {
154 if (custom_options.num_threads < 0) {
155 custom_options.num_threads = num_threads_per_worker;
158 for (
const auto image_id : cluster.image_ids) {
159 custom_options.image_names.insert(image_id_to_name.at(image_id));
164 reconstruction_manager);
170 std::sort(leaf_clusters.begin(), leaf_clusters.end(),
171 [](
const SceneClustering::Cluster* cluster1,
172 const SceneClustering::Cluster* cluster2) {
173 return cluster1->image_ids.size() > cluster2->image_ids.size();
178 std::unordered_map<const SceneClustering::Cluster*, ReconstructionManager>
179 reconstruction_managers;
180 reconstruction_managers.reserve(leaf_clusters.size());
182 ThreadPool thread_pool(num_eff_workers);
183 for (
const auto& cluster : leaf_clusters) {
184 thread_pool.AddTask(ReconstructCluster, *cluster,
185 &reconstruction_managers[cluster]);
195 MergeClusters(*scene_clustering.GetRootCluster(), &reconstruction_managers);
197 CHECK_EQ(reconstruction_managers.size(), 1);
198 *reconstruction_manager_ = std::move(reconstruction_managers.begin()->second);
std::shared_ptr< core::Tensor > image
HierarchicalMapperController(const Options &options, const SceneClustering::Options &clustering_options, const IncrementalMapperOptions &mapper_options, ReconstructionManager *reconstruction_manager)
static SceneClustering Create(const Options &options, const Database &database)
const Timer & GetTimer() const
void PrintMinutes() const
#define CHECK_OPTION_GT(val1, val2)
#define CHECK_OPTION_GE(val1, val2)
QTextStream & endl(QTextStream &stream)
colmap::IncrementalMapperOptions IncrementalMapperOptions
colmap::IncrementalMapperController IncrementalMapperController
void PrintHeading1(const std::string &heading)
std::string StringPrintf(const char *format,...)
int GetEffectiveNumThreads(const int num_threads)
std::string database_path