这程序就是用于重建单个Cluster的程序,如果读懂了,就能理解分Cluster重建的整体思路了。 如果读懂了,分组重建就懂了。
void IncrementalMapperController::Reconstruct(
const IncrementalMapper::Options& init_mapper_options) {
const bool kDiscardReconstruction = true;
//
// Main loop
//
IncrementalMapper mapper(&database_cache_);
// Is there a sub-model before we start the reconstruction? I.e. the user
// has imported an existing reconstruction.
const bool initial_reconstruction_given = reconstruction_manager_->Size() > 0;
CHECK_LE(reconstruction_manager_->Size(), 1) << "Can only resume from a "
"single reconstruction, but "
"multiple are given.";
for (int num_trials = 0; num_trials < options_->init_num_trials;
++num_trials) {
BlockIfPaused();
if (IsStopped()) {
break;
}
size_t reconstruction_idx;
if (!initial_reconstruction_given || num_trials > 0) {
reconstruction_idx = reconstruction_manager_->Add();
} else {
reconstruction_idx = 0;
}
Reconstruction& reconstruction =
reconstruction_manager_->Get(reconstruction_idx);
mapper.BeginReconstruction(&reconstruction);
看到这里,看一下 BeginReconstruction() !的庐山真面目吧~~~
void IncrementalMapper::BeginReconstruction(Reconstruction* reconstruction) {
CHECK(reconstruction_ == nullptr);
// 这个reconstruction是一个重建模型(实际上是一个class啦,包含重建所用的所有信息)
reconstruction_ = reconstruction;
reconstruction_->Load(*database_cache_);
reconstruction_->SetUp(&database_cache_->CorrespondenceGraph());
// triangulator类开始啦,毕竟无论如何重建都要回归到三角化上,
triangulator_.reset(new IncrementalTriangulator(
&database_cache_->CorrespondenceGraph(), reconstruction));
num_shared_reg_images_ = 0;
num_reg_images_per_camera_.clear();
for (const image_t image_id : reconstruction_->RegImageIds()) {
RegisterImageEvent(image_id);
}
existing_image_ids_ =
std::unordered_set<image_t>(reconstruction->RegImageIds().begin(),
reconstruction->RegImageIds().end());
prev_init_image_pair_id_ = kInvalidImagePairId;
prev_init_two_view_geometry_ = TwoViewGeometry();
filtered_images_.clear();
num_reg_trials_.clear();
}
// Register initial pair
// 这里注册前两张图片
if (reconstruction.NumRegImages() == 0) {
image_t image_id1 = static_cast<image_t>(options_->init_image_id1);
image_t image_id2 = static_cast<image_t>(options_->init_image_id2);
// Try to find good initial pair.
if (options_->init_image_id1 == -1 || options_->init_image_id2 == -1) {
const bool find_init_success = mapper.FindInitialImagePair(
init_mapper_options, &image_id1, &image_id2);
if (!find_init_success) {
std::cout << " => No good initial image pair found." << std::endl;
mapper.EndReconstruction(kDiscardReconstruction);
reconstruction_manager_->Delete(reconstruction_idx);
break;
}
} else {
if (!reconstruction.ExistsImage(image_id1) ||
!reconstruction.ExistsImage(image_id2)) {
std::cout << StringPrintf(
" => Initial image pair #%d and #%d do not exist.",
image_id1, image_id2)
<< std::endl;
mapper.EndReconstruction(kDiscardReconstruction);
reconstruction_manager_->Delete(reconstruction_idx);
return;
}
}
PrintHeading1(StringPrintf("Initializing with image pair #%d and #%d",
image_id1, image_id2));
const bool reg_init_success = mapper.RegisterInitialImagePair(
init_mapper_options, image_id1, image_id2);
if (!reg_init_success) {
std::cout << " => Initialization failed - possible solutions:"
<< std::endl
<< " - try to relax the initialization constraints"
<< std::endl
<< " - manually select an initial image pair"
<< std::endl;
mapper.EndReconstruction(kDiscardReconstruction);
reconstruction_manager_->Delete(reconstruction_idx);
break;
}
AdjustGlobalBundle(*options_, &mapper);
FilterPoints(*options_, &mapper);
FilterImages(*options_, &mapper);
// Initial image pair failed to register.
if (reconstruction.NumRegImages() == 0 ||
reconstruction.NumPoints3D() == 0) {
mapper.EndReconstruction(kDiscardReconstruction);
reconstruction_manager_->Delete(reconstruction_idx);
// If both initial images are manually specified, there is no need for
// further initialization trials.
if (options_->init_image_id1 != -1 && options_->init_image_id2 != -1) {
break;
} else {
continue;
}
}
if (options_->extract_colors) {
ExtractColors(image_path_, image_id1, &reconstruction);
}
}
Callback(INITIAL_IMAGE_PAIR_REG_CALLBACK);
// Incremental mapping
size_t snapshot_prev_num_reg_images = reconstruction.NumRegImages();
size_t ba_prev_num_reg_images = reconstruction.NumRegImages();
size_t ba_prev_num_points = reconstruction.NumPoints3D();
bool reg_next_success = true;
bool prev_reg_next_success = true;
while (reg_next_success) {
BlockIfPaused();
if (IsStopped()) {
break;
}
reg_next_success = false;
const std::vector<image_t> next_images =
mapper.FindNextImages(options_->Mapper());
if (next_images.empty()) {
break;
}
for (size_t reg_trial = 0; reg_trial < next_images.size(); ++reg_trial) {
const image_t next_image_id = next_images[reg_trial];
const Image& next_image = reconstruction.Image(next_image_id);
PrintHeading1(StringPrintf("Registering image #%d (%d)", next_image_id,
reconstruction.NumRegImages() + 1));
std::cout << StringPrintf(" => Image sees %d / %d points",
next_image.NumVisiblePoints3D(),
next_image.NumObservations())
<< std::endl;
reg_next_success =
mapper.RegisterNextImage(options_->Mapper(), next_image_id);
if (reg_next_success) {
TriangulateImage(*options_, next_image, &mapper);
IterativeLocalRefinement(*options_, next_image_id, &mapper);
if (reconstruction.NumRegImages() >=
options_->ba_global_images_ratio * ba_prev_num_reg_images ||
reconstruction.NumRegImages() >=
options_->ba_global_images_freq + ba_prev_num_reg_images ||
reconstruction.NumPoints3D() >=
options_->ba_global_points_ratio * ba_prev_num_points ||
reconstruction.NumPoints3D() >=
options_->ba_global_points_freq + ba_prev_num_points) {
IterativeGlobalRefinement(*options_, &mapper);
ba_prev_num_points = reconstruction.NumPoints3D();
ba_prev_num_reg_images = reconstruction.NumRegImages();
}
if (options_->extract_colors) {
ExtractColors(image_path_, next_image_id, &reconstruction);
}
if (options_->snapshot_images_freq > 0 &&
reconstruction.NumRegImages() >=
options_->snapshot_images_freq +
snapshot_prev_num_reg_images) {
snapshot_prev_num_reg_images = reconstruction.NumRegImages();
WriteSnapshot(reconstruction, options_->snapshot_path);
}
Callback(NEXT_IMAGE_REG_CALLBACK);
break;
} else {
std::cout << " => Could not register, trying another image."
<< std::endl;
// If initial pair fails to continue for some time,
// abort and try different initial pair.
const size_t kMinNumInitialRegTrials = 30;
if (reg_trial >= kMinNumInitialRegTrials &&
reconstruction.NumRegImages() <
static_cast<size_t>(options_->min_model_size)) {
break;
}
}
}
const size_t max_model_overlap =
static_cast<size_t>(options_->max_model_overlap);
if (mapper.NumSharedRegImages() >= max_model_overlap) {
break;
}
// If no image could be registered, try a single final global iterative
// bundle adjustment and try again to register one image. If this fails
// once, then exit the incremental mapping.
if (!reg_next_success && prev_reg_next_success) {
reg_next_success = true;
prev_reg_next_success = false;
IterativeGlobalRefinement(*options_, &mapper);
} else {
prev_reg_next_success = reg_next_success;
}
}
if (IsStopped()) {
const bool kDiscardReconstruction = false;
mapper.EndReconstruction(kDiscardReconstruction);
break;
}
// Only run final global BA, if last incremental BA was not global.
if (reconstruction.NumRegImages() >= 2 &&
reconstruction.NumRegImages() != ba_prev_num_reg_images &&
reconstruction.NumPoints3D() != ba_prev_num_points) {
IterativeGlobalRefinement(*options_, &mapper);
}
// If the total number of images is small then do not enforce the minimum
// model size so that we can reconstruct small image collections.
const size_t min_model_size =
std::min(database_cache_.NumImages(),
static_cast<size_t>(options_->min_model_size));
if ((options_->multiple_models &&
reconstruction.NumRegImages() < min_model_size) ||
reconstruction.NumRegImages() == 0) {
mapper.EndReconstruction(kDiscardReconstruction);
reconstruction_manager_->Delete(reconstruction_idx);
} else {
const bool kDiscardReconstruction = false;
mapper.EndReconstruction(kDiscardReconstruction);
}
Callback(LAST_IMAGE_REG_CALLBACK);
const size_t max_num_models = static_cast<size_t>(options_->max_num_models);
if (initial_reconstruction_given || !options_->multiple_models ||
reconstruction_manager_->Size() >= max_num_models ||
mapper.NumTotalRegImages() >= database_cache_.NumImages() - 1) {
break;
}
}
}