| 379 | } |
| 380 | |
| 381 | std::vector<image_t> IncrementalMapperImpl::FindLocalBundle( |
| 382 | const IncrementalMapper::Options& options, |
| 383 | image_t image_id, |
| 384 | const Reconstruction& reconstruction) { |
| 385 | THROW_CHECK(options.Check()); |
| 386 | |
| 387 | const Image& image = reconstruction.Image(image_id); |
| 388 | THROW_CHECK(image.HasPose()); |
| 389 | |
| 390 | // Extract all images that have at least one 3D point with the query image |
| 391 | // in common, and simultaneously count the number of common 3D points. |
| 392 | |
| 393 | std::unordered_map<image_t, size_t> shared_observations; |
| 394 | |
| 395 | std::unordered_set<point3D_t> point3D_ids; |
| 396 | point3D_ids.reserve(image.NumPoints3D()); |
| 397 | |
| 398 | for (const Point2D& point2D : image.Points2D()) { |
| 399 | if (point2D.HasPoint3D()) { |
| 400 | point3D_ids.insert(point2D.point3D_id); |
| 401 | const Point3D& point3D = reconstruction.Point3D(point2D.point3D_id); |
| 402 | for (const TrackElement& track_el : point3D.track.Elements()) { |
| 403 | if (track_el.image_id != image_id) { |
| 404 | shared_observations[track_el.image_id] += 1; |
| 405 | } |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | |
| 410 | // Sort overlapping images according to number of shared observations. |
| 411 | |
| 412 | std::vector<std::pair<image_t, size_t>> overlapping_images( |
| 413 | shared_observations.begin(), shared_observations.end()); |
| 414 | std::sort(overlapping_images.begin(), |
| 415 | overlapping_images.end(), |
| 416 | [](const std::pair<image_t, size_t>& image1, |
| 417 | const std::pair<image_t, size_t>& image2) { |
| 418 | return image1.second > image2.second; |
| 419 | }); |
| 420 | |
| 421 | // The local bundle is composed of the given image and its most connected |
| 422 | // neighbor images, hence the subtraction of 1. |
| 423 | |
| 424 | const size_t num_images = |
| 425 | static_cast<size_t>(options.ba_local_num_images - 1); |
| 426 | const size_t num_eff_images = std::min(num_images, overlapping_images.size()); |
| 427 | |
| 428 | // Extract most connected images and ensure sufficient triangulation angle. |
| 429 | |
| 430 | std::vector<image_t> local_bundle_image_ids; |
| 431 | local_bundle_image_ids.reserve(num_eff_images); |
| 432 | |
| 433 | // If the number of overlapping images equals the number of desired images |
| 434 | // in the local bundle, then simply copy over the image identifiers. |
| 435 | if (overlapping_images.size() == num_eff_images) { |
| 436 | for (const auto& overlapping_image : overlapping_images) { |
| 437 | local_bundle_image_ids.push_back(overlapping_image.first); |
| 438 | } |
nothing calls this directly
no test coverage detected