ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
matching.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <array>
11 #include <memory>
12 #include <mutex>
13 #include <string>
14 #include <unordered_map>
15 #include <vector>
16 
17 #include "base/database.h"
18 #include "feature/sift.h"
19 #include "retrieval/resources.h"
20 #include "util/alignment.h"
21 #include "util/cache.h"
22 #include "util/opengl_utils.h"
23 #include "util/threading.h"
24 #include "util/timer.h"
25 
26 namespace colmap {
27 
29  // Block size, i.e. number of images to simultaneously load into memory.
30  int block_size = 50;
31 
32  bool Check() const;
33 };
34 
36  // Number of overlapping image pairs.
37  int overlap = 10;
38 
39  // Whether to match images against their quadratic neighbors.
40  bool quadratic_overlap = true;
41 
42  // Whether to enable vocabulary tree based loop detection.
43  bool loop_detection = false;
44 
45  // Loop detection is invoked every `loop_detection_period` images.
47 
48  // The number of images to retrieve in loop detection. This number should
49  // be significantly bigger than the sequential matching overlap.
51 
52  // Number of nearest neighbors to retrieve per query feature.
54 
55  // Number of nearest-neighbor checks to use in retrieval.
57 
58  // How many images to return after spatial verification. Set to 0 to turn
59  // off spatial verification.
61 
62  // The maximum number of features to use for indexing an image. If an
63  // image has more features, only the largest-scale features will be indexed.
65 
66  // Path to the vocabulary tree.
68 
69  bool Check() const;
70 };
71 
73  // Number of images to retrieve for each query image.
74  int num_images = 100;
75 
76  // Number of nearest neighbors to retrieve per query feature.
78 
79  // Number of nearest-neighbor checks to use in retrieval.
80  int num_checks = 256;
81 
82  // How many images to return after spatial verification. Set to 0 to turn
83  // off spatial verification.
85 
86  // The maximum number of features to use for indexing an image. If an
87  // image has more features, only the largest-scale features will be indexed.
88  int max_num_features = -1;
89 
90  // Path to the vocabulary tree.
92 
93  // Optional path to file with specific image names to match.
94  std::string match_list_path = "";
95 
96  bool Check() const;
97 };
98 
100  // Whether the location priors in the database are GPS coordinates in
101  // the form of longitude and latitude coordinates in degrees.
102  bool is_gps = true;
103 
104  // Whether to ignore the Z-component of the location prior.
105  bool ignore_z = true;
106 
107  // The maximum number of nearest neighbors to match.
109 
110  // The maximum distance between the query and nearest neighbor. For GPS
111  // coordinates the unit is Euclidean distance in meters.
112  double max_distance = 100;
113 
114  bool Check() const;
115 };
116 
118  // The maximum number of image pairs to process in one batch.
119  int batch_size = 1000;
120 
121  // The number of transitive closure iterations.
122  int num_iterations = 3;
123 
124  bool Check() const;
125 };
126 
128  // Number of image pairs to match in one batch.
129  int block_size = 1225;
130 
131  // Path to the file with the matches.
132  std::string match_list_path = "";
133 
134  bool Check() const;
135 };
136 
138  // Whether to geometrically verify the given matches.
139  bool verify_matches = true;
140 
141  // Path to the file with the matches.
142  std::string match_list_path = "";
143 
144  bool Check() const;
145 };
146 
147 namespace internal {
148 
154 };
155 
156 } // namespace internal
157 
158 // Cache for feature matching to minimize database access during matching.
160 public:
161  FeatureMatcherCache(const size_t cache_size, const Database* database);
162 
163  void Setup();
164 
165  const Camera& GetCamera(const camera_t camera_id);
166  const Image& GetImage(const image_t image_id);
167  std::shared_ptr<FeatureKeypoints> GetKeypoints(const image_t image_id);
168  std::shared_ptr<FeatureDescriptors> GetDescriptors(const image_t image_id);
169  FeatureMatches GetMatches(const image_t image_id1, const image_t image_id2);
170  std::vector<image_t> GetImageIds();
171 
172  bool ExistsKeypoints(const image_t image_id);
173  bool ExistsDescriptors(const image_t image_id);
174 
175  bool ExistsMatches(const image_t image_id1, const image_t image_id2);
176  bool ExistsInlierMatches(const image_t image_id1, const image_t image_id2);
177 
178  void WriteMatches(const image_t image_id1,
179  const image_t image_id2,
180  const FeatureMatches& matches);
181  void WriteTwoViewGeometry(const image_t image_id1,
182  const image_t image_id2,
183  const TwoViewGeometry& two_view_geometry);
184 
185  void DeleteMatches(const image_t image_id1, const image_t image_id2);
186  void DeleteInlierMatches(const image_t image_id1, const image_t image_id2);
187 
188 private:
189  void MaybeLoadCameras();
190  void MaybeLoadImages();
191 
192  const size_t cache_size_;
193  const Database* database_;
194  std::mutex database_mutex_;
195  std::unique_ptr<std::unordered_map<camera_t, Camera>> cameras_cache_;
196  std::unique_ptr<std::unordered_map<image_t, Image>> images_cache_;
197  std::unique_ptr<ThreadSafeLRUCache<image_t, FeatureKeypoints>>
198  keypoints_cache_;
199  std::unique_ptr<ThreadSafeLRUCache<image_t, FeatureDescriptors>>
200  descriptors_cache_;
201  std::unique_ptr<ThreadSafeLRUCache<image_t, bool>> keypoints_exists_cache_;
202  std::unique_ptr<ThreadSafeLRUCache<image_t, bool>>
203  descriptors_exists_cache_;
204 };
205 
206 class FeatureMatcherThread : public Thread {
207 public:
209  FeatureMatcherCache* cache);
210 
211  void SetMaxNumMatches(const int max_num_matches);
212 
213 protected:
216 };
217 
219 public:
222 
224  FeatureMatcherCache* cache,
225  JobQueue<Input>* input_queue,
226  JobQueue<Output>* output_queue);
227 
228 protected:
229  void Run() override;
230 
233 };
234 
236 public:
239 
241  FeatureMatcherCache* cache,
242  JobQueue<Input>* input_queue,
243  JobQueue<Output>* output_queue);
244 
245 protected:
246  void Run() override;
247 
248  void GetDescriptorData(const int index,
249  const image_t image_id,
250  const FeatureDescriptors** descriptors_ptr);
251 
254 
255  std::unique_ptr<OpenGLContextManager> opengl_context_;
256 
257  // The previously uploaded images to the GPU.
258  std::array<image_t, 2> prev_uploaded_image_ids_;
259  std::array<FeatureDescriptors, 2> prev_uploaded_descriptors_;
260 };
261 
263 public:
266 
268  FeatureMatcherCache* cache,
269  JobQueue<Input>* input_queue,
270  JobQueue<Output>* output_queue);
271 
272 private:
273  void Run() override;
274 
275  JobQueue<Input>* input_queue_;
276  JobQueue<Output>* output_queue_;
277 };
278 
280 public:
283 
285  FeatureMatcherCache* cache,
286  JobQueue<Input>* input_queue,
287  JobQueue<Output>* output_queue);
288 
289 private:
290  void Run() override;
291 
292  void GetFeatureData(const int index,
293  const image_t image_id,
294  const FeatureKeypoints** keypoints_ptr,
295  const FeatureDescriptors** descriptors_ptr);
296 
297  JobQueue<Input>* input_queue_;
298  JobQueue<Output>* output_queue_;
299 
300  std::unique_ptr<OpenGLContextManager> opengl_context_;
301 
302  // The previously uploaded images to the GPU.
303  std::array<image_t, 2> prev_uploaded_image_ids_;
304  std::array<FeatureKeypoints, 2> prev_uploaded_keypoints_;
305  std::array<FeatureDescriptors, 2> prev_uploaded_descriptors_;
306 };
307 
309 public:
312 
314  FeatureMatcherCache* cache,
315  JobQueue<Input>* input_queue,
316  JobQueue<Output>* output_queue);
317 
318 protected:
319  void Run() override;
320 
326 };
327 
328 // Multi-threaded and multi-GPU SIFT feature matcher, which writes the computed
329 // results to the database and skips already matched image pairs. To improve
330 // performance of the matching by taking advantage of caching and database
331 // transactions, pass multiple images to the `Match` function. Note that the
332 // database should be in an active transaction while calling `Match`.
334 public:
336  Database* database,
337  FeatureMatcherCache* cache);
338 
340 
341  // Setup the matchers and return if successful.
342  bool Setup();
343 
344  // Match one batch of multiple image pairs.
345  void Match(const std::vector<std::pair<image_t, image_t>>& image_pairs);
346 
347 private:
348  SiftMatchingOptions options_;
349  Database* database_;
350  FeatureMatcherCache* cache_;
351 
352  bool is_setup_;
353 
354  std::vector<std::unique_ptr<FeatureMatcherThread>> matchers_;
355  std::vector<std::unique_ptr<FeatureMatcherThread>> guided_matchers_;
356  std::vector<std::unique_ptr<Thread>> verifiers_;
357  std::unique_ptr<ThreadPool> thread_pool_;
358 
361  JobQueue<internal::FeatureMatcherData> guided_matcher_queue_;
363 };
364 
365 // Exhaustively match images by processing each block in the exhaustive match
366 // matrix in one batch:
367 //
368 // +----+----+-----------------> images[i]
369 // |#000|0000|
370 // |1#00|1000| <- Above the main diagonal, the block diagonal is not matched
371 // |11#0|1100| ^
372 // |111#|1110| |
373 // +----+----+ |
374 // |1000|#000|\ |
375 // |1100|1#00| \ One block |
376 // |1110|11#0| / of image pairs |
377 // |1111|111#|/ |
378 // +----+----+ |
379 // | ^ |
380 // | | |
381 // | Below the main diagonal, the block diagonal is matched <--------------+
382 // |
383 // v
384 // images[i]
385 //
386 // Pairs will only be matched if 1, to avoid duplicate pairs. Pairs with #
387 // are on the main diagonal and denote pairs of the same image.
389 public:
391  const SiftMatchingOptions& match_options,
392  const std::string& database_path);
393 
394 private:
395  void Run() override;
396 
397  const ExhaustiveMatchingOptions options_;
398  const SiftMatchingOptions match_options_;
399  std::shared_ptr<Database> database_;
400  std::shared_ptr<FeatureMatcherCache> cache_;
401  std::shared_ptr<SiftFeatureMatcher> matcher_;
402 };
403 
404 // Sequentially match images within neighborhood:
405 //
406 // +-------------------------------+-----------------------> images[i]
407 // ^ | ^
408 // | Current image[i] |
409 // | | |
410 // +----------+-----------+
411 // |
412 // Match image_i against
413 //
414 // image_[i - o, i + o] with o = [1 .. overlap]
415 // image_[i - 2^o, i + 2^o] (for quadratic overlap)
416 //
417 // Sequential order is determined based on the image names in ascending order.
418 //
419 // Invoke loop detection if `(i mod loop_detection_period) == 0`, retrieve
420 // most similar `loop_detection_num_images` images from vocabulary tree,
421 // and perform matching and verification.
423 public:
425  const SiftMatchingOptions& match_options,
426  const std::string& database_path);
427 
428 private:
429  void Run() override;
430 
431  std::vector<image_t> GetOrderedImageIds() const;
432  void RunSequentialMatching(const std::vector<image_t>& image_ids);
433  void RunLoopDetection(const std::vector<image_t>& image_ids);
434 
435  const SequentialMatchingOptions options_;
436  const SiftMatchingOptions match_options_;
437  Database database_;
438  const std::shared_ptr<FeatureMatcherCache> cache_;
439  SiftFeatureMatcher matcher_;
440 };
441 
442 // Match each image against its nearest neighbors using a vocabulary tree.
444 public:
446  const SiftMatchingOptions& match_options,
447  const std::string& database_path);
448 
449 private:
450  void Run() override;
451 
452  const VocabTreeMatchingOptions options_;
453  const SiftMatchingOptions match_options_;
454  Database database_;
455  FeatureMatcherCache cache_;
456  SiftFeatureMatcher matcher_;
457 };
458 
459 // Match images against spatial nearest neighbors using prior location
460 // information, e.g. provided manually or extracted from EXIF.
462 public:
464  const SiftMatchingOptions& match_options,
465  const std::string& database_path);
466 
467 private:
468  void Run() override;
469 
470  const SpatialMatchingOptions options_;
471  const SiftMatchingOptions match_options_;
472  Database database_;
473  FeatureMatcherCache cache_;
474  SiftFeatureMatcher matcher_;
475 };
476 
477 // Match transitive image pairs in a database with existing feature matches.
478 // This matcher transitively closes loops. For example, if image pairs A-B and
479 // B-C match but A-C has not been matched, then this matcher attempts to match
480 // A-C. This procedure is performed for multiple iterations.
482 public:
484  const SiftMatchingOptions& match_options,
485  const std::string& database_path);
486 
487 private:
488  void Run() override;
489 
490  const TransitiveMatchingOptions options_;
491  const SiftMatchingOptions match_options_;
492  Database database_;
493  FeatureMatcherCache cache_;
494  SiftFeatureMatcher matcher_;
495 };
496 
497 // Match images manually specified in a list of image pairs.
498 //
499 // Read matches file with the following format:
500 //
501 // image_name1 image_name2
502 // image_name1 image_name3
503 // image_name2 image_name3
504 // ...
505 //
507 public:
509  const SiftMatchingOptions& match_options,
510  const std::string& database_path);
511 
512 private:
513  void Run() override;
514 
515  const ImagePairsMatchingOptions options_;
516  const SiftMatchingOptions match_options_;
517  Database database_;
518  FeatureMatcherCache cache_;
519  SiftFeatureMatcher matcher_;
520 };
521 
522 // Import feature matches from a text file.
523 //
524 // Read matches file with the following format:
525 //
526 // image_name1 image_name2
527 // 0 1
528 // 1 2
529 // 2 3
530 // <empty line>
531 // image_name1 image_name3
532 // 0 1
533 // 1 2
534 // 2 3
535 // ...
536 //
538 public:
540  const SiftMatchingOptions& match_options,
541  const std::string& database_path);
542 
543 private:
544  const static size_t kCacheSize = 100;
545 
546  void Run() override;
547 
548  const FeaturePairsMatchingOptions options_;
549  const SiftMatchingOptions match_options_;
550  Database database_;
551  FeatureMatcherCache cache_;
552 };
553 
554 } // namespace colmap
ExhaustiveFeatureMatcher(const ExhaustiveMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:961
const Image & GetImage(const image_t image_id)
Definition: matching.cc:287
FeatureMatches GetMatches(const image_t image_id1, const image_t image_id2)
Definition: matching.cc:302
FeatureMatcherCache(const size_t cache_size, const Database *database)
Definition: matching.cc:216
void WriteMatches(const image_t image_id1, const image_t image_id2, const FeatureMatches &matches)
Definition: matching.cc:340
bool ExistsInlierMatches(const image_t image_id1, const image_t image_id2)
Definition: matching.cc:334
void DeleteInlierMatches(const image_t image_id1, const image_t image_id2)
Definition: matching.cc:360
void WriteTwoViewGeometry(const image_t image_id1, const image_t image_id2, const TwoViewGeometry &two_view_geometry)
Definition: matching.cc:347
std::vector< image_t > GetImageIds()
Definition: matching.cc:308
const Camera & GetCamera(const camera_t camera_id)
Definition: matching.cc:282
bool ExistsDescriptors(const image_t image_id)
Definition: matching.cc:324
void DeleteMatches(const image_t image_id1, const image_t image_id2)
Definition: matching.cc:354
std::shared_ptr< FeatureKeypoints > GetKeypoints(const image_t image_id)
Definition: matching.cc:292
bool ExistsKeypoints(const image_t image_id)
Definition: matching.cc:320
bool ExistsMatches(const image_t image_id1, const image_t image_id2)
Definition: matching.cc:328
std::shared_ptr< FeatureDescriptors > GetDescriptors(const image_t image_id)
Definition: matching.cc:297
void SetMaxNumMatches(const int max_num_matches)
Definition: matching.cc:370
FeatureMatcherThread(const SiftMatchingOptions &options, FeatureMatcherCache *cache)
Definition: matching.cc:366
SiftMatchingOptions options_
Definition: matching.h:214
FeatureMatcherCache * cache_
Definition: matching.h:215
FeaturePairsFeatureMatcher(const FeaturePairsMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:1649
internal::FeatureMatcherData Output
Definition: matching.h:265
GuidedSiftCPUFeatureMatcher(const SiftMatchingOptions &options, FeatureMatcherCache *cache, JobQueue< Input > *input_queue, JobQueue< Output > *output_queue)
Definition: matching.cc:502
internal::FeatureMatcherData Input
Definition: matching.h:264
internal::FeatureMatcherData Output
Definition: matching.h:282
GuidedSiftGPUFeatureMatcher(const SiftMatchingOptions &options, FeatureMatcherCache *cache, JobQueue< Input > *input_queue, JobQueue< Output > *output_queue)
Definition: matching.cc:551
internal::FeatureMatcherData Input
Definition: matching.h:281
ImagePairsFeatureMatcher(const ImagePairsMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:1534
SequentialFeatureMatcher(const SequentialMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:1038
SiftCPUFeatureMatcher(const SiftMatchingOptions &options, FeatureMatcherCache *cache, JobQueue< Input > *input_queue, JobQueue< Output > *output_queue)
Definition: matching.cc:374
JobQueue< Input > * input_queue_
Definition: matching.h:231
JobQueue< Output > * output_queue_
Definition: matching.h:232
internal::FeatureMatcherData Output
Definition: matching.h:221
internal::FeatureMatcherData Input
Definition: matching.h:220
SiftFeatureMatcher(const SiftMatchingOptions &options, Database *database, FeatureMatcherCache *cache)
Definition: matching.cc:724
void Match(const std::vector< std::pair< image_t, image_t >> &image_pairs)
Definition: matching.cc:869
void GetDescriptorData(const int index, const image_t image_id, const FeatureDescriptors **descriptors_ptr)
Definition: matching.cc:488
internal::FeatureMatcherData Output
Definition: matching.h:238
JobQueue< Input > * input_queue_
Definition: matching.h:252
JobQueue< Output > * output_queue_
Definition: matching.h:253
std::array< image_t, 2 > prev_uploaded_image_ids_
Definition: matching.h:258
internal::FeatureMatcherData Input
Definition: matching.h:237
std::array< FeatureDescriptors, 2 > prev_uploaded_descriptors_
Definition: matching.h:259
SiftGPUFeatureMatcher(const SiftMatchingOptions &options, FeatureMatcherCache *cache, JobQueue< Input > *input_queue, JobQueue< Output > *output_queue)
Definition: matching.cc:411
std::unique_ptr< OpenGLContextManager > opengl_context_
Definition: matching.h:255
SpatialFeatureMatcher(const SpatialMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:1251
TransitiveFeatureMatcher(const TransitiveMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:1436
JobQueue< Output > * output_queue_
Definition: matching.h:325
FeatureMatcherCache * cache_
Definition: matching.h:323
TwoViewGeometryVerifier(const SiftMatchingOptions &options, FeatureMatcherCache *cache, JobQueue< Input > *input_queue, JobQueue< Output > *output_queue)
Definition: matching.cc:656
JobQueue< Input > * input_queue_
Definition: matching.h:324
internal::FeatureMatcherData Input
Definition: matching.h:310
internal::FeatureMatcherData Output
Definition: matching.h:311
TwoViewGeometry::Options two_view_geometry_options_
Definition: matching.h:322
const SiftMatchingOptions options_
Definition: matching.h:321
VocabTreeFeatureMatcher(const VocabTreeMatchingOptions &options, const SiftMatchingOptions &match_options, const std::string &database_path)
Definition: matching.cc:1171
static const std::string kDefaultVocabTreeUri
Definition: resources.h:25
Eigen::Matrix< uint8_t, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > FeatureDescriptors
Definition: types.h:79
uint32_t image_t
Definition: types.h:61
std::vector< FeatureKeypoint > FeatureKeypoints
Definition: types.h:77
const image_t kInvalidImageId
Definition: types.h:76
uint32_t camera_t
Definition: types.h:58
std::vector< FeatureMatch > FeatureMatches
Definition: types.h:80