| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef COLMAP_SRC_FEATURE_MATCHING_H_ |
| | #define COLMAP_SRC_FEATURE_MATCHING_H_ |
| |
|
| | #include <array> |
| | #include <string> |
| | #include <vector> |
| |
|
| | #include "base/database.h" |
| | #include "feature/sift.h" |
| | #include "util/alignment.h" |
| | #include "util/cache.h" |
| | #include "util/opengl_utils.h" |
| | #include "util/threading.h" |
| | #include "util/timer.h" |
| |
|
| | namespace colmap { |
| |
|
| | struct ExhaustiveMatchingOptions { |
| | |
| | int block_size = 50; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | struct SequentialMatchingOptions { |
| | |
| | int overlap = 10; |
| |
|
| | |
| | bool quadratic_overlap = true; |
| |
|
| | |
| | bool loop_detection = false; |
| |
|
| | |
| | int loop_detection_period = 10; |
| |
|
| | |
| | |
| | int loop_detection_num_images = 50; |
| |
|
| | |
| | int loop_detection_num_nearest_neighbors = 1; |
| |
|
| | |
| | int loop_detection_num_checks = 256; |
| |
|
| | |
| | |
| | int loop_detection_num_images_after_verification = 0; |
| |
|
| | |
| | |
| | int loop_detection_max_num_features = -1; |
| |
|
| | |
| | std::string vocab_tree_path = ""; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | struct VocabTreeMatchingOptions { |
| | |
| | int num_images = 100; |
| |
|
| | |
| | int num_nearest_neighbors = 5; |
| |
|
| | |
| | int num_checks = 256; |
| |
|
| | |
| | |
| | int num_images_after_verification = 0; |
| |
|
| | |
| | |
| | int max_num_features = -1; |
| |
|
| | |
| | std::string vocab_tree_path = ""; |
| |
|
| | |
| | std::string match_list_path = ""; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | struct SpatialMatchingOptions { |
| | |
| | |
| | bool is_gps = true; |
| |
|
| | |
| | bool ignore_z = true; |
| |
|
| | |
| | int max_num_neighbors = 50; |
| |
|
| | |
| | |
| | double max_distance = 100; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | struct TransitiveMatchingOptions { |
| | |
| | int batch_size = 1000; |
| |
|
| | |
| | int num_iterations = 3; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | struct ImagePairsMatchingOptions { |
| | |
| | int block_size = 1225; |
| |
|
| | |
| | std::string match_list_path = ""; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | struct FeaturePairsMatchingOptions { |
| | |
| | bool verify_matches = true; |
| |
|
| | |
| | std::string match_list_path = ""; |
| |
|
| | bool Check() const; |
| | }; |
| |
|
| | namespace internal { |
| |
|
| | struct FeatureMatcherData { |
| | image_t image_id1 = kInvalidImageId; |
| | image_t image_id2 = kInvalidImageId; |
| | FeatureMatches matches; |
| | TwoViewGeometry two_view_geometry; |
| | }; |
| |
|
| | } |
| |
|
| | using FeatureKeypointsPtr = std::shared_ptr<FeatureKeypoints>; |
| | using FeatureDescriptorsPtr = std::shared_ptr<FeatureDescriptors>; |
| |
|
| | |
| | class FeatureMatcherCache { |
| | public: |
| | FeatureMatcherCache(const size_t cache_size, const Database* database); |
| |
|
| | void Setup(); |
| |
|
| | const Camera& GetCamera(const camera_t camera_id) const; |
| | const Image& GetImage(const image_t image_id) const; |
| | FeatureKeypointsPtr GetKeypoints(const image_t image_id); |
| | FeatureDescriptorsPtr GetDescriptors(const image_t image_id); |
| | FeatureMatches GetMatches(const image_t image_id1, const image_t image_id2); |
| | std::vector<image_t> GetImageIds() const; |
| |
|
| | bool ExistsKeypoints(const image_t image_id); |
| | bool ExistsDescriptors(const image_t image_id); |
| |
|
| | bool ExistsMatches(const image_t image_id1, const image_t image_id2); |
| | bool ExistsInlierMatches(const image_t image_id1, const image_t image_id2); |
| |
|
| | void WriteMatches(const image_t image_id1, const image_t image_id2, |
| | const FeatureMatches& matches); |
| | void WriteTwoViewGeometry(const image_t image_id1, const image_t image_id2, |
| | const TwoViewGeometry& two_view_geometry); |
| |
|
| | void DeleteMatches(const image_t image_id1, const image_t image_id2); |
| | void DeleteInlierMatches(const image_t image_id1, const image_t image_id2); |
| |
|
| | private: |
| | const size_t cache_size_; |
| | const Database* database_; |
| | std::mutex database_mutex_; |
| | EIGEN_STL_UMAP(camera_t, Camera) cameras_cache_; |
| | EIGEN_STL_UMAP(image_t, Image) images_cache_; |
| | std::unique_ptr<LRUCache<image_t, FeatureKeypointsPtr>> keypoints_cache_; |
| | std::unique_ptr<LRUCache<image_t, FeatureDescriptorsPtr>> descriptors_cache_; |
| | std::unique_ptr<LRUCache<image_t, bool>> keypoints_exists_cache_; |
| | std::unique_ptr<LRUCache<image_t, bool>> descriptors_exists_cache_; |
| | }; |
| |
|
| | class FeatureMatcherThread : public Thread { |
| | public: |
| | FeatureMatcherThread(const SiftMatchingOptions& options, |
| | FeatureMatcherCache* cache); |
| |
|
| | void SetMaxNumMatches(const int max_num_matches); |
| |
|
| | protected: |
| | SiftMatchingOptions options_; |
| | FeatureMatcherCache* cache_; |
| | }; |
| |
|
| | class SiftCPUFeatureMatcher : public FeatureMatcherThread { |
| | public: |
| | typedef internal::FeatureMatcherData Input; |
| | typedef internal::FeatureMatcherData Output; |
| |
|
| | SiftCPUFeatureMatcher(const SiftMatchingOptions& options, |
| | FeatureMatcherCache* cache, |
| | JobQueue<Input>* input_queue, |
| | JobQueue<Output>* output_queue); |
| |
|
| | protected: |
| | void Run() override; |
| |
|
| | JobQueue<Input>* input_queue_; |
| | JobQueue<Output>* output_queue_; |
| | }; |
| |
|
| | class SiftGPUFeatureMatcher : public FeatureMatcherThread { |
| | public: |
| | typedef internal::FeatureMatcherData Input; |
| | typedef internal::FeatureMatcherData Output; |
| |
|
| | SiftGPUFeatureMatcher(const SiftMatchingOptions& options, |
| | FeatureMatcherCache* cache, |
| | JobQueue<Input>* input_queue, |
| | JobQueue<Output>* output_queue); |
| |
|
| | protected: |
| | void Run() override; |
| |
|
| | void GetDescriptorData(const int index, const image_t image_id, |
| | const FeatureDescriptors** descriptors_ptr); |
| |
|
| | JobQueue<Input>* input_queue_; |
| | JobQueue<Output>* output_queue_; |
| |
|
| | std::unique_ptr<OpenGLContextManager> opengl_context_; |
| |
|
| | |
| | std::array<image_t, 2> prev_uploaded_image_ids_; |
| | std::array<FeatureDescriptorsPtr, 2> prev_uploaded_descriptors_; |
| | }; |
| |
|
| | class GuidedSiftCPUFeatureMatcher : public FeatureMatcherThread { |
| | public: |
| | typedef internal::FeatureMatcherData Input; |
| | typedef internal::FeatureMatcherData Output; |
| |
|
| | GuidedSiftCPUFeatureMatcher(const SiftMatchingOptions& options, |
| | FeatureMatcherCache* cache, |
| | JobQueue<Input>* input_queue, |
| | JobQueue<Output>* output_queue); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | JobQueue<Input>* input_queue_; |
| | JobQueue<Output>* output_queue_; |
| | }; |
| |
|
| | class GuidedSiftGPUFeatureMatcher : public FeatureMatcherThread { |
| | public: |
| | typedef internal::FeatureMatcherData Input; |
| | typedef internal::FeatureMatcherData Output; |
| |
|
| | GuidedSiftGPUFeatureMatcher(const SiftMatchingOptions& options, |
| | FeatureMatcherCache* cache, |
| | JobQueue<Input>* input_queue, |
| | JobQueue<Output>* output_queue); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | void GetFeatureData(const int index, const image_t image_id, |
| | const FeatureKeypoints** keypoints_ptr, |
| | const FeatureDescriptors** descriptors_ptr); |
| |
|
| | JobQueue<Input>* input_queue_; |
| | JobQueue<Output>* output_queue_; |
| |
|
| | std::unique_ptr<OpenGLContextManager> opengl_context_; |
| |
|
| | |
| | std::array<image_t, 2> prev_uploaded_image_ids_; |
| | std::array<FeatureKeypointsPtr, 2> prev_uploaded_keypoints_; |
| | std::array<FeatureDescriptorsPtr, 2> prev_uploaded_descriptors_; |
| | }; |
| |
|
| | class TwoViewGeometryVerifier : public Thread { |
| | public: |
| | typedef internal::FeatureMatcherData Input; |
| | typedef internal::FeatureMatcherData Output; |
| |
|
| | TwoViewGeometryVerifier(const SiftMatchingOptions& options, |
| | FeatureMatcherCache* cache, |
| | JobQueue<Input>* input_queue, |
| | JobQueue<Output>* output_queue); |
| |
|
| | protected: |
| | void Run() override; |
| |
|
| | const SiftMatchingOptions options_; |
| | TwoViewGeometry::Options two_view_geometry_options_; |
| | FeatureMatcherCache* cache_; |
| | JobQueue<Input>* input_queue_; |
| | JobQueue<Output>* output_queue_; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | class SiftFeatureMatcher { |
| | public: |
| | SiftFeatureMatcher(const SiftMatchingOptions& options, Database* database, |
| | FeatureMatcherCache* cache); |
| |
|
| | ~SiftFeatureMatcher(); |
| |
|
| | |
| | bool Setup(); |
| |
|
| | |
| | void Match(const std::vector<std::pair<image_t, image_t>>& image_pairs); |
| |
|
| | private: |
| | SiftMatchingOptions options_; |
| | Database* database_; |
| | FeatureMatcherCache* cache_; |
| |
|
| | bool is_setup_; |
| |
|
| | std::vector<std::unique_ptr<FeatureMatcherThread>> matchers_; |
| | std::vector<std::unique_ptr<FeatureMatcherThread>> guided_matchers_; |
| | std::vector<std::unique_ptr<Thread>> verifiers_; |
| | std::unique_ptr<ThreadPool> thread_pool_; |
| |
|
| | JobQueue<internal::FeatureMatcherData> matcher_queue_; |
| | JobQueue<internal::FeatureMatcherData> verifier_queue_; |
| | JobQueue<internal::FeatureMatcherData> guided_matcher_queue_; |
| | JobQueue<internal::FeatureMatcherData> output_queue_; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | class ExhaustiveFeatureMatcher : public Thread { |
| | public: |
| | ExhaustiveFeatureMatcher(const ExhaustiveMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | const ExhaustiveMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | SiftFeatureMatcher matcher_; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | class SequentialFeatureMatcher : public Thread { |
| | public: |
| | SequentialFeatureMatcher(const SequentialMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | std::vector<image_t> GetOrderedImageIds() const; |
| | void RunSequentialMatching(const std::vector<image_t>& image_ids); |
| | void RunLoopDetection(const std::vector<image_t>& image_ids); |
| |
|
| | const SequentialMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | SiftFeatureMatcher matcher_; |
| | }; |
| |
|
| | |
| | class VocabTreeFeatureMatcher : public Thread { |
| | public: |
| | VocabTreeFeatureMatcher(const VocabTreeMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | const VocabTreeMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | SiftFeatureMatcher matcher_; |
| | }; |
| |
|
| | |
| | |
| | class SpatialFeatureMatcher : public Thread { |
| | public: |
| | SpatialFeatureMatcher(const SpatialMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | const SpatialMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | SiftFeatureMatcher matcher_; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | class TransitiveFeatureMatcher : public Thread { |
| | public: |
| | TransitiveFeatureMatcher(const TransitiveMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | const TransitiveMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | SiftFeatureMatcher matcher_; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | class ImagePairsFeatureMatcher : public Thread { |
| | public: |
| | ImagePairsFeatureMatcher(const ImagePairsMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | void Run() override; |
| |
|
| | const ImagePairsMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | SiftFeatureMatcher matcher_; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | class FeaturePairsFeatureMatcher : public Thread { |
| | public: |
| | FeaturePairsFeatureMatcher(const FeaturePairsMatchingOptions& options, |
| | const SiftMatchingOptions& match_options, |
| | const std::string& database_path); |
| |
|
| | private: |
| | const static size_t kCacheSize = 100; |
| |
|
| | void Run() override; |
| |
|
| | const FeaturePairsMatchingOptions options_; |
| | const SiftMatchingOptions match_options_; |
| | Database database_; |
| | FeatureMatcherCache cache_; |
| | }; |
| |
|
| | } |
| |
|
| | #endif |
| |
|