11 #include <utils/logger.hpp>
19 #if ENABLE_MULTITHREADING && ENABLE_OPENMP
22 #if ENABLE_MULTITHREADING && ENABLE_MPI
26 _INITIALIZE_EASYLOGGINGPP
29 #if ENABLE_MULTITHREADING && ENABLE_OPENMP
30 #pragma omp parallel for schedule(dynamic)
32 for (int64_t i = 0; i < dataset.
num_images(); i++) {
35 if (image ==
nullptr)
continue;
37 const std::string &keypoints_location = dataset.
location(image->feature_path(
"keypoints"));
38 const std::string &descriptors_location = dataset.
location(image->feature_path(
"descriptors"));
41 const std::string &image_location = dataset.
location(image->location());
45 cv::Mat im = cv::imread(image_location, cv::IMREAD_GRAYSCALE);
47 cv::Mat keypoints, descriptors;
59 const std::vector< std::shared_ptr<const Image> > &all_images = dataset.
all_images();
60 #if ENABLE_MULTITHREADING && ENABLE_OPENMP
61 uint32_t num_threads = omp_get_max_threads();
62 std::vector< cv::Ptr<cv::DescriptorMatcher> > matchers;
63 for (uint32_t i = 0; i < num_threads; i++) {
66 #pragma omp parallel for schedule(dynamic)
70 for (int64_t i = 0; i < (int64_t)all_images.size(); i++) {
71 #if ENABLE_MULTITHREADING && ENABLE_OPENMP
72 const cv::Ptr<cv::DescriptorMatcher> &matcher = matchers[omp_get_thread_num()];
74 const std::string &sift_descriptor_location = dataset.
location(all_images[i]->feature_path(
"descriptors"));
75 const std::string &bow_descriptor_location = dataset.
location(all_images[i]->feature_path(
"bow_descriptors"));
77 cv::Mat descriptors, bow_descriptors, descriptorsf;
80 descriptors.convertTo(descriptorsf, CV_32FC1);
84 const std::vector< std::pair<uint32_t, float> > &bow_descriptors_sparse =
numerics::sparsify(bow_descriptors);
87 LINFO <<
"Wrote " << bow_descriptor_location;
91 std::shared_ptr<VocabTree>
train_tree(
Dataset &dataset, uint32_t num_images, uint32_t split, uint32_t depth) {
93 std::shared_ptr<VocabTree::TrainParams> train_params = std::make_shared<VocabTree::TrainParams>();
94 train_params->depth = depth;
95 train_params->
split = split;
98 std::stringstream vocab_output_file;
99 vocab_output_file << dataset.
location() <<
"/tree/" << split <<
"." << depth <<
".vocab";
100 vt.
save(vocab_output_file.str());
101 return std::make_shared<VocabTree>(vt);
104 std::shared_ptr<BagOfWords>
train_bow(
Dataset &dataset, uint32_t num_images, uint32_t num_clusters) {
106 std::shared_ptr<BagOfWords::TrainParams> train_params = std::make_shared<BagOfWords::TrainParams>();
107 train_params->numClusters = num_clusters;
108 const std::vector< std::shared_ptr<const Image> > &random_images = dataset.
random_images(num_images);
109 bow.
train(dataset, train_params, random_images);
110 std::stringstream vocab_output_file;
111 vocab_output_file << dataset.
location() <<
"/vocabulary/" << train_params->numClusters <<
".vocab";
112 bow.
save(vocab_output_file.str());
113 return std::make_shared<BagOfWords>(bow);
118 std::shared_ptr<InvertedIndex::TrainParams> train_params = std::make_shared<InvertedIndex::TrainParams>();
119 train_params->bag_of_words = bow;
122 return std::make_shared<InvertedIndex>(ii);
129 uint32_t num_images = 128;
131 uint32_t bow_clusters[] = { 256, 3125, 46656 };
132 std::pair<uint32_t, uint32_t> tree_branches[] = {
133 std::pair<uint32_t, uint32_t>(4, 4),
134 std::pair<uint32_t, uint32_t>(5, 5),
135 std::pair<uint32_t, uint32_t>(6, 6)};
137 std::stringstream timings_file_name;
138 timings_file_name << dataset.
location() +
"/results/times.index.json";
140 std::ofstream ofs(timings_file_name.str(), std::ios::app);
142 for(
size_t i=0; i<3; i++) {
143 LINFO <<
"Training bag of words";
145 std::shared_ptr<BagOfWords> bow =
train_bow(dataset, num_images, bow_clusters[i]);
148 std::stringstream timing;
151 "\"operation\" : \"" <<
"bow_train" <<
"\", " <<
152 "\"bow_numclusters\" : " << bow->num_clusters() <<
", " <<
153 "\"db_size\" : " << dataset.
num_images() <<
", " <<
154 "\"time\" : " << end_time_bow - start_time_bow <<
", " <<
159 ofs.write(timing.str().c_str(), timing.str().size());
163 LINFO <<
"Computing bag of words features";
168 std::stringstream timing;
171 "\"operation\" : \"" <<
"bow_features" <<
"\", " <<
172 "\"bow_numclusters\" : " << bow->num_clusters() <<
", " <<
173 "\"db_size\" : " << dataset.
num_images() <<
", " <<
174 "\"time\" : " << end_time_bowfeatures - start_time_bowfeatures <<
", " <<
179 ofs.write(timing.str().c_str(), timing.str().size());
183 LINFO <<
"Computing index";
185 std::shared_ptr<InvertedIndex> ii =
train_index(dataset, bow);
188 std::stringstream timing;
191 "\"operation\" : \"" <<
"index_train" <<
"\", " <<
192 "\"index_numclusters\" : " << ii->num_clusters() <<
", " <<
193 "\"db_size\" : " << dataset.
num_images() <<
", " <<
194 "\"time\" : " << end_time_index - start_time_index <<
", " <<
199 ofs.write(timing.str().c_str(), timing.str().size());
203 LINFO <<
"Training tree";
205 std::shared_ptr<VocabTree> vt =
train_tree(dataset, num_images, tree_branches[i].first, tree_branches[i].second);
208 std::stringstream timing;
211 "\"operation\" : \"" <<
"tree_train" <<
"\", " <<
212 "\"tree_depth\" : " << vt->tree_depth() <<
", " <<
213 "\"tree_split\" : " << vt->tree_splits() <<
", " <<
214 "\"db_size\" : " << dataset.
num_images() <<
", " <<
215 "\"time\" : " << end_time_tree - start_time_tree <<
", " <<
220 ofs.write(timing.str().c_str(), timing.str().size());
224 uint32_t num_validate = 10;
225 uint32_t total_iterations = MIN(dataset.
num_images(), 128);
227 LINFO <<
"Running index search";
231 double total_time = 0.0;
232 uint32_t total_correct = 0, total_tested = 0;
233 for (uint32_t i = 0; i < total_iterations; i++) {
237 std::shared_ptr<InvertedIndex::MatchResults> matches_index =
239 if (matches_index ==
nullptr) {
240 LERROR <<
"Error while running search.";
244 total_time += (end_time - start_time);
247 cv::Mat keypoints_0, descriptors_0;
248 const std::string &query_keypoints_location = dataset.
location(query_image->feature_path(
"keypoints"));
249 const std::string &query_descriptors_location = dataset.
location(query_image->feature_path(
"descriptors"));
252 std::vector<int> validated(MIN(num_validate, matches_index->matches.size()), 0);
253 total_tested += validated.size();
254 uint32_t total_correct_tmp = 0;
255 #if ENABLE_MULTITHREADING && ENABLE_OPENMP
256 #pragma omp parallel for schedule(dynamic) reduction(+:total_correct_tmp)
258 for (int32_t j = 0; j < validated.size(); j++) {
259 cv::Mat keypoints_1, descriptors_1;
260 std::shared_ptr<SimpleDataset::SimpleImage> match_image = std::static_pointer_cast<
SimpleDataset::SimpleImage>(dataset.
image(matches_index->matches[j]));
261 const std::string &match_keypoints_location = dataset.
location(match_image->feature_path(
"keypoints"));
262 const std::string &match_descriptors_location = dataset.
location(match_image->feature_path(
"descriptors"));
266 cv::detail::MatchesInfo match_info;
270 if (validated[j] > 0) total_correct_tmp++;
272 total_correct += total_correct_tmp;
273 html_output_index.
add_match(i, matches_index->matches, dataset, std::make_shared< std::vector<int> >(validated));
275 std::stringstream outfilestr;
276 outfilestr << dataset.
location() <<
"/results/matches/index." << bow->num_clusters();
277 html_output_index.
write(outfilestr.str());
281 std::stringstream timing;
284 "\"operation\" : \"" <<
"index_search" <<
"\", " <<
285 "\"index_numclusters\" : " << ii->num_clusters() <<
", " <<
286 "\"db_size\" : " << dataset.
num_images() <<
", " <<
287 "\"time\" : " << total_time <<
", " <<
288 "\"iterations\" : " << total_iterations <<
", " <<
289 "\"correct\" : " << total_correct <<
", " <<
290 "\"tested\" : " << total_tested <<
", " <<
295 ofs.write(timing.str().c_str(), timing.str().size());
299 LINFO <<
"Running tree search";
303 double total_time = 0.0;
304 uint32_t total_correct = 0, total_tested = 0;
305 for (uint32_t i = 0; i < total_iterations; i++) {
309 std::shared_ptr<InvertedIndex::MatchResults> matches_index =
311 if (matches_index ==
nullptr) {
312 LERROR <<
"Error while running search.";
316 total_time += (end_time - start_time);
319 cv::Mat keypoints_0, descriptors_0;
320 const std::string &query_keypoints_location = dataset.
location(query_image->feature_path(
"keypoints"));
321 const std::string &query_descriptors_location = dataset.
location(query_image->feature_path(
"descriptors"));
324 std::vector<int> validated(MIN(num_validate, matches_index->matches.size()), 0);
325 total_tested += validated.size();
326 uint32_t total_correct_tmp = 0;
327 #if ENABLE_MULTITHREADING && ENABLE_OPENMP
328 #pragma omp parallel for schedule(dynamic) reduction(+:total_correct_tmp)
330 for (int32_t j = 0; j < validated.size(); j++) {
331 cv::Mat keypoints_1, descriptors_1;
332 std::shared_ptr<SimpleDataset::SimpleImage> match_image = std::static_pointer_cast<
SimpleDataset::SimpleImage>(dataset.
image(matches_index->matches[j]));
333 const std::string &match_keypoints_location = dataset.
location(match_image->feature_path(
"keypoints"));
334 const std::string &match_descriptors_location = dataset.
location(match_image->feature_path(
"descriptors"));
338 cv::detail::MatchesInfo match_info;
342 if (validated[j] > 0) total_correct_tmp++;
344 total_correct += total_correct_tmp;
345 html_output_tree.
add_match(i, matches_index->matches, dataset, std::make_shared< std::vector<int> >(validated));
347 std::stringstream outfilestr;
348 outfilestr << dataset.
location() <<
"/results/matches/tree." << vt->tree_depth() <<
"." << vt->tree_splits();
349 html_output_tree.
write(outfilestr.str());
353 std::stringstream timing;
356 "\"operation\" : \"" <<
"tree_search" <<
"\", " <<
357 "\"tree_depth\" : " << vt->tree_depth() <<
", " <<
358 "\"tree_split\" : " << vt->tree_splits() <<
", " <<
359 "\"db_size\" : " << dataset.
num_images() <<
", " <<
360 "\"time\" : " << total_time <<
", " <<
361 "\"iterations\" : " << total_iterations <<
", " <<
362 "\"correct\" : " << total_correct <<
", " <<
363 "\"tested\" : " << total_tested <<
", " <<
368 ofs.write(timing.str().c_str(), timing.str().size());
376 int main(
int argc,
char *argv[]) {
377 #if ENABLE_MULTITHREADING && ENABLE_MPI
378 MPI::Init(argc, argv);
379 int rank = MPI::COMM_WORLD.Get_rank();
390 for (
size_t i = 0; i < 3; i++) {
391 LINFO << datasets[i];
396 #if ENABLE_MULTITHREADING && ENABLE_MPI