| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #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 |
|
|