ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
database.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 <Eigen/Core>
11 #include <mutex>
12 #include <unordered_map>
13 #include <vector>
14 
15 #include "SQLite/sqlite3.h"
16 #include "base/camera.h"
17 #include "base/image.h"
19 #include "feature/types.h"
20 #include "util/types.h"
21 
22 namespace colmap {
23 
24 // Database class to read and write images, features, cameras, matches, etc.
25 // from a SQLite database. The class is not thread-safe and must not be accessed
26 // concurrently. The class is optimized for single-thread speed and for optimal
27 // performance, wrap multiple method calls inside a leading `BeginTransaction`
28 // and trailing `EndTransaction`.
29 class Database {
30 public:
31  const static int kSchemaVersion = 1;
32 
33  // The maximum number of images, that can be stored in the database.
34  // This limitation arises due to the fact, that we generate unique IDs for
35  // image pairs manually. Note: do not change this to
36  // another type than `size_t`.
37  const static size_t kMaxNumImages;
38 
39  Database();
40  explicit Database(const std::string& path);
41  ~Database();
42 
43  // Open and close database. The same database should not be opened
44  // concurrently in multiple threads or processes.
45  void Open(const std::string& path);
46  void Close();
47 
48  // Check if entry already exists in database. For image pairs, the order of
49  // `image_id1` and `image_id2` does not matter.
50  bool ExistsCamera(const camera_t camera_id) const;
51  bool ExistsImage(const image_t image_id) const;
52  bool ExistsImageWithName(std::string name) const;
53  bool ExistsKeypoints(const image_t image_id) const;
54  bool ExistsDescriptors(const image_t image_id) const;
55  bool ExistsMatches(const image_t image_id1, const image_t image_id2) const;
56  bool ExistsInlierMatches(const image_t image_id1,
57  const image_t image_id2) const;
58 
59  // Number of rows in `cameras` table.
60  size_t NumCameras() const;
61 
62  // Number of rows in `images` table.
63  size_t NumImages() const;
64 
65  // Sum of `rows` column in `keypoints` table, i.e. number of total
66  // keypoints.
67  size_t NumKeypoints() const;
68 
69  // The number of keypoints for the image with most features.
70  size_t MaxNumKeypoints() const;
71 
72  // Number of descriptors for specific image.
73  size_t NumKeypointsForImage(const image_t image_id) const;
74 
75  // Sum of `rows` column in `descriptors` table,
76  // i.e. number of total descriptors.
77  size_t NumDescriptors() const;
78 
79  // The number of descriptors for the image with most features.
80  size_t MaxNumDescriptors() const;
81 
82  // Number of descriptors for specific image.
83  size_t NumDescriptorsForImage(const image_t image_id) const;
84 
85  // Sum of `rows` column in `matches` table, i.e. number of total matches.
86  size_t NumMatches() const;
87 
88  // Sum of `rows` column in `two_view_geometries` table,
89  // i.e. number of total inlier matches.
90  size_t NumInlierMatches() const;
91 
92  // Number of rows in `matches` table.
93  size_t NumMatchedImagePairs() const;
94 
95  // Number of rows in `two_view_geometries` table.
96  size_t NumVerifiedImagePairs() const;
97 
98  // Each image pair is assigned an unique ID in the `matches` and
99  // `two_view_geometries` table. We intentionally avoid to store the pairs in
100  // a separate table by using e.g. AUTOINCREMENT, since the overhead of
101  // querying the unique pair ID is significant.
102  inline static image_pair_t ImagePairToPairId(const image_t image_id1,
103  const image_t image_id2);
104 
105  inline static void PairIdToImagePair(const image_pair_t pair_id,
106  image_t* image_id1,
107  image_t* image_id2);
108 
109  // Return true if image pairs should be swapped. Used to enforce a specific
110  // image order to generate unique image pair identifiers independent of the
111  // order in which the image identifiers are used.
112  inline static bool SwapImagePair(const image_t image_id1,
113  const image_t image_id2);
114 
115  // Read an existing entry in the database. The user is responsible for
116  // making sure that the entry actually exists. For image pairs, the order of
117  // `image_id1` and `image_id2` does not matter.
118  Camera ReadCamera(const camera_t camera_id) const;
119  std::vector<Camera> ReadAllCameras() const;
120 
121  Image ReadImage(const image_t image_id) const;
122  Image ReadImageWithName(const std::string& name) const;
123  std::vector<Image> ReadAllImages() const;
124 
125  FeatureKeypoints ReadKeypoints(const image_t image_id) const;
126  FeatureDescriptors ReadDescriptors(const image_t image_id) const;
127 
128  FeatureMatches ReadMatches(const image_t image_id1,
129  const image_t image_id2) const;
130  std::vector<std::pair<image_pair_t, FeatureMatches>> ReadAllMatches() const;
131 
133  const image_t image_id2) const;
135  std::vector<image_pair_t>* image_pair_ids,
136  std::vector<TwoViewGeometry>* two_view_geometries) const;
137 
138  // Read all image pairs that have an entry in the `NumVerifiedImagePairs`
139  // table with at least one inlier match and their number of inlier matches.
141  std::vector<std::pair<image_t, image_t>>* image_pairs,
142  std::vector<int>* num_inliers) const;
143 
144  // Add new camera and return its database identifier. If `use_camera_id`
145  // is false a new identifier is automatically generated.
146  camera_t WriteCamera(const Camera& camera,
147  const bool use_camera_id = false) const;
148 
149  // Add new image and return its database identifier. If `use_image_id`
150  // is false a new identifier is automatically generated.
151  image_t WriteImage(const Image& image,
152  const bool use_image_id = false) const;
153 
154  // Write a new entry in the database. The user is responsible for making
155  // sure that the entry does not yet exist. For image pairs, the order of
156  // `image_id1` and `image_id2` does not matter.
157  void WriteKeypoints(const image_t image_id,
158  const FeatureKeypoints& keypoints) const;
159  void WriteDescriptors(const image_t image_id,
160  const FeatureDescriptors& descriptors) const;
161  void WriteMatches(const image_t image_id1,
162  const image_t image_id2,
163  const FeatureMatches& matches) const;
164  void WriteTwoViewGeometry(const image_t image_id1,
165  const image_t image_id2,
166  const TwoViewGeometry& two_view_geometry) const;
167 
168  // Update an existing camera in the database. The user is responsible for
169  // making sure that the entry already exists.
170  void UpdateCamera(const Camera& camera) const;
171 
172  // Update an existing image in the database. The user is responsible for
173  // making sure that the entry already exists.
174  void UpdateImage(const Image& image) const;
175 
176  // Delete matches of an image pair.
177  void DeleteMatches(const image_t image_id1, const image_t image_id2) const;
178 
179  // Delete inlier matches of an image pair.
180  void DeleteInlierMatches(const image_t image_id1,
181  const image_t image_id2) const;
182 
183  // Clear all database tables
184  void ClearAllTables() const;
185 
186  // Clear the entire cameras table
187  void ClearCameras() const;
188 
189  // Clear the entire images, keypoints, and descriptors tables
190  void ClearImages() const;
191 
192  // Clear the entire descriptors table
193  void ClearDescriptors() const;
194 
195  // Clear the entire keypoints table
196  void ClearKeypoints() const;
197 
198  // Clear the entire matches table.
199  void ClearMatches() const;
200 
201  // Clear the entire inlier matches table.
202  void ClearTwoViewGeometries() const;
203 
204  // Merge two databases into a single, new database.
205  static void Merge(const Database& database1,
206  const Database& database2,
207  Database* merged_database);
208 
209 private:
210  friend class DatabaseTransaction;
211 
212  // Combine multiple queries into one transaction by wrapping a code section
213  // into a `BeginTransaction` and `EndTransaction`. You can create a scoped
214  // transaction with `DatabaseTransaction` that ends when the transaction
215  // object is destructed. Combining queries results in faster transaction
216  // time due to reduced locking of the database etc.
217  void BeginTransaction() const;
218  void EndTransaction() const;
219 
220  // Prepare SQL statements once at construction of the database, and reuse
221  // the statements for multiple queries by resetting their states.
222  void PrepareSQLStatements();
223  void FinalizeSQLStatements();
224 
225  // Create database tables, if not existing, called when opening a database.
226  void CreateTables() const;
227  void CreateCameraTable() const;
228  void CreateImageTable() const;
229  void CreateKeypointsTable() const;
230  void CreateDescriptorsTable() const;
231  void CreateMatchesTable() const;
232  void CreateTwoViewGeometriesTable() const;
233 
234  void UpdateSchema() const;
235 
236  bool ExistsTable(const std::string& table_name) const;
237  bool ExistsColumn(const std::string& table_name,
238  const std::string& column_name) const;
239 
240  bool ExistsRowId(sqlite3_stmt* sql_stmt, const sqlite3_int64 row_id) const;
241  bool ExistsRowString(sqlite3_stmt* sql_stmt,
242  const std::string& row_entry) const;
243 
244  size_t CountRows(const std::string& table) const;
245  size_t CountRowsForEntry(sqlite3_stmt* sql_stmt,
246  const sqlite3_int64 row_id) const;
247  size_t SumColumn(const std::string& column, const std::string& table) const;
248  size_t MaxColumn(const std::string& column, const std::string& table) const;
249 
250  sqlite3* database_ = nullptr;
251 
252  // Ensure that only one database object at a time updates the schema of a
253  // database. Since the schema is updated every time a database is opened,
254  // this is to ensure that there are no race conditions ("database locked"
255  // error messages) when the user actually only intends to read from the
256  // database, which requires to open it.
257  static std::mutex update_schema_mutex_;
258 
259  // Used to ensure that only one transaction is active at the same time.
260  std::mutex transaction_mutex_;
261 
262  // A collection of all `sqlite3_stmt` objects for deletion in the
263  // destructor.
264  std::vector<sqlite3_stmt*> sql_stmts_;
265 
266  // num_*
267  sqlite3_stmt* sql_stmt_num_keypoints_ = nullptr;
268  sqlite3_stmt* sql_stmt_num_descriptors_ = nullptr;
269 
270  // exists_*
271  sqlite3_stmt* sql_stmt_exists_camera_ = nullptr;
272  sqlite3_stmt* sql_stmt_exists_image_id_ = nullptr;
273  sqlite3_stmt* sql_stmt_exists_image_name_ = nullptr;
274  sqlite3_stmt* sql_stmt_exists_keypoints_ = nullptr;
275  sqlite3_stmt* sql_stmt_exists_descriptors_ = nullptr;
276  sqlite3_stmt* sql_stmt_exists_matches_ = nullptr;
277  sqlite3_stmt* sql_stmt_exists_two_view_geometry_ = nullptr;
278 
279  // add_*
280  sqlite3_stmt* sql_stmt_add_camera_ = nullptr;
281  sqlite3_stmt* sql_stmt_add_image_ = nullptr;
282 
283  // update_*
284  sqlite3_stmt* sql_stmt_update_camera_ = nullptr;
285  sqlite3_stmt* sql_stmt_update_image_ = nullptr;
286 
287  // read_*
288  sqlite3_stmt* sql_stmt_read_camera_ = nullptr;
289  sqlite3_stmt* sql_stmt_read_cameras_ = nullptr;
290  sqlite3_stmt* sql_stmt_read_image_id_ = nullptr;
291  sqlite3_stmt* sql_stmt_read_image_name_ = nullptr;
292  sqlite3_stmt* sql_stmt_read_images_ = nullptr;
293  sqlite3_stmt* sql_stmt_read_keypoints_ = nullptr;
294  sqlite3_stmt* sql_stmt_read_descriptors_ = nullptr;
295  sqlite3_stmt* sql_stmt_read_matches_ = nullptr;
296  sqlite3_stmt* sql_stmt_read_matches_all_ = nullptr;
297  sqlite3_stmt* sql_stmt_read_two_view_geometry_ = nullptr;
298  sqlite3_stmt* sql_stmt_read_two_view_geometries_ = nullptr;
299  sqlite3_stmt* sql_stmt_read_two_view_geometry_num_inliers_ = nullptr;
300 
301  // write_*
302  sqlite3_stmt* sql_stmt_write_keypoints_ = nullptr;
303  sqlite3_stmt* sql_stmt_write_descriptors_ = nullptr;
304  sqlite3_stmt* sql_stmt_write_matches_ = nullptr;
305  sqlite3_stmt* sql_stmt_write_two_view_geometry_ = nullptr;
306 
307  // delete_*
308  sqlite3_stmt* sql_stmt_delete_matches_ = nullptr;
309  sqlite3_stmt* sql_stmt_delete_two_view_geometry_ = nullptr;
310 
311  // clear_*
312  sqlite3_stmt* sql_stmt_clear_cameras_ = nullptr;
313  sqlite3_stmt* sql_stmt_clear_images_ = nullptr;
314  sqlite3_stmt* sql_stmt_clear_descriptors_ = nullptr;
315  sqlite3_stmt* sql_stmt_clear_keypoints_ = nullptr;
316  sqlite3_stmt* sql_stmt_clear_matches_ = nullptr;
317  sqlite3_stmt* sql_stmt_clear_two_view_geometries_ = nullptr;
318 };
319 
320 // This class automatically manages the scope of a database transaction by
321 // calling `BeginTransaction` and `EndTransaction` during construction and
322 // destruction, respectively.
324 public:
325  explicit DatabaseTransaction(Database* database);
327 
328 private:
331  Database* database_;
332  std::unique_lock<std::mutex> database_lock_;
333 };
334 
336 // Implementation
338 
340  const image_t image_id2) {
341  CHECK_GE(image_id1, 0);
342  CHECK_GE(image_id2, 0);
343  CHECK_LT(image_id1, kMaxNumImages);
344  CHECK_LT(image_id2, kMaxNumImages);
345  if (SwapImagePair(image_id1, image_id2)) {
346  return static_cast<image_pair_t>(kMaxNumImages) * image_id2 + image_id1;
347  } else {
348  return static_cast<image_pair_t>(kMaxNumImages) * image_id1 + image_id2;
349  }
350 }
351 
353  image_t* image_id1,
354  image_t* image_id2) {
355  *image_id2 = static_cast<image_t>(pair_id % kMaxNumImages);
356  *image_id1 = static_cast<image_t>((pair_id - *image_id2) / kMaxNumImages);
357  CHECK_GE(*image_id1, 0);
358  CHECK_GE(*image_id2, 0);
359  CHECK_LT(*image_id1, kMaxNumImages);
360  CHECK_LT(*image_id2, kMaxNumImages);
361 }
362 
363 // Return true if image pairs should be swapped. Used to enforce a specific
364 // image order to generate unique image pair identifiers independent of the
365 // order in which the image identifiers are used.
366 bool Database::SwapImagePair(const image_t image_id1, const image_t image_id2) {
367  return image_id1 > image_id2;
368 }
369 
370 } // namespace colmap
std::shared_ptr< core::Tensor > image
std::string name
DatabaseTransaction(Database *database)
Definition: database.cc:1490
void ClearCameras() const
Definition: database.cc:836
void WriteDescriptors(const image_t image_id, const FeatureDescriptors &descriptors) const
Definition: database.cc:676
size_t NumMatches() const
Definition: database.cc:353
static const size_t kMaxNumImages
Definition: database.h:37
FeatureDescriptors ReadDescriptors(const image_t image_id) const
Definition: database.cc:448
void ClearDescriptors() const
Definition: database.cc:846
static void Merge(const Database &database1, const Database &database2, Database *merged_database)
Definition: database.cc:866
size_t NumMatchedImagePairs() const
Definition: database.cc:359
void ReadTwoViewGeometryNumInliers(std::vector< std::pair< image_t, image_t >> *image_pairs, std::vector< int > *num_inliers) const
Definition: database.cc:579
void ClearImages() const
Definition: database.cc:841
size_t MaxNumDescriptors() const
Definition: database.cc:345
void ClearAllTables() const
Definition: database.cc:827
FeatureMatches ReadMatches(const image_t image_id1, const image_t image_id2) const
Definition: database.cc:461
bool ExistsImage(const image_t image_id) const
Definition: database.cc:299
void DeleteInlierMatches(const image_t image_id1, const image_t image_id2) const
Definition: database.cc:818
size_t NumImages() const
Definition: database.cc:329
void WriteMatches(const image_t image_id1, const image_t image_id2, const FeatureMatches &matches) const
Definition: database.cc:685
bool ExistsMatches(const image_t image_id1, const image_t image_id2) const
Definition: database.cc:315
FeatureKeypoints ReadKeypoints(const image_t image_id) const
Definition: database.cc:436
size_t NumInlierMatches() const
Definition: database.cc:355
void ClearKeypoints() const
Definition: database.cc:851
size_t NumDescriptors() const
Definition: database.cc:341
size_t NumKeypoints() const
Definition: database.cc:331
void WriteTwoViewGeometry(const image_t image_id1, const image_t image_id2, const TwoViewGeometry &two_view_geometry) const
Definition: database.cc:703
size_t NumVerifiedImagePairs() const
Definition: database.cc:361
void WriteKeypoints(const image_t image_id, const FeatureKeypoints &keypoints) const
Definition: database.cc:665
std::vector< std::pair< image_pair_t, FeatureMatches > > ReadAllMatches() const
Definition: database.cc:479
static image_pair_t ImagePairToPairId(const image_t image_id1, const image_t image_id2)
Definition: database.h:339
bool ExistsKeypoints(const image_t image_id) const
Definition: database.cc:307
size_t NumKeypointsForImage(const image_t image_id) const
Definition: database.cc:337
bool ExistsInlierMatches(const image_t image_id1, const image_t image_id2) const
Definition: database.cc:321
std::vector< Camera > ReadAllCameras() const
Definition: database.cc:380
bool ExistsCamera(const camera_t camera_id) const
Definition: database.cc:295
void DeleteMatches(const image_t image_id1, const image_t image_id2) const
Definition: database.cc:809
size_t NumDescriptorsForImage(const image_t image_id) const
Definition: database.cc:349
void ReadTwoViewGeometries(std::vector< image_pair_t > *image_pair_ids, std::vector< TwoViewGeometry > *two_view_geometries) const
Definition: database.cc:539
void Open(const std::string &path)
Definition: database.cc:254
void ClearTwoViewGeometries() const
Definition: database.cc:861
static bool SwapImagePair(const image_t image_id1, const image_t image_id2)
Definition: database.h:366
void ClearMatches() const
Definition: database.cc:856
bool ExistsDescriptors(const image_t image_id) const
Definition: database.cc:311
bool ExistsImageWithName(std::string name) const
Definition: database.cc:303
void UpdateCamera(const Camera &camera) const
Definition: database.cc:760
Image ReadImageWithName(const std::string &name) const
Definition: database.cc:407
size_t MaxNumKeypoints() const
Definition: database.cc:333
static const int kSchemaVersion
Definition: database.h:31
TwoViewGeometry ReadTwoViewGeometry(const image_t image_id1, const image_t image_id2) const
Definition: database.cc:498
static void PairIdToImagePair(const image_pair_t pair_id, image_t *image_id1, image_t *image_id2)
Definition: database.h:352
Camera ReadCamera(const camera_t camera_id) const
Definition: database.cc:365
void UpdateImage(const Image &image) const
Definition: database.cc:783
image_t WriteImage(const Image &image, const bool use_image_id=false) const
Definition: database.cc:633
size_t NumCameras() const
Definition: database.cc:327
std::vector< Image > ReadAllImages() const
Definition: database.cc:423
camera_t WriteCamera(const Camera &camera, const bool use_camera_id=false) const
Definition: database.cc:603
Image ReadImage(const image_t image_id) const
Definition: database.cc:392
static const std::string path
Definition: PointCloud.cpp:59
uint64_t image_pair_t
Definition: types.h:64
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
uint32_t camera_t
Definition: types.h:58
std::vector< FeatureMatch > FeatureMatches
Definition: types.h:80
CorePointDescSet * descriptors
#define NON_COPYABLE(class_name)
Definition: types.h:30
#define NON_MOVABLE(class_name)
Definition: types.h:33