// compare images feature using db int VocabCompare(int argc, char **argv) { if (argc != 5 && argc != 6) { printf("Usage: %s <tree.in> <image1.key> <image2.key> <matches.out> [distance_type]\n", argv[0]); return 1; } char *tree_in = argv[1]; char *image1_in = argv[2]; char *image2_in = argv[3]; char *matches_out = argv[4]; DistanceType distance_type = DistanceMin; if (argc >= 6) distance_type = (DistanceType)atoi(argv[5]); switch (distance_type) { case DistanceDot: printf("[VocabMatch] Using distance Dot\n"); break; case DistanceMin: printf("[VocabMatch] Using distance Min\n"); break; default: printf("[VocabMatch] Using no known distance!\n"); break; } printf("[VocabBuildDB] Reading tree %s...\n", tree_in); fflush(stdout); VocabTree tree; tree.Read(tree_in); printf("[VocabCompare] Flattening tree...\n"); tree.Flatten(); tree.m_distance_type = distance_type; tree.SetInteriorNodeWeight(0.0); /* Initialize leaf weights to 1.0 */ tree.SetConstantLeafWeights(); const int dim = 128; tree.ClearDatabase(); int num_keys_1 = 0, num_keys_2 = 0; unsigned char *keys1 = ReadKeys(image1_in, dim, num_keys_1); unsigned char *keys2 = ReadKeys(image2_in, dim, num_keys_2); unsigned long *ids1 = new unsigned long[num_keys_1]; unsigned long *ids2 = new unsigned long[num_keys_2]; printf("[VocabCompare] Adding image 0 (%d keys)\n", num_keys_1); tree.AddImageToDatabase(0, num_keys_1, keys1, ids1); if (num_keys_1 > 0) delete[] keys1; printf("[VocabCompare] Adding image 1 (%d keys)\n", num_keys_2); tree.AddImageToDatabase(1, num_keys_2, keys2, ids2); if (num_keys_2 > 0) delete[] keys2; // tree.ComputeTFIDFWeights(); tree.NormalizeDatabase(0, 2); //Find collisions among visual word IDs std::multimap<unsigned long, unsigned int> word_map; for (unsigned int i = 0; i < (unsigned int)num_keys_1; i++) { printf("0 %d -> %lu\n", i, ids1[i]); std::pair<unsigned long, unsigned int> elem(ids1[i], i); word_map.insert(elem); } //Count number of matches int num_matches = 0; for (unsigned int i = 0; i < (unsigned int)num_keys_2; i++) { unsigned long id = ids2[i]; printf("1 %d -> %lu\n", i, ids2[i]); std::pair<std::multimap<unsigned long, unsigned int>::iterator, std::multimap<unsigned long, unsigned int>::iterator> ret; ret = word_map.equal_range(id); unsigned int size = 0; std::multimap<unsigned long, unsigned int>::iterator iter; for (iter = ret.first; iter != ret.second; iter++) size++, num_matches++; if (size > 0) printf("size[%lu] = %d\n", id, size); } printf("number of matches: %d\n", num_matches); fflush(stdout); FILE *f = fopen(matches_out, "w"); if (f == NULL) { printf("Error opening file %s for writing\n", matches_out); return 1; } fprintf(f, "%d\n", num_matches); /* Write matches */ for (unsigned int i = 0; i < (unsigned int)num_keys_2; i++) { unsigned long id = ids2[i]; std::pair<std::multimap<unsigned long, unsigned int>::iterator, std::multimap<unsigned long, unsigned int>::iterator> ret; ret = word_map.equal_range(id); std::multimap<unsigned long, unsigned int>::iterator iter; for (iter = ret.first; iter != ret.second; iter++) fprintf(f, "%d %d\n", iter->second, i); } fclose(f); // printf("[VocabBuildDB] Writing tree...\n"); // tree.Write(tree_out); return 0; }
int main(int argc, char **argv) { if (argc < 4 || argc > 8) { printf("Usage: %s <list.in> <tree.in> <tree.out> [use_tfidf:1] " "[normalize:1] [start_id:0] [distance_type:1]\n", argv[0]); return 1; } double min_feature_scale = 1.4; bool use_tfidf = true; bool normalize = true; char *list_in = argv[1]; char *tree_in = argv[2]; char *tree_out = argv[3]; DistanceType distance_type = DistanceMin; int start_id = 0; if (argc >= 5) use_tfidf = atoi(argv[4]); if (argc >= 6) normalize = atoi(argv[5]); if (argc >= 7) start_id = atoi(argv[6]); if (argc >= 8) distance_type = (DistanceType) atoi(argv[7]); switch (distance_type) { case DistanceDot: printf("[VocabMatch] Using distance Dot\n"); break; case DistanceMin: printf("[VocabMatch] Using distance Min\n"); break; default: printf("[VocabMatch] Using no known distance!\n"); break; } FILE *f = fopen(list_in, "r"); if (f == NULL) { printf("Error opening file %s for reading\n", list_in); return 1; } std::vector<std::string> key_files; char buf[256]; while (fgets(buf, 256, f)) { /* Remove trailing newline */ if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0; key_files.push_back(std::string(buf)); } printf("[VocabBuildDB] Reading tree %s...\n", tree_in); fflush(stdout); VocabTree tree; tree.Read(tree_in); #if 1 tree.Flatten(); #endif tree.m_distance_type = distance_type; tree.SetInteriorNodeWeight(0.0); /* Initialize leaf weights to 1.0 */ tree.SetConstantLeafWeights(); const int dim = 128; int num_db_images = (int) key_files.size(); unsigned long count = 0; tree.ClearDatabase(); for (int i = 0; i < num_db_images; i++) { int num_keys = 0; unsigned char *keys = ReadAndFilterKeys(key_files[i].c_str(), dim, min_feature_scale, 0, num_keys); printf("[VocabBuildDB] Adding vector %d (%d keys)\n", start_id + i, num_keys); tree.AddImageToDatabase(start_id + i, num_keys, keys); if (num_keys > 0) delete [] keys; } printf("[VocabBuildDB] Pushed %lu features\n", count); fflush(stdout); if (use_tfidf) tree.ComputeTFIDFWeights(num_db_images); if (normalize) tree.NormalizeDatabase(start_id, num_db_images); printf("[VocabBuildDB] Writing tree...\n"); tree.Write(tree_out); // char filename[256]; // sprintf(filename, "vectors_%03d.txt", start_id); // tree.WriteDatabaseVectors(filename, start_id, num_db_images); return 0; }
// Building a database with a vocabulary tree int VocabDB(char *list_in, char *tree_in, char *db_out, int use_tfidf = 1, int normalize = 1, int start_id = 0, DistanceType distance_type = DistanceMin) { double min_feature_scale = 1.4; switch (distance_type) { case DistanceDot: printf("[VocabMatch] Using distance Dot\n"); break; case DistanceMin: printf("[VocabMatch] Using distance Min\n"); break; default: printf("[VocabMatch] Using no known distance!\n"); break; } FILE *f = fopen(list_in, "r"); if (f == NULL) { printf("Error opening file %s for reading\n", list_in); return 1; } std::vector<std::string> key_files; char buf[256]; while (fgets(buf, 256, f)) { /* Remove trailing newline */ if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0; key_files.push_back(std::string(buf)); } printf("[VocabBuildDB] Reading tree %s...\n", tree_in); fflush(stdout); VocabTree tree; tree.Read(tree_in); tree.Flatten(); tree.m_distance_type = distance_type; tree.SetInteriorNodeWeight(0.0); //Initialize leaf weights to 1.0 tree.SetConstantLeafWeights(); const int dim = 128; int num_db_images = (int)key_files.size(); unsigned long count = 0; tree.ClearDatabase(); for (int i = 0; i < num_db_images; i++) { int num_keys = 0; unsigned char *keys = ReadAndFilterKeys(key_files[i].c_str(), dim, min_feature_scale, 0, num_keys); printf("[VocabBuildDB] Adding vector %d (%d keys)\n", start_id + i, num_keys); tree.AddImageToDatabase(start_id + i, num_keys, keys); if (num_keys > 0) delete[] keys; } printf("[VocabBuildDB] Pushed %lu features\n", count); fflush(stdout); if (use_tfidf == 1) tree.ComputeTFIDFWeights(num_db_images); if (normalize == 1) tree.NormalizeDatabase(start_id, num_db_images); printf("[VocabBuildDB] Writing database ...\n"); tree.Write(db_out); // char filename[256]; // sprintf(filename, "vectors_%03d.txt", start_id); // tree.WriteDatabaseVectors(filename, start_id, num_db_images); return 0; }