-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Localizer/works without cost matrix #32
base: main
Are you sure you want to change the base?
Changes from all commits
06bb22b
c8fe6f3
32d5303
167375c
476cc20
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
add_subdirectory(cost_matrix_based_matching) | ||
add_subdirectory(cost_matrix_based_matching) | ||
add_subdirectory(feature_based_matching) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
find_package(OpenCV REQUIRED) | ||
|
||
add_executable(feature_based_localizer feature_based_localizer.cpp) | ||
target_link_libraries(feature_based_localizer | ||
cxx_flags | ||
glog::glog | ||
path_element | ||
online_database | ||
online_localizer | ||
successor_manager | ||
config_parser | ||
lsh_cv_hashing | ||
cnn_feature | ||
${OpenCV_LIBS} | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Created by O.Vysotska in 2023 | ||
|
||
#include "online_localizer/online_localizer.h" | ||
#include "database/idatabase.h" | ||
#include "database/list_dir.h" | ||
#include "database/online_database.h" | ||
#include "features/cnn_feature.h" | ||
#include "features/ifeature.h" | ||
#include "online_localizer/path_element.h" | ||
#include "relocalizers/lsh_cv_hashing.h" | ||
#include "tools/config_parser/config_parser.h" | ||
|
||
#include <glog/logging.h> | ||
|
||
#include <iostream> | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace loc = localization; | ||
|
||
std::vector<std::unique_ptr<loc::features::iFeature>> | ||
loadFeatures(const std::string &path2folder) { | ||
LOG(INFO) << "Loading the features to hash with LSH."; | ||
std::vector<std::string> featureNames = | ||
loc::database::listProtoDir(path2folder, ".Feature"); | ||
std::vector<std::unique_ptr<loc::features::iFeature>> features; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: you might want to reserve the memory for the features if you have a lot of those: features.reserve(featureNames.size()); |
||
|
||
for (size_t i = 0; i < featureNames.size(); ++i) { | ||
features.emplace_back( | ||
std::make_unique<loc::features::CnnFeature>(featureNames[i])); | ||
fprintf(stderr, "."); | ||
} | ||
fprintf(stderr, "\n"); | ||
LOG(INFO) << "Features were loaded and binarized"; | ||
return features; | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
google::InitGoogleLogging(argv[0]); | ||
FLAGS_logtostderr = 1; | ||
LOG(INFO) << "===== Online place recognition with LSH ====\n"; | ||
|
||
if (argc < 2) { | ||
printf("[ERROR] Not enough input parameters.\n"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: why not use |
||
printf("Proper usage: ./cost_matrix_based_matching_lsh config_file.yaml\n"); | ||
exit(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Follow up on above, if a program terminates with an error it probably should not return code |
||
} | ||
|
||
std::string config_file = argv[1]; | ||
ConfigParser parser; | ||
parser.parseYaml(config_file); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: a small design suggestions that might make sense here. Why now pass the |
||
parser.print(); | ||
|
||
const auto database = std::make_unique<loc::database::OnlineDatabase>( | ||
/*queryFeaturesDir=*/parser.path2qu, | ||
/*refFeaturesDir=*/parser.path2ref, | ||
/*type=*/loc::features::FeatureType::Cnn_Feature, | ||
/*bufferSize=*/parser.bufferSize); | ||
Comment on lines
+55
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: these comments indicate that the names in the |
||
|
||
auto relocalizer = std::make_unique<loc::relocalizers::LshCvHashing>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can it be const? |
||
/*onlineDatabase=*/database.get(), | ||
/*tableNum=*/1, | ||
/*keySize=*/12, | ||
/*multiProbeLevel=*/2); | ||
Comment on lines
+62
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: it is a good practice to put such magic numbers as |
||
relocalizer->train(loadFeatures(parser.path2ref)); | ||
|
||
auto successorManager = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can it be const? |
||
std::make_unique<loc::successor_manager::SuccessorManager>( | ||
database.get(), relocalizer.get(), parser.fanOut); | ||
loc::online_localizer::OnlineLocalizer localizer{ | ||
successorManager.get(), parser.expansionRate, parser.nonMatchCost}; | ||
const loc::online_localizer::Matches imageMatches = | ||
localizer.findMatchesTill(parser.querySize); | ||
loc::online_localizer::storeMatchesAsProto(imageMatches, | ||
parser.matchingResult); | ||
loc::database::storeCostsAsProto(database->getEstimatedCosts(), | ||
parser.costsOutputName); | ||
|
||
LOG(INFO) << "Done."; | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,28 +30,28 @@ | |
* @brief Class for storing the configuration parameters. | ||
*/ | ||
class ConfigParser { | ||
public: | ||
ConfigParser() {} | ||
bool parse(const std::string &iniFile); | ||
bool parseYaml(const std::string &yamlFile); | ||
void print() const; | ||
public: | ||
ConfigParser() {} | ||
bool parse(const std::string &iniFile); | ||
bool parseYaml(const std::string &yamlFile); | ||
void print() const; | ||
|
||
std::string path2qu = ""; | ||
std::string path2ref = ""; | ||
std::string path2quImg = ""; | ||
std::string path2refImg = ""; | ||
std::string imgExt = ""; | ||
std::string costMatrix = ""; | ||
std::string costOutputName = ""; | ||
std::string simPlaces = ""; | ||
std::string hashTable = ""; | ||
std::string matchingResult = "matches.MatchingResult.pb"; | ||
std::string path2qu = ""; | ||
std::string path2ref = ""; | ||
std::string path2quImg = ""; | ||
std::string path2refImg = ""; | ||
std::string imgExt = ""; | ||
std::string costMatrix = ""; | ||
std::string costsOutputName = "costs.MatchingCosts.pb"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally speaking, using default values on which your logic depends is frowned upon. The reason is that if your logic changes, these default values are easy to forget. I would suggest to set the default value to empty and just pass the appropriate values into a constructor that takes just the values you need. This way, when reading the code it should be easy to see which objects are created with which values. |
||
std::string simPlaces = ""; | ||
std::string hashTable = ""; | ||
std::string matchingResult = "matches.MatchingResult.pb"; | ||
|
||
int querySize = -1; | ||
int fanOut = -1; | ||
int bufferSize = -1; | ||
double nonMatchCost = -1.0; | ||
double expansionRate = -1.0; | ||
int querySize = -1; | ||
int fanOut = -1; | ||
int bufferSize = -1; | ||
double nonMatchCost = -1.0; | ||
double expansionRate = -1.0; | ||
}; | ||
|
||
/*! \var std::string ConfigParser::path2qu | ||
|
@@ -73,7 +73,7 @@ class ConfigParser { | |
/*! \var std::string ConfigParser::costMatrix | ||
\brief stores path to precomputed cost/similarity matrix. | ||
*/ | ||
/*! \var std::string ConfigParser::costOutputName | ||
/*! \var std::string ConfigParser::costsOutputName | ||
\brief stores the name of the produced result for the cost_matrix_based | ||
matching. | ||
*/ | ||
|
@@ -111,4 +111,4 @@ class ConfigParser { | |
typically be selected from 0.5 - 0.7. | ||
*/ | ||
|
||
#endif // SRC_TOOLS_CONFIG_PARSER_CONFIG_PARSER_H_ | ||
#endif // SRC_TOOLS_CONFIG_PARSER_CONFIG_PARSER_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,25 @@ syntax = "proto2"; | |
|
||
package image_sequence_localizer; | ||
|
||
// Assumes that all values of the matrix is known. | ||
// values.size() == rows*cols. No checks for this though. | ||
message CostMatrix { | ||
optional int32 rows = 20; | ||
optional int32 cols = 21; | ||
repeated double values = 1; | ||
} | ||
|
||
// Is used to store matching costs with associated query and reference id. | ||
// Does not require all elements of the cost matrix to be present | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These comments usually go out of date quite quickly and then become confusing to read. Maybe jut add the check whenever you read the message and remove this comment? |
||
message MatchingCosts{ | ||
message Element { | ||
optional int32 query_id = 1; | ||
optional int32 ref_id = 2; | ||
optional double value = 3; | ||
} | ||
repeated Element elements = 1; | ||
} | ||
|
||
message MatchingResult { | ||
message Match { | ||
optional int32 query_id = 1; | ||
|
@@ -25,12 +38,3 @@ message Feature { | |
optional int32 size = 2; | ||
optional string type = 3; | ||
} | ||
|
||
message Patch { | ||
message Element { | ||
optional int32 row = 1; | ||
optional int32 col = 2; | ||
optional int32 similarity_value = 3; | ||
} | ||
repeated Element elements = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a good practice to put functions in a
cpp
file into an unnamed namespace to enforce internal linkage of these functions, i.e., to guarantee that they are only visible from this file. So I would put theloadFeatures
function in one: