Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/colmap/controllers/incremental_mapper_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,35 @@ TEST(IncrementalMapperController, MultiReconstruction) {
/*num_obs_tolerance=*/0);
}

TEST(IncrementalMapperController, ChainedMatches) {
const std::string database_path = CreateTestDir() + "/database.db";

Database database(database_path);
Reconstruction gt_reconstruction;
SyntheticDatasetOptions synthetic_dataset_options;
synthetic_dataset_options.match_config =
SyntheticDatasetOptions::MatchConfig::CHAINED;
synthetic_dataset_options.num_cameras = 1;
synthetic_dataset_options.num_images = 4;
synthetic_dataset_options.num_points3D = 100;
synthetic_dataset_options.point2D_stddev = 0;
SynthesizeDataset(synthetic_dataset_options, &gt_reconstruction, &database);

auto reconstruction_manager = std::make_shared<ReconstructionManager>();
IncrementalMapperController mapper(
std::make_shared<IncrementalMapperOptions>(),
/*image_path=*/"",
database_path,
reconstruction_manager);
mapper.Start();
mapper.Wait();

ASSERT_EQ(reconstruction_manager->Size(), 1);
ExpectEqualReconstructions(gt_reconstruction,
*reconstruction_manager->Get(0),
/*max_rotation_error_deg=*/1e-2,
/*max_proj_center_error=*/1e-4,
/*num_obs_tolerance=*/0);
}

} // namespace colmap
124 changes: 90 additions & 34 deletions src/colmap/scene/synthetic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,87 @@
#include <Eigen/Geometry>

namespace colmap {
namespace {

void SynthesizeExhaustiveMatches(Reconstruction* reconstruction,
Database* database) {
const std::vector<image_t>& reg_image_ids = reconstruction->RegImageIds();
for (size_t image_idx1 = 0; image_idx1 < reg_image_ids.size(); ++image_idx1) {
const auto& image1 = reconstruction->Image(reg_image_ids[image_idx1]);
const auto num_points2D1 = image1.NumPoints2D();
for (size_t image_idx2 = 0; image_idx2 < image_idx1; ++image_idx2) {
const auto& image2 = reconstruction->Image(reg_image_ids[image_idx2]);
const auto num_points2D2 = image2.NumPoints2D();

TwoViewGeometry two_view_geometry;
two_view_geometry.config = TwoViewGeometry::CALIBRATED;
const Rigid3d cam2_from_cam1 =
image2.CamFromWorld() * Inverse(image1.CamFromWorld());
two_view_geometry.E = EssentialMatrixFromPose(cam2_from_cam1);

for (point2D_t point2D_idx1 = 0; point2D_idx1 < num_points2D1;
++point2D_idx1) {
const auto& point2D1 = image1.Point2D(point2D_idx1);
if (!point2D1.HasPoint3D()) {
continue;
}
for (point2D_t point2D_idx2 = 0; point2D_idx2 < num_points2D2;
++point2D_idx2) {
const auto& point2D2 = image2.Point2D(point2D_idx2);
if (point2D1.point3D_id == point2D2.point3D_id) {
two_view_geometry.inlier_matches.emplace_back(point2D_idx1,
point2D_idx2);
break;
}
}
}

database->WriteTwoViewGeometry(
image1.ImageId(), image2.ImageId(), two_view_geometry);
}
}
}

void SynthesizeChainedMatches(Reconstruction* reconstruction,
Database* database) {
std::unordered_map<image_pair_t, TwoViewGeometry> two_view_geometries;
for (const auto& point3D : reconstruction->Points3D()) {
std::vector<TrackElement> track_elements =
point3D.second.Track().Elements();
std::shuffle(track_elements.begin(), track_elements.end(), *PRNG);
for (size_t i = 1; i < track_elements.size(); ++i) {
const auto& prev_track_el = track_elements[i - 1];
const auto& curr_track_el = track_elements[i];
const image_pair_t pair_id = Database::ImagePairToPairId(
prev_track_el.image_id, curr_track_el.image_id);
if (Database::SwapImagePair(prev_track_el.image_id,
curr_track_el.image_id)) {
two_view_geometries[pair_id].inlier_matches.emplace_back(
curr_track_el.point2D_idx, prev_track_el.point2D_idx);
} else {
two_view_geometries[pair_id].inlier_matches.emplace_back(
prev_track_el.point2D_idx, curr_track_el.point2D_idx);
}
}
}

for (auto& two_view_geometry : two_view_geometries) {
image_t image_id1;
image_t image_id2;
Database::PairIdToImagePair(
two_view_geometry.first, &image_id1, &image_id2);
const auto& image1 = reconstruction->Image(image_id1);
const auto& image2 = reconstruction->Image(image_id2);
two_view_geometry.second.config = TwoViewGeometry::CALIBRATED;
const Rigid3d cam2_from_cam1 =
image2.CamFromWorld() * Inverse(image1.CamFromWorld());
two_view_geometry.second.E = EssentialMatrixFromPose(cam2_from_cam1);
database->WriteTwoViewGeometry(
image1.ImageId(), image2.ImageId(), two_view_geometry.second);
}
}

} // namespace

void SynthesizeDataset(const SyntheticDatasetOptions& options,
Reconstruction* reconstruction,
Expand Down Expand Up @@ -147,40 +228,15 @@ void SynthesizeDataset(const SyntheticDatasetOptions& options,
reconstruction->RegisterImage(image_id);
}

const std::vector<image_t>& reg_image_ids = reconstruction->RegImageIds();
for (size_t image_idx1 = 0; image_idx1 < reg_image_ids.size(); ++image_idx1) {
const auto& image1 = reconstruction->Image(reg_image_ids[image_idx1]);
const auto num_points2D1 = image1.NumPoints2D();
for (size_t image_idx2 = 0; image_idx2 < image_idx1; ++image_idx2) {
const auto& image2 = reconstruction->Image(reg_image_ids[image_idx2]);
const auto num_points2D2 = image2.NumPoints2D();

TwoViewGeometry two_view_geometry;
two_view_geometry.config = TwoViewGeometry::CALIBRATED;
const Rigid3d cam2_from_cam1 =
image2.CamFromWorld() * Inverse(image1.CamFromWorld());
two_view_geometry.E = EssentialMatrixFromPose(cam2_from_cam1);

for (point2D_t point2D_idx1 = 0; point2D_idx1 < num_points2D1;
++point2D_idx1) {
const auto& point2D1 = image1.Point2D(point2D_idx1);
if (!point2D1.HasPoint3D()) {
continue;
}
for (point2D_t point2D_idx2 = 0; point2D_idx2 < num_points2D2;
++point2D_idx2) {
const auto& point2D2 = image2.Point2D(point2D_idx2);
if (point2D1.point3D_id == point2D2.point3D_id) {
two_view_geometry.inlier_matches.emplace_back(point2D_idx1,
point2D_idx2);
break;
}
}
}

database->WriteTwoViewGeometry(
image1.ImageId(), image2.ImageId(), two_view_geometry);
}
switch (options.match_config) {
case SyntheticDatasetOptions::MatchConfig::EXHAUSTIVE:
SynthesizeExhaustiveMatches(reconstruction, database);
break;
case SyntheticDatasetOptions::MatchConfig::CHAINED:
SynthesizeChainedMatches(reconstruction, database);
break;
default:
LOG(FATAL) << "Invalid MatchConfig specified";
}

reconstruction->UpdatePoint3DErrors();
Expand Down
8 changes: 8 additions & 0 deletions src/colmap/scene/synthetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ struct SyntheticDatasetOptions {

int num_points2D_without_point3D = 10;
double point2D_stddev = 0.0;

enum class MatchConfig {
// Exhaustive matches between all pairs of observations of a 3D point.
EXHAUSTIVE = 1,
// Chain of matches with random start/end observations.
CHAINED = 2,
};
MatchConfig match_config = MatchConfig::EXHAUSTIVE;
};

void SynthesizeDataset(const SyntheticDatasetOptions& options,
Expand Down
26 changes: 26 additions & 0 deletions src/colmap/scene/synthetic_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,30 @@ TEST(SynthesizeDataset, MultiReconstruction) {
2 * num_image_pairs * options.num_points3D);
}

TEST(SynthesizeDataset, ExhaustiveMatches) {
Database database(Database::kInMemoryDatabasePath);
Reconstruction reconstruction;
SyntheticDatasetOptions options;
options.match_config = SyntheticDatasetOptions::MatchConfig::EXHAUSTIVE;
SynthesizeDataset(options, &reconstruction, &database);

const int num_image_pairs = options.num_images * (options.num_images - 1) / 2;
EXPECT_EQ(database.NumVerifiedImagePairs(), num_image_pairs);
EXPECT_EQ(database.NumInlierMatches(),
num_image_pairs * options.num_points3D);
}

TEST(SynthesizeDataset, ChainedMatches) {
Database database(Database::kInMemoryDatabasePath);
Reconstruction reconstruction;
SyntheticDatasetOptions options;
options.match_config = SyntheticDatasetOptions::MatchConfig::CHAINED;
SynthesizeDataset(options, &reconstruction, &database);

const int num_image_pairs = options.num_images * (options.num_images - 1) / 2;
EXPECT_EQ(database.NumVerifiedImagePairs(), num_image_pairs);
EXPECT_EQ(database.NumInlierMatches(),
(options.num_images - 1) * options.num_points3D);
}

} // namespace colmap