Skip to content
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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ovysotska
Copy link
Owner

This PR adds new message type to localization_protos. This type is called "MatchingCosts" and is used to store individual matching costs for a pair of images with [query_id, ref_id]. The difference to "CostMatrix" is that "MatchingCosts" are not required to store all values of the cost matrix of size row x col but can store just individual values. This is necessary to be able to visualize the "online" operation of the sequence matching algorithm.

Additionally, this PR adds functionality to read and write "MatchingCosts" from C++, Python and viewer interfaces.

@ovysotska
Copy link
Owner Author

@niosus, could you have a look at C++ part? Thank you :)

Copy link

@niosus niosus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the logic is easy to follow and the code is well written and styled. So I am approving the PR.

That being said, there was a couple of places where the code can be slightly improved to follow best practices and reduce the potential for future errors creeping up. Please see the comments in the code for those.

namespace loc = localization;

std::vector<std::unique_ptr<loc::features::iFeature>>
loadFeatures(const std::string &path2folder) {
Copy link

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 the loadFeatures function in one:

namespace {
std::vector<std::unique_ptr<loc::features::iFeature>>
loadFeatures(const std::string &path2folder) {...}
}  // namespace

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;
Copy link

Choose a reason for hiding this comment

The 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());

LOG(INFO) << "===== Online place recognition with LSH ====\n";

if (argc < 2) {
printf("[ERROR] Not enough input parameters.\n");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why not use LOG(FATAL) << "message" instead? It also terminates the program with an error code.

if (argc < 2) {
printf("[ERROR] Not enough input parameters.\n");
printf("Proper usage: ./cost_matrix_based_matching_lsh config_file.yaml\n");
exit(0);
Copy link

Choose a reason for hiding this comment

The 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 0 as it will be interpreted as "program terminated correctly".


std::string config_file = argv[1];
ConfigParser parser;
parser.parseYaml(config_file);
Copy link

Choose a reason for hiding this comment

The 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 config_file into the constructor of the ConfigParser directly?

Comment on lines +62 to +64
/*tableNum=*/1,
/*keySize=*/12,
/*multiProbeLevel=*/2);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it is a good practice to put such magic numbers as constexpr int kTableNum etc into the unnamed namespace at the top of the file. This way they are easy to find upon glancing into the file.

/*multiProbeLevel=*/2);
relocalizer->train(loadFeatures(parser.path2ref));

auto successorManager =
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be const?

/*type=*/loc::features::FeatureType::Cnn_Feature,
/*bufferSize=*/parser.bufferSize);

auto relocalizer = std::make_unique<loc::relocalizers::LshCvHashing>(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be const?

std::string path2refImg = "";
std::string imgExt = "";
std::string costMatrix = "";
std::string costsOutputName = "costs.MatchingCosts.pb";
Copy link

Choose a reason for hiding this comment

The 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.

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
Copy link

Choose a reason for hiding this comment

The 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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants