Download include/colmap/base/database.h from camenduru/ceres-solver: direct link, hf CLI and curl.
- Browser
- Download file 16 kB
-
https://huggingface.co/camenduru/ceres-solver/resolve/main/include/colmap/base/database.h
- Command line
-
hf download hf://camenduru/ceres-solver/include/colmap/base/database.h
-
curl -L -o database.h https://huggingface.co/camenduru/ceres-solver/resolve/main/include/colmap/base/database.h
16 kB
| // Copyright (c) 2022, ETH Zurich and UNC Chapel Hill. | |
| // All rights reserved. | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // * Redistributions of source code must retain the above copyright | |
| // notice, this list of conditions and the following disclaimer. | |
| // | |
| // * Redistributions in binary form must reproduce the above copyright | |
| // notice, this list of conditions and the following disclaimer in the | |
| // documentation and/or other materials provided with the distribution. | |
| // | |
| // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of | |
| // its contributors may be used to endorse or promote products derived | |
| // from this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE | |
| // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
| // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| // POSSIBILITY OF SUCH DAMAGE. | |
| // | |
| // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de) | |
| namespace colmap { | |
| // Database class to read and write images, features, cameras, matches, etc. | |
| // from a SQLite database. The class is not thread-safe and must not be accessed | |
| // concurrently. The class is optimized for single-thread speed and for optimal | |
| // performance, wrap multiple method calls inside a leading `BeginTransaction` | |
| // and trailing `EndTransaction`. | |
| class Database { | |
| public: | |
| const static int kSchemaVersion = 1; | |
| // The maximum number of images, that can be stored in the database. | |
| // This limitation arises due to the fact, that we generate unique IDs for | |
| // image pairs manually. Note: do not change this to | |
| // another type than `size_t`. | |
| const static size_t kMaxNumImages; | |
| Database(); | |
| explicit Database(const std::string& path); | |
| ~Database(); | |
| // Open and close database. The same database should not be opened | |
| // concurrently in multiple threads or processes. | |
| void Open(const std::string& path); | |
| void Close(); | |
| // Check if entry already exists in database. For image pairs, the order of | |
| // `image_id1` and `image_id2` does not matter. | |
| bool ExistsCamera(const camera_t camera_id) const; | |
| bool ExistsImage(const image_t image_id) const; | |
| bool ExistsImageWithName(std::string name) const; | |
| bool ExistsKeypoints(const image_t image_id) const; | |
| bool ExistsDescriptors(const image_t image_id) const; | |
| bool ExistsMatches(const image_t image_id1, const image_t image_id2) const; | |
| bool ExistsInlierMatches(const image_t image_id1, | |
| const image_t image_id2) const; | |
| // Number of rows in `cameras` table. | |
| size_t NumCameras() const; | |
| // Number of rows in `images` table. | |
| size_t NumImages() const; | |
| // Sum of `rows` column in `keypoints` table, i.e. number of total keypoints. | |
| size_t NumKeypoints() const; | |
| // The number of keypoints for the image with most features. | |
| size_t MaxNumKeypoints() const; | |
| // Number of descriptors for specific image. | |
| size_t NumKeypointsForImage(const image_t image_id) const; | |
| // Sum of `rows` column in `descriptors` table, | |
| // i.e. number of total descriptors. | |
| size_t NumDescriptors() const; | |
| // The number of descriptors for the image with most features. | |
| size_t MaxNumDescriptors() const; | |
| // Number of descriptors for specific image. | |
| size_t NumDescriptorsForImage(const image_t image_id) const; | |
| // Sum of `rows` column in `matches` table, i.e. number of total matches. | |
| size_t NumMatches() const; | |
| // Sum of `rows` column in `two_view_geometries` table, | |
| // i.e. number of total inlier matches. | |
| size_t NumInlierMatches() const; | |
| // Number of rows in `matches` table. | |
| size_t NumMatchedImagePairs() const; | |
| // Number of rows in `two_view_geometries` table. | |
| size_t NumVerifiedImagePairs() const; | |
| // Each image pair is assigned an unique ID in the `matches` and | |
| // `two_view_geometries` table. We intentionally avoid to store the pairs in a | |
| // separate table by using e.g. AUTOINCREMENT, since the overhead of querying | |
| // the unique pair ID is significant. | |
| inline static image_pair_t ImagePairToPairId(const image_t image_id1, | |
| const image_t image_id2); | |
| inline static void PairIdToImagePair(const image_pair_t pair_id, | |
| image_t* image_id1, image_t* image_id2); | |
| // Return true if image pairs should be swapped. Used to enforce a specific | |
| // image order to generate unique image pair identifiers independent of the | |
| // order in which the image identifiers are used. | |
| inline static bool SwapImagePair(const image_t image_id1, | |
| const image_t image_id2); | |
| // Read an existing entry in the database. The user is responsible for making | |
| // sure that the entry actually exists. For image pairs, the order of | |
| // `image_id1` and `image_id2` does not matter. | |
| Camera ReadCamera(const camera_t camera_id) const; | |
| std::vector<Camera> ReadAllCameras() const; | |
| Image ReadImage(const image_t image_id) const; | |
| Image ReadImageWithName(const std::string& name) const; | |
| std::vector<Image> ReadAllImages() const; | |
| FeatureKeypoints ReadKeypoints(const image_t image_id) const; | |
| FeatureDescriptors ReadDescriptors(const image_t image_id) const; | |
| FeatureMatches ReadMatches(const image_t image_id1, | |
| const image_t image_id2) const; | |
| std::vector<std::pair<image_pair_t, FeatureMatches>> ReadAllMatches() const; | |
| TwoViewGeometry ReadTwoViewGeometry(const image_t image_id1, | |
| const image_t image_id2) const; | |
| void ReadTwoViewGeometries( | |
| std::vector<image_pair_t>* image_pair_ids, | |
| std::vector<TwoViewGeometry>* two_view_geometries) const; | |
| // Read all image pairs that have an entry in the `NumVerifiedImagePairs` | |
| // table with at least one inlier match and their number of inlier matches. | |
| void ReadTwoViewGeometryNumInliers( | |
| std::vector<std::pair<image_t, image_t>>* image_pairs, | |
| std::vector<int>* num_inliers) const; | |
| // Add new camera and return its database identifier. If `use_camera_id` | |
| // is false a new identifier is automatically generated. | |
| camera_t WriteCamera(const Camera& camera, | |
| const bool use_camera_id = false) const; | |
| // Add new image and return its database identifier. If `use_image_id` | |
| // is false a new identifier is automatically generated. | |
| image_t WriteImage(const Image& image, const bool use_image_id = false) const; | |
| // Write a new entry in the database. The user is responsible for making sure | |
| // that the entry does not yet exist. For image pairs, the order of | |
| // `image_id1` and `image_id2` does not matter. | |
| void WriteKeypoints(const image_t image_id, | |
| const FeatureKeypoints& keypoints) const; | |
| void WriteDescriptors(const image_t image_id, | |
| const FeatureDescriptors& descriptors) const; | |
| void WriteMatches(const image_t image_id1, const image_t image_id2, | |
| const FeatureMatches& matches) const; | |
| void WriteTwoViewGeometry(const image_t image_id1, const image_t image_id2, | |
| const TwoViewGeometry& two_view_geometry) const; | |
| // Update an existing camera in the database. The user is responsible for | |
| // making sure that the entry already exists. | |
| void UpdateCamera(const Camera& camera) const; | |
| // Update an existing image in the database. The user is responsible for | |
| // making sure that the entry already exists. | |
| void UpdateImage(const Image& image) const; | |
| // Delete matches of an image pair. | |
| void DeleteMatches(const image_t image_id1, const image_t image_id2) const; | |
| // Delete inlier matches of an image pair. | |
| void DeleteInlierMatches(const image_t image_id1, | |
| const image_t image_id2) const; | |
| // Clear all database tables | |
| void ClearAllTables() const; | |
| // Clear the entire cameras table | |
| void ClearCameras() const; | |
| // Clear the entire images, keypoints, and descriptors tables | |
| void ClearImages() const; | |
| // Clear the entire descriptors table | |
| void ClearDescriptors() const; | |
| // Clear the entire keypoints table | |
| void ClearKeypoints() const; | |
| // Clear the entire matches table. | |
| void ClearMatches() const; | |
| // Clear the entire inlier matches table. | |
| void ClearTwoViewGeometries() const; | |
| // Merge two databases into a single, new database. | |
| static void Merge(const Database& database1, const Database& database2, | |
| Database* merged_database); | |
| private: | |
| friend class DatabaseTransaction; | |
| // Combine multiple queries into one transaction by wrapping a code section | |
| // into a `BeginTransaction` and `EndTransaction`. You can create a scoped | |
| // transaction with `DatabaseTransaction` that ends when the transaction | |
| // object is destructed. Combining queries results in faster transaction time | |
| // due to reduced locking of the database etc. | |
| void BeginTransaction() const; | |
| void EndTransaction() const; | |
| // Prepare SQL statements once at construction of the database, and reuse | |
| // the statements for multiple queries by resetting their states. | |
| void PrepareSQLStatements(); | |
| void FinalizeSQLStatements(); | |
| // Create database tables, if not existing, called when opening a database. | |
| void CreateTables() const; | |
| void CreateCameraTable() const; | |
| void CreateImageTable() const; | |
| void CreateKeypointsTable() const; | |
| void CreateDescriptorsTable() const; | |
| void CreateMatchesTable() const; | |
| void CreateTwoViewGeometriesTable() const; | |
| void UpdateSchema() const; | |
| bool ExistsTable(const std::string& table_name) const; | |
| bool ExistsColumn(const std::string& table_name, | |
| const std::string& column_name) const; | |
| bool ExistsRowId(sqlite3_stmt* sql_stmt, const sqlite3_int64 row_id) const; | |
| bool ExistsRowString(sqlite3_stmt* sql_stmt, | |
| const std::string& row_entry) const; | |
| size_t CountRows(const std::string& table) const; | |
| size_t CountRowsForEntry(sqlite3_stmt* sql_stmt, | |
| const sqlite3_int64 row_id) const; | |
| size_t SumColumn(const std::string& column, const std::string& table) const; | |
| size_t MaxColumn(const std::string& column, const std::string& table) const; | |
| sqlite3* database_ = nullptr; | |
| // Check if elements got removed from the database to only apply | |
| // the VACUUM command in such case | |
| mutable bool database_cleared_ = false; | |
| // Ensure that only one database object at a time updates the schema of a | |
| // database. Since the schema is updated every time a database is opened, this | |
| // is to ensure that there are no race conditions ("database locked" error | |
| // messages) when the user actually only intends to read from the database, | |
| // which requires to open it. | |
| static std::mutex update_schema_mutex_; | |
| // Used to ensure that only one transaction is active at the same time. | |
| std::mutex transaction_mutex_; | |
| // A collection of all `sqlite3_stmt` objects for deletion in the destructor. | |
| std::vector<sqlite3_stmt*> sql_stmts_; | |
| // num_* | |
| sqlite3_stmt* sql_stmt_num_keypoints_ = nullptr; | |
| sqlite3_stmt* sql_stmt_num_descriptors_ = nullptr; | |
| // exists_* | |
| sqlite3_stmt* sql_stmt_exists_camera_ = nullptr; | |
| sqlite3_stmt* sql_stmt_exists_image_id_ = nullptr; | |
| sqlite3_stmt* sql_stmt_exists_image_name_ = nullptr; | |
| sqlite3_stmt* sql_stmt_exists_keypoints_ = nullptr; | |
| sqlite3_stmt* sql_stmt_exists_descriptors_ = nullptr; | |
| sqlite3_stmt* sql_stmt_exists_matches_ = nullptr; | |
| sqlite3_stmt* sql_stmt_exists_two_view_geometry_ = nullptr; | |
| // add_* | |
| sqlite3_stmt* sql_stmt_add_camera_ = nullptr; | |
| sqlite3_stmt* sql_stmt_add_image_ = nullptr; | |
| // update_* | |
| sqlite3_stmt* sql_stmt_update_camera_ = nullptr; | |
| sqlite3_stmt* sql_stmt_update_image_ = nullptr; | |
| // read_* | |
| sqlite3_stmt* sql_stmt_read_camera_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_cameras_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_image_id_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_image_name_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_images_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_keypoints_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_descriptors_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_matches_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_matches_all_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_two_view_geometry_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_two_view_geometries_ = nullptr; | |
| sqlite3_stmt* sql_stmt_read_two_view_geometry_num_inliers_ = nullptr; | |
| // write_* | |
| sqlite3_stmt* sql_stmt_write_keypoints_ = nullptr; | |
| sqlite3_stmt* sql_stmt_write_descriptors_ = nullptr; | |
| sqlite3_stmt* sql_stmt_write_matches_ = nullptr; | |
| sqlite3_stmt* sql_stmt_write_two_view_geometry_ = nullptr; | |
| // delete_* | |
| sqlite3_stmt* sql_stmt_delete_matches_ = nullptr; | |
| sqlite3_stmt* sql_stmt_delete_two_view_geometry_ = nullptr; | |
| // clear_* | |
| sqlite3_stmt* sql_stmt_clear_cameras_ = nullptr; | |
| sqlite3_stmt* sql_stmt_clear_images_ = nullptr; | |
| sqlite3_stmt* sql_stmt_clear_descriptors_ = nullptr; | |
| sqlite3_stmt* sql_stmt_clear_keypoints_ = nullptr; | |
| sqlite3_stmt* sql_stmt_clear_matches_ = nullptr; | |
| sqlite3_stmt* sql_stmt_clear_two_view_geometries_ = nullptr; | |
| }; | |
| // This class automatically manages the scope of a database transaction by | |
| // calling `BeginTransaction` and `EndTransaction` during construction and | |
| // destruction, respectively. | |
| class DatabaseTransaction { | |
| public: | |
| explicit DatabaseTransaction(Database* database); | |
| ~DatabaseTransaction(); | |
| private: | |
| NON_COPYABLE(DatabaseTransaction) | |
| NON_MOVABLE(DatabaseTransaction) | |
| Database* database_; | |
| std::unique_lock<std::mutex> database_lock_; | |
| }; | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // Implementation | |
| //////////////////////////////////////////////////////////////////////////////// | |
| image_pair_t Database::ImagePairToPairId(const image_t image_id1, | |
| const image_t image_id2) { | |
| CHECK_GE(image_id1, 0); | |
| CHECK_GE(image_id2, 0); | |
| CHECK_LT(image_id1, kMaxNumImages); | |
| CHECK_LT(image_id2, kMaxNumImages); | |
| if (SwapImagePair(image_id1, image_id2)) { | |
| return static_cast<image_pair_t>(kMaxNumImages) * image_id2 + image_id1; | |
| } else { | |
| return static_cast<image_pair_t>(kMaxNumImages) * image_id1 + image_id2; | |
| } | |
| } | |
| void Database::PairIdToImagePair(const image_pair_t pair_id, image_t* image_id1, | |
| image_t* image_id2) { | |
| *image_id2 = static_cast<image_t>(pair_id % kMaxNumImages); | |
| *image_id1 = static_cast<image_t>((pair_id - *image_id2) / kMaxNumImages); | |
| CHECK_GE(*image_id1, 0); | |
| CHECK_GE(*image_id2, 0); | |
| CHECK_LT(*image_id1, kMaxNumImages); | |
| CHECK_LT(*image_id2, kMaxNumImages); | |
| } | |
| // Return true if image pairs should be swapped. Used to enforce a specific | |
| // image order to generate unique image pair identifiers independent of the | |
| // order in which the image identifiers are used. | |
| bool Database::SwapImagePair(const image_t image_id1, const image_t image_id2) { | |
| return image_id1 > image_id2; | |
| } | |
| } // namespace colmap | |