Skip to content

Commit 4384b41

Browse files
Feature/add image database (#241)
* Initial implementation * add database file and main test file * Update json object
1 parent 0cb0de1 commit 4384b41

5 files changed

Lines changed: 175 additions & 0 deletions

File tree

beam_cv/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ BEAM_ADD_MODULE(${PROJECT_NAME}
66
beam::containers
77
beam::utils
88
beam::optimization
9+
DBoW3
910
SOURCES
1011
src/Utils.cpp
1112
src/Raycast.cpp
1213
src/OpenCVConversions.cpp
14+
src/ImageDatabase.cpp
1315
src/geometry/Triangulation.cpp
1416
src/geometry/RelativePoseEstimator.cpp
1517
src/geometry/AbsolutePoseEstimator.cpp

beam_cv/data/orbvoc.dbow3

47.1 MB
Binary file not shown.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#pragma once
2+
3+
#include <DBoW3/DBoW3.h>
4+
#include <nlohmann/json.hpp>
5+
#include <opencv2/opencv.hpp>
6+
7+
#include <beam_cv/descriptors/ORBDescriptor.h>
8+
#include <beam_cv/detectors/GFTTDetector.h>
9+
#include <beam_utils/filesystem.h>
10+
#include <beam_utils/optional.h>
11+
12+
using json = nlohmann::json;
13+
14+
const std::string DEFAULT_VOCAB_PATH =
15+
beam::LibbeamRoot() + "/beam_cv/data/orbvoc.dbow3";
16+
17+
namespace beam_cv {
18+
19+
/**
20+
* @brief class for image database
21+
*/
22+
class ImageDatabase {
23+
public:
24+
/**
25+
* @brief Constructor to initialize with empty database and default params
26+
*/
27+
ImageDatabase();
28+
29+
/**
30+
* @brief Constructor to initialize with empty database
31+
*/
32+
ImageDatabase(const beam_cv::GFTTDetector::Params& detector_params,
33+
const beam_cv::ORBDescriptor::Params& descriptor_params);
34+
35+
/**
36+
* @brief Constructor to initialize with already created dbow db
37+
* @param database_path path to database folder
38+
*/
39+
ImageDatabase(const beam_cv::GFTTDetector::Params& detector_params,
40+
const beam_cv::ORBDescriptor::Params& descriptor_params,
41+
const std::string& dbow_file_path,
42+
const std::string& timestamps_file_path);
43+
44+
/**
45+
* @brief Default destructor
46+
*/
47+
~ImageDatabase() = default;
48+
49+
/**
50+
* @brief Save current database to default folder
51+
*/
52+
void SaveDatabase(const std::string& dbow_file_path,
53+
const std::string& timestamps_file_path);
54+
55+
/**
56+
* @brief Gets the word for a given descriptor
57+
*/
58+
cv::Mat GetWord(const cv::Mat& descriptor);
59+
60+
/**
61+
* @brief Return list of N image id's best matching query image
62+
* @param query_image to query database with
63+
*/
64+
std::vector<unsigned int> QueryDatabase(const cv::Mat& query_image,
65+
int N = 2);
66+
67+
/**
68+
* @brief Add an image to the database
69+
*/
70+
unsigned int AddImage(const cv::Mat& image, const ros::Time& timestamp);
71+
72+
/**
73+
* @brief Gets the timestamp associated to image with index in the database
74+
*/
75+
beam::opt<ros::Time> GetImageTimestamp(unsigned int index);
76+
77+
private:
78+
json index_to_timestamp_map_;
79+
std::shared_ptr<DBoW3::Database> dbow_db_;
80+
beam_cv::ORBDescriptor descriptor_;
81+
beam_cv::GFTTDetector detector_;
82+
};
83+
84+
} // namespace beam_cv

beam_cv/src/ImageDatabase.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#include <beam_cv/ImageDatabase.h>
2+
3+
namespace beam_cv {
4+
5+
ImageDatabase::ImageDatabase() {
6+
// construct default detector and descriptor
7+
beam_cv::GFTTDetector::Params detector_params;
8+
beam_cv::ORBDescriptor::Params descriptor_params;
9+
detector_ = beam_cv::GFTTDetector(detector_params);
10+
descriptor_ = beam_cv::ORBDescriptor(descriptor_params);
11+
// construct database
12+
DBoW3::Vocabulary default_vocab(DEFAULT_VOCAB_PATH);
13+
dbow_db_ = std::make_shared<DBoW3::Database>(default_vocab);
14+
index_to_timestamp_map_ = json::object();
15+
}
16+
17+
ImageDatabase::ImageDatabase(
18+
const beam_cv::GFTTDetector::Params& detector_params,
19+
const beam_cv::ORBDescriptor::Params& descriptor_params) {
20+
// construct detector and descriptor
21+
detector_ = beam_cv::GFTTDetector(detector_params);
22+
descriptor_ = beam_cv::ORBDescriptor(descriptor_params);
23+
// construct database
24+
DBoW3::Vocabulary default_vocab(DEFAULT_VOCAB_PATH);
25+
dbow_db_ = std::make_shared<DBoW3::Database>(default_vocab);
26+
index_to_timestamp_map_ = json::object();
27+
}
28+
29+
ImageDatabase::ImageDatabase(
30+
const beam_cv::GFTTDetector::Params& detector_params,
31+
const beam_cv::ORBDescriptor::Params& descriptor_params,
32+
const std::string& dbow_file_path,
33+
const std::string& timestamps_file_path) {
34+
// construct detector and descriptor
35+
detector_ = beam_cv::GFTTDetector(detector_params);
36+
descriptor_ = beam_cv::ORBDescriptor(descriptor_params);
37+
// construct database
38+
dbow_db_ = std::make_shared<DBoW3::Database>(dbow_file_path);
39+
std::ifstream timestamps_file(timestamps_file_path);
40+
index_to_timestamp_map_ = json::object();
41+
timestamps_file >> index_to_timestamp_map_;
42+
}
43+
44+
void ImageDatabase::SaveDatabase(const std::string& dbow_file_path,
45+
const std::string& timestamps_file_path) {
46+
dbow_db_->save(dbow_file_path);
47+
std::ofstream timestamps_file(timestamps_file_path);
48+
timestamps_file << std::setw(4) << index_to_timestamp_map_ << std::endl;
49+
}
50+
51+
cv::Mat ImageDatabase::GetWord(const cv::Mat& descriptor) {
52+
auto vocab = dbow_db_->getVocabulary();
53+
auto word_id = vocab->transform(descriptor);
54+
return vocab->getWord(word_id);
55+
}
56+
57+
std::vector<unsigned int>
58+
ImageDatabase::QueryDatabase(const cv::Mat& query_image, int N) {
59+
std::vector<cv::KeyPoint> kps = detector_.DetectFeatures(query_image);
60+
cv::Mat features = descriptor_.ExtractDescriptors(query_image, kps);
61+
DBoW3::QueryResults results;
62+
dbow_db_->query(features, results, N);
63+
64+
std::vector<unsigned int> indices;
65+
for (size_t i = 0; i < results.size(); i++) {
66+
DBoW3::Result res = results[i];
67+
indices.push_back(res.Id);
68+
}
69+
return indices;
70+
}
71+
72+
unsigned int ImageDatabase::AddImage(const cv::Mat& image,
73+
const ros::Time& timestamp) {
74+
std::vector<cv::KeyPoint> kps = detector_.DetectFeatures(image);
75+
cv::Mat features = descriptor_.ExtractDescriptors(image, kps);
76+
unsigned int idx = dbow_db_->add(features);
77+
index_to_timestamp_map_[std::to_string(idx)] = timestamp.toSec();
78+
return idx;
79+
}
80+
81+
beam::opt<ros::Time> ImageDatabase::GetImageTimestamp(unsigned int index) {
82+
std::string index_str = std::to_string(index);
83+
if (!index_to_timestamp_map_.contains(index_str)) { return {}; }
84+
double time = index_to_timestamp_map_[std::to_string(index)];
85+
return ros::Time(time);
86+
}
87+
88+
} // namespace beam_cv

cmake/GetBeamDependencies.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ FIND_PACKAGE(Boost 1.58.0 REQUIRED system filesystem)
55
FIND_PACKAGE(PCL 1.11.1 REQUIRED COMPONENTS
66
common filters registration kdtree search io visualization
77
surface segmentation features)
8+
FIND_PACKAGE(DBoW3 REQUIRED)
89
FIND_PACKAGE(Catch2 REQUIRED)
910
FIND_PACKAGE(nlohmann_json 3.2.0 REQUIRED)
1011
FIND_PACKAGE(roscpp REQUIRED)

0 commit comments

Comments
 (0)