-
Notifications
You must be signed in to change notification settings - Fork 281
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make global descriptor flags available to CLI. Small improvments to s…
…tability of FV computation.
- Loading branch information
Chris Sweeney
authored and
Chris Sweeney
committed
Sep 29, 2018
1 parent
287c009
commit 8d5bb9b
Showing
5 changed files
with
135 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,12 +32,12 @@ | |
// Please contact the author of this library if you have any questions. | ||
// Author: Chris Sweeney ([email protected]) | ||
|
||
#include <glog/logging.h> | ||
#include <gflags/gflags.h> | ||
#include <time.h> | ||
#include <theia/theia.h> | ||
#include <chrono> // NOLINT | ||
#include <gflags/gflags.h> | ||
#include <glog/logging.h> | ||
#include <string> | ||
#include <theia/theia.h> | ||
#include <time.h> | ||
#include <vector> | ||
|
||
#include "applications/command_line_helpers.h" | ||
|
@@ -46,72 +46,102 @@ | |
DEFINE_string(images, "", "Wildcard of images to reconstruct."); | ||
DEFINE_string(image_masks, "", "Wildcard of image masks to reconstruct."); | ||
DEFINE_string(matches_file, "", "Filename of the matches file."); | ||
DEFINE_string(calibration_file, "", | ||
DEFINE_string(calibration_file, | ||
"", | ||
"Calibration file containing image calibration data."); | ||
DEFINE_string( | ||
output_matches_file, "", | ||
output_matches_file, | ||
"", | ||
"File to write the two-view matches to. This file can be used in " | ||
"future iterations as input to the reconstruction builder. Leave empty if " | ||
"you do not want to output matches."); | ||
DEFINE_string( | ||
output_reconstruction, "", | ||
output_reconstruction, | ||
"", | ||
"Filename to write reconstruction to. The filename will be appended with " | ||
"the reconstruction number if multiple reconstructions are created."); | ||
|
||
// Multithreading. | ||
DEFINE_int32(num_threads, 1, | ||
DEFINE_int32(num_threads, | ||
1, | ||
"Number of threads to use for feature extraction and matching."); | ||
|
||
// Feature and matching options. | ||
DEFINE_string( | ||
descriptor, "SIFT", | ||
descriptor, | ||
"SIFT", | ||
"Type of feature descriptor to use. Must be one of the following: " | ||
"SIFT"); | ||
DEFINE_string(feature_density, "NORMAL", | ||
DEFINE_string(feature_density, | ||
"NORMAL", | ||
"Set to SPARSE, NORMAL, or DENSE to extract fewer or more " | ||
"features from each image."); | ||
DEFINE_string(matching_strategy, "CASCADE_HASHING", | ||
DEFINE_string(matching_strategy, | ||
"CASCADE_HASHING", | ||
"Strategy used to match features. Must be BRUTE_FORCE " | ||
" or CASCADE_HASHING"); | ||
DEFINE_bool(match_out_of_core, true, | ||
DEFINE_bool(match_out_of_core, | ||
true, | ||
"Perform matching out of core by saving features to disk and " | ||
"reading them as needed. Set to false to perform matching all in " | ||
"memory."); | ||
DEFINE_string(matching_working_directory, "", | ||
DEFINE_string(matching_working_directory, | ||
"", | ||
"Directory used during matching to store features for " | ||
"out-of-core matching."); | ||
DEFINE_int32(matching_max_num_images_in_cache, 128, | ||
DEFINE_int32(matching_max_num_images_in_cache, | ||
128, | ||
"Maximum number of images to store in the LRU cache during " | ||
"feature matching. The higher this number is the more memory is " | ||
"consumed during matching."); | ||
DEFINE_double(lowes_ratio, 0.8, "Lowes ratio used for feature matching."); | ||
DEFINE_double(max_sampson_error_for_verified_match, 4.0, | ||
DEFINE_double(max_sampson_error_for_verified_match, | ||
4.0, | ||
"Maximum sampson error for a match to be considered " | ||
"geometrically valid. This threshold is relative to an image " | ||
"with a width of 1024 pixels and will be appropriately scaled " | ||
"for images with different resolutions."); | ||
DEFINE_int32(min_num_inliers_for_valid_match, 30, | ||
DEFINE_int32(min_num_inliers_for_valid_match, | ||
30, | ||
"Minimum number of geometrically verified inliers that a pair on " | ||
"images must have in order to be considered a valid two-view " | ||
"match."); | ||
DEFINE_bool(bundle_adjust_two_view_geometry, true, | ||
DEFINE_bool(bundle_adjust_two_view_geometry, | ||
true, | ||
"Set to false to turn off 2-view BA."); | ||
DEFINE_bool(keep_only_symmetric_matches, true, | ||
DEFINE_bool(keep_only_symmetric_matches, | ||
true, | ||
"Performs two-way matching and keeps symmetric matches."); | ||
DEFINE_int32( | ||
num_nearest_neighbors_for_global_descriptor_matching, | ||
100, | ||
"Number of nearest neighbor images to use for full descriptor matching."); | ||
DEFINE_int32(num_gmm_clusters_for_fisher_vector, | ||
16, | ||
"Number of clusters to use for the GMM with Fisher Vectors for " | ||
"global image descriptors."); | ||
DEFINE_int32(max_num_features_for_fisher_vector_training, | ||
1000000, | ||
"Number of features to use to train the Fisher Vector kernel for " | ||
"global image descriptor extraction."); | ||
|
||
// Reconstruction building options. | ||
DEFINE_string(reconstruction_estimator, "GLOBAL", | ||
DEFINE_string(reconstruction_estimator, | ||
"GLOBAL", | ||
"Type of SfM reconstruction estimation to use."); | ||
DEFINE_bool(reconstruct_largest_connected_component, false, | ||
DEFINE_bool(reconstruct_largest_connected_component, | ||
false, | ||
"If set to true, only the single largest connected component is " | ||
"reconstructed. Otherwise, as many models as possible are " | ||
"estimated."); | ||
DEFINE_bool(shared_calibration, false, | ||
DEFINE_bool(shared_calibration, | ||
false, | ||
"Set to true if all camera intrinsic parameters should be shared " | ||
"as a single set of intrinsics. This is useful, for instance, if " | ||
"all images in the reconstruction were taken with the same " | ||
"camera."); | ||
DEFINE_bool(only_calibrated_views, false, | ||
DEFINE_bool(only_calibrated_views, | ||
false, | ||
"Set to true to only reconstruct the views where calibration is " | ||
"provided or can be extracted from EXIF"); | ||
DEFINE_int32(min_track_length, 2, "Minimum length of a track."); | ||
|
@@ -120,99 +150,123 @@ DEFINE_string(intrinsics_to_optimize, | |
"NONE", | ||
"Set to control which intrinsics parameters are optimized during " | ||
"bundle adjustment."); | ||
DEFINE_double(max_reprojection_error_pixels, 4.0, | ||
DEFINE_double(max_reprojection_error_pixels, | ||
4.0, | ||
"Maximum reprojection error for a correspondence to be " | ||
"considered an inlier after bundle adjustment."); | ||
|
||
// Global SfM options. | ||
DEFINE_string(global_rotation_estimator, "ROBUST_L1L2", | ||
DEFINE_string(global_rotation_estimator, | ||
"ROBUST_L1L2", | ||
"Type of global rotation estimation to use for global SfM."); | ||
DEFINE_string(global_position_estimator, "NONLINEAR", | ||
DEFINE_string(global_position_estimator, | ||
"NONLINEAR", | ||
"Type of global position estimation to use for global SfM."); | ||
DEFINE_bool(refine_relative_translations_after_rotation_estimation, true, | ||
DEFINE_bool(refine_relative_translations_after_rotation_estimation, | ||
true, | ||
"Refine the relative translation estimation after computing the " | ||
"absolute rotations. This can help improve the accuracy of the " | ||
"position estimation."); | ||
DEFINE_double(post_rotation_filtering_degrees, 5.0, | ||
DEFINE_double(post_rotation_filtering_degrees, | ||
5.0, | ||
"Max degrees difference in relative rotation and rotation " | ||
"estimates for rotation filtering."); | ||
DEFINE_bool(extract_maximal_rigid_subgraph, false, | ||
DEFINE_bool(extract_maximal_rigid_subgraph, | ||
false, | ||
"If true, only cameras that are well-conditioned for position " | ||
"estimation will be used for global position estimation."); | ||
DEFINE_bool(filter_relative_translations_with_1dsfm, true, | ||
DEFINE_bool(filter_relative_translations_with_1dsfm, | ||
true, | ||
"Filter relative translation estimations with the 1DSfM algorithm " | ||
"to potentially remove outlier relativep oses for position " | ||
"estimation."); | ||
DEFINE_bool(refine_camera_positions_and_points_after_position_estimation, true, | ||
DEFINE_bool(refine_camera_positions_and_points_after_position_estimation, | ||
true, | ||
"After estimating positions in Global SfM we can refine only " | ||
"camera positions and 3D point locations, holding camera " | ||
"intrinsics and rotations constant. This often improves the " | ||
"stability of bundle adjustment when the camera intrinsics are " | ||
"inaccurate."); | ||
DEFINE_int32(num_retriangulation_iterations, 1, | ||
DEFINE_int32(num_retriangulation_iterations, | ||
1, | ||
"Number of times to retriangulate any unestimated tracks. Bundle " | ||
"adjustment is performed after retriangulation."); | ||
|
||
// Nonlinear position estimation options. | ||
DEFINE_int32( | ||
position_estimation_min_num_tracks_per_view, 0, | ||
position_estimation_min_num_tracks_per_view, | ||
0, | ||
"Minimum number of point to camera constraints for position estimation."); | ||
DEFINE_double(position_estimation_robust_loss_width, 0.1, | ||
DEFINE_double(position_estimation_robust_loss_width, | ||
0.1, | ||
"Robust loss width to use for position estimation."); | ||
|
||
// Incremental SfM options. | ||
DEFINE_double(absolute_pose_reprojection_error_threshold, 4.0, | ||
DEFINE_double(absolute_pose_reprojection_error_threshold, | ||
4.0, | ||
"The inlier threshold for absolute pose estimation. This " | ||
"threshold is relative to an image with a width of 1024 pixels " | ||
"and will be appropriately scaled based on the input image " | ||
"resolutions."); | ||
DEFINE_int32(min_num_absolute_pose_inliers, 30, | ||
DEFINE_int32(min_num_absolute_pose_inliers, | ||
30, | ||
"Minimum number of inliers in order for absolute pose estimation " | ||
"to be considered successful."); | ||
DEFINE_double(full_bundle_adjustment_growth_percent, 5.0, | ||
DEFINE_double(full_bundle_adjustment_growth_percent, | ||
5.0, | ||
"Full BA is only triggered for incremental SfM when the " | ||
"reconstruction has growth by this percent since the last time " | ||
"full BA was used."); | ||
DEFINE_int32(partial_bundle_adjustment_num_views, 20, | ||
DEFINE_int32(partial_bundle_adjustment_num_views, | ||
20, | ||
"When full BA is not being run, partial BA is executed on a " | ||
"constant number of views specified by this parameter."); | ||
|
||
// Triangulation options. | ||
DEFINE_double(min_triangulation_angle_degrees, 4.0, | ||
DEFINE_double(min_triangulation_angle_degrees, | ||
4.0, | ||
"Minimum angle between views for triangulation."); | ||
DEFINE_double( | ||
triangulation_reprojection_error_pixels, 15.0, | ||
triangulation_reprojection_error_pixels, | ||
15.0, | ||
"Max allowable reprojection error on initial triangulation of points."); | ||
DEFINE_bool(bundle_adjust_tracks, true, | ||
DEFINE_bool(bundle_adjust_tracks, | ||
true, | ||
"Set to true to optimize tracks immediately upon estimation."); | ||
|
||
// Bundle adjustment parameters. | ||
DEFINE_string(bundle_adjustment_robust_loss_function, "NONE", | ||
DEFINE_string(bundle_adjustment_robust_loss_function, | ||
"NONE", | ||
"By setting this to an option other than NONE, a robust loss " | ||
"function will be used during bundle adjustment which can " | ||
"improve robustness to outliers. Options are NONE, HUBER, " | ||
"SOFTLONE, CAUCHY, ARCTAN, and TUKEY."); | ||
DEFINE_double(bundle_adjustment_robust_loss_width, 10.0, | ||
DEFINE_double(bundle_adjustment_robust_loss_width, | ||
10.0, | ||
"If the BA loss function is not NONE, then this value controls " | ||
"where the robust loss begins with respect to reprojection error " | ||
"in pixels."); | ||
|
||
// Track Subsampling parameters. | ||
DEFINE_bool(subsample_tracks_for_bundle_adjustment, false, | ||
DEFINE_bool(subsample_tracks_for_bundle_adjustment, | ||
false, | ||
"Set to true to subsample tracks used for bundle adjustment. This " | ||
"can help improve efficiency of bundle adjustment dramatically " | ||
"when used properly."); | ||
DEFINE_int32(track_subset_selection_long_track_length_threshold, 10, | ||
DEFINE_int32(track_subset_selection_long_track_length_threshold, | ||
10, | ||
"When track subsampling is enabled, longer tracks are chosen with " | ||
"a higher probability with the track length capped to this value " | ||
"for selection."); | ||
DEFINE_int32(track_selection_image_grid_cell_size_pixels, 100, | ||
DEFINE_int32(track_selection_image_grid_cell_size_pixels, | ||
100, | ||
"When track subsampling is enabled, tracks are chosen such that " | ||
"each view has a good spatial coverage. This is achieved by " | ||
"binning tracks into an image grid in each view and choosing the " | ||
"best tracks in each grid cell to guarantee spatial coverage. The " | ||
"image grid cells are defined to be this width in pixels."); | ||
DEFINE_int32(min_num_optimized_tracks_per_view, 100, | ||
DEFINE_int32(min_num_optimized_tracks_per_view, | ||
100, | ||
"When track subsampling is enabled, tracks are selected such that " | ||
"each view observes a minimum number of optimized tracks."); | ||
|
||
|
@@ -254,6 +308,13 @@ ReconstructionBuilderOptions SetReconstructionBuilderOptions() { | |
.min_triangulation_angle_degrees = FLAGS_min_triangulation_angle_degrees; | ||
options.matching_options.geometric_verification_options | ||
.final_max_reprojection_error = FLAGS_max_reprojection_error_pixels; | ||
options.matching_options | ||
.num_nearest_neighbors_for_global_descriptor_matching = | ||
FLAGS_num_nearest_neighbors_for_global_descriptor_matching; | ||
options.matching_options.num_gmm_clusters_for_fisher_vector = | ||
FLAGS_num_gmm_clusters_for_fisher_vector; | ||
options.matching_options.max_num_features_for_fisher_vector_training = | ||
FLAGS_max_num_features_for_fisher_vector_training; | ||
|
||
options.min_track_length = FLAGS_min_track_length; | ||
options.max_track_length = FLAGS_max_track_length; | ||
|
@@ -265,7 +326,7 @@ ReconstructionBuilderOptions SetReconstructionBuilderOptions() { | |
FLAGS_min_num_inliers_for_valid_match; | ||
reconstruction_estimator_options.num_threads = FLAGS_num_threads; | ||
reconstruction_estimator_options.intrinsics_to_optimize = | ||
StringToOptimizeIntrinsicsType(FLAGS_intrinsics_to_optimize); | ||
StringToOptimizeIntrinsicsType(FLAGS_intrinsics_to_optimize); | ||
options.reconstruct_largest_connected_component = | ||
FLAGS_reconstruct_largest_connected_component; | ||
options.only_calibrated_views = FLAGS_only_calibrated_views; | ||
|
@@ -290,8 +351,7 @@ ReconstructionBuilderOptions SetReconstructionBuilderOptions() { | |
FLAGS_extract_maximal_rigid_subgraph; | ||
reconstruction_estimator_options.filter_relative_translations_with_1dsfm = | ||
FLAGS_filter_relative_translations_with_1dsfm; | ||
reconstruction_estimator_options | ||
.rotation_filtering_max_difference_degrees = | ||
reconstruction_estimator_options.rotation_filtering_max_difference_degrees = | ||
FLAGS_post_rotation_filtering_degrees; | ||
reconstruction_estimator_options.nonlinear_position_estimator_options | ||
.min_num_points_per_view = | ||
|
@@ -301,13 +361,11 @@ ReconstructionBuilderOptions SetReconstructionBuilderOptions() { | |
FLAGS_refine_camera_positions_and_points_after_position_estimation; | ||
|
||
// Incremental SfM Options. | ||
reconstruction_estimator_options | ||
.absolute_pose_reprojection_error_threshold = | ||
reconstruction_estimator_options.absolute_pose_reprojection_error_threshold = | ||
FLAGS_absolute_pose_reprojection_error_threshold; | ||
reconstruction_estimator_options.min_num_absolute_pose_inliers = | ||
FLAGS_min_num_absolute_pose_inliers; | ||
reconstruction_estimator_options | ||
.full_bundle_adjustment_growth_percent = | ||
reconstruction_estimator_options.full_bundle_adjustment_growth_percent = | ||
FLAGS_full_bundle_adjustment_growth_percent; | ||
reconstruction_estimator_options.partial_bundle_adjustment_num_views = | ||
FLAGS_partial_bundle_adjustment_num_views; | ||
|
@@ -369,9 +427,8 @@ void AddMatchesToReconstructionBuilder( | |
|
||
// Add the matches. | ||
for (const auto& match : image_matches) { | ||
CHECK(reconstruction_builder->AddTwoViewMatch(match.image1, | ||
match.image2, | ||
match)); | ||
CHECK(reconstruction_builder->AddTwoViewMatch( | ||
match.image1, match.image2, match)); | ||
} | ||
} | ||
|
||
|
@@ -407,7 +464,7 @@ void AddImagesToReconstructionBuilder( | |
CHECK(theia::GetFilenameFromFilepath(image_file, true, &image_filename)); | ||
|
||
const theia::CameraIntrinsicsPrior* image_camera_intrinsics_prior = | ||
FindOrNull(camera_intrinsics_prior, image_filename); | ||
FindOrNull(camera_intrinsics_prior, image_filename); | ||
if (image_camera_intrinsics_prior != nullptr) { | ||
CHECK(reconstruction_builder->AddImageWithCameraIntrinsicsPrior( | ||
image_file, *image_camera_intrinsics_prior, intrinsics_group_id)); | ||
|
@@ -424,21 +481,18 @@ void AddImagesToReconstructionBuilder( | |
std::vector<std::string> mask_files; | ||
if (FLAGS_image_masks.size() != 0) { | ||
CHECK(theia::GetFilepathsFromWildcard(FLAGS_image_masks, &mask_files)) | ||
<< "Could not find image masks that matched the filepath: " | ||
<< FLAGS_image_masks | ||
<< ". NOTE that the ~ filepath is not supported."; | ||
<< "Could not find image masks that matched the filepath: " | ||
<< FLAGS_image_masks << ". NOTE that the ~ filepath is not supported."; | ||
if (mask_files.size() > 0) { | ||
for (const std::string& image_file : image_files) { | ||
std::string image_filename; | ||
CHECK(theia::GetFilenameFromFilepath(image_file, | ||
false, | ||
&image_filename)); | ||
CHECK( | ||
theia::GetFilenameFromFilepath(image_file, false, &image_filename)); | ||
// Find and add the associated mask | ||
for (const std::string& mask_file : mask_files) { | ||
if (mask_file.find(image_filename) != std::string::npos) { | ||
CHECK(reconstruction_builder->AddMaskForFeaturesExtraction( | ||
image_file, | ||
mask_file)); | ||
image_file, mask_file)); | ||
break; | ||
} | ||
} | ||
|
@@ -452,7 +506,7 @@ void AddImagesToReconstructionBuilder( | |
CHECK(reconstruction_builder->ExtractAndMatchFeatures()); | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
int main(int argc, char* argv[]) { | ||
THEIA_GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true); | ||
google::InitGoogleLogging(argv[0]); | ||
|
||
|
Oops, something went wrong.