|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef COLMAP_SRC_BASE_DATABASE_H_ |
|
#define COLMAP_SRC_BASE_DATABASE_H_ |
|
|
|
#include <mutex> |
|
#include <unordered_map> |
|
#include <vector> |
|
|
|
#include <Eigen/Core> |
|
|
|
#include "SQLite/sqlite3.h" |
|
#include "base/camera.h" |
|
#include "base/image.h" |
|
#include "estimators/two_view_geometry.h" |
|
#include "feature/types.h" |
|
#include "util/types.h" |
|
|
|
namespace colmap { |
|
|
|
|
|
|
|
|
|
|
|
|
|
class Database { |
|
public: |
|
const static int kSchemaVersion = 1; |
|
|
|
|
|
|
|
|
|
|
|
const static size_t kMaxNumImages; |
|
|
|
Database(); |
|
explicit Database(const std::string& path); |
|
~Database(); |
|
|
|
|
|
|
|
void Open(const std::string& path); |
|
void Close(); |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
size_t NumCameras() const; |
|
|
|
|
|
size_t NumImages() const; |
|
|
|
|
|
size_t NumKeypoints() const; |
|
|
|
|
|
size_t MaxNumKeypoints() const; |
|
|
|
|
|
size_t NumKeypointsForImage(const image_t image_id) const; |
|
|
|
|
|
|
|
size_t NumDescriptors() const; |
|
|
|
|
|
size_t MaxNumDescriptors() const; |
|
|
|
|
|
size_t NumDescriptorsForImage(const image_t image_id) const; |
|
|
|
|
|
size_t NumMatches() const; |
|
|
|
|
|
|
|
size_t NumInlierMatches() const; |
|
|
|
|
|
size_t NumMatchedImagePairs() const; |
|
|
|
|
|
size_t NumVerifiedImagePairs() const; |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
inline static bool SwapImagePair(const image_t image_id1, |
|
const image_t image_id2); |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
void ReadTwoViewGeometryNumInliers( |
|
std::vector<std::pair<image_t, image_t>>* image_pairs, |
|
std::vector<int>* num_inliers) const; |
|
|
|
|
|
|
|
camera_t WriteCamera(const Camera& camera, |
|
const bool use_camera_id = false) const; |
|
|
|
|
|
|
|
image_t WriteImage(const Image& image, const bool use_image_id = false) const; |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
void UpdateCamera(const Camera& camera) const; |
|
|
|
|
|
|
|
void UpdateImage(const Image& image) const; |
|
|
|
|
|
void DeleteMatches(const image_t image_id1, const image_t image_id2) const; |
|
|
|
|
|
void DeleteInlierMatches(const image_t image_id1, |
|
const image_t image_id2) const; |
|
|
|
|
|
void ClearAllTables() const; |
|
|
|
|
|
void ClearCameras() const; |
|
|
|
|
|
void ClearImages() const; |
|
|
|
|
|
void ClearDescriptors() const; |
|
|
|
|
|
void ClearKeypoints() const; |
|
|
|
|
|
void ClearMatches() const; |
|
|
|
|
|
void ClearTwoViewGeometries() const; |
|
|
|
|
|
static void Merge(const Database& database1, const Database& database2, |
|
Database* merged_database); |
|
|
|
private: |
|
friend class DatabaseTransaction; |
|
|
|
|
|
|
|
|
|
|
|
|
|
void BeginTransaction() const; |
|
void EndTransaction() const; |
|
|
|
|
|
|
|
void PrepareSQLStatements(); |
|
void FinalizeSQLStatements(); |
|
|
|
|
|
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; |
|
|
|
|
|
|
|
mutable bool database_cleared_ = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
static std::mutex update_schema_mutex_; |
|
|
|
|
|
std::mutex transaction_mutex_; |
|
|
|
|
|
std::vector<sqlite3_stmt*> sql_stmts_; |
|
|
|
|
|
sqlite3_stmt* sql_stmt_num_keypoints_ = nullptr; |
|
sqlite3_stmt* sql_stmt_num_descriptors_ = nullptr; |
|
|
|
|
|
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; |
|
|
|
|
|
sqlite3_stmt* sql_stmt_add_camera_ = nullptr; |
|
sqlite3_stmt* sql_stmt_add_image_ = nullptr; |
|
|
|
|
|
sqlite3_stmt* sql_stmt_update_camera_ = nullptr; |
|
sqlite3_stmt* sql_stmt_update_image_ = nullptr; |
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
sqlite3_stmt* sql_stmt_delete_matches_ = nullptr; |
|
sqlite3_stmt* sql_stmt_delete_two_view_geometry_ = nullptr; |
|
|
|
|
|
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; |
|
}; |
|
|
|
|
|
|
|
|
|
class DatabaseTransaction { |
|
public: |
|
explicit DatabaseTransaction(Database* database); |
|
~DatabaseTransaction(); |
|
|
|
private: |
|
NON_COPYABLE(DatabaseTransaction) |
|
NON_MOVABLE(DatabaseTransaction) |
|
Database* database_; |
|
std::unique_lock<std::mutex> database_lock_; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
|
|
bool Database::SwapImagePair(const image_t image_id1, const image_t image_id2) { |
|
return image_id1 > image_id2; |
|
} |
|
|
|
} |
|
|
|
#endif |
|
|