From 049600af8132712f97706d34f34bccd2e8ae2064 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Thu, 7 Jun 2018 11:14:13 +0200 Subject: [PATCH 01/12] VS2017 compile errors resolved --- src/cpu_x86.h | 13 ++++++++----- src/fbow.cpp | 12 +++++++++++- src/fbow.h | 7 ++++++- tests/test_cpu_x86.cpp | 2 +- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/cpu_x86.h b/src/cpu_x86.h index d6c7107..e8c8e4a 100644 --- a/src/cpu_x86.h +++ b/src/cpu_x86.h @@ -35,13 +35,17 @@ struct cpu_x86{ static bool inline detect_OS_AVX512(); static inline uint64_t xgetbv(unsigned int x); }; +/////GCC +} +using namespace fbow; //// MSCV #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) # if _WIN32 void cpu_x86::cpuid(int32_t out[4], int32_t x){ __cpuidex(out, x, 0); } -__int64 cpu_x86::xgetbv(unsigned int x){ return _xgetbv(x); } +uint64_t cpu_x86::xgetbv(unsigned int x){ return _xgetbv(x); } // Detect 64-bit - Note that this snippet of code for detecting 64-bit has been copied from MSDN. typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +#ifndef _M_X64 BOOL IsWow64() { BOOL bIsWow64 = FALSE; @@ -50,6 +54,8 @@ BOOL IsWow64() if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) return FALSE; return bIsWow64 ; } +#endif + bool cpu_x86::cpu_x86::detect_OS_x64(){ #ifdef _M_X64 return true; @@ -57,8 +63,7 @@ bool cpu_x86::cpu_x86::detect_OS_x64(){ return IsWow64() != 0; #endif } -/////GCC -} + # elif defined(__GNUC__) || defined(__clang__) void cpu_x86::cpuid(int32_t out[4], int32_t x){ __cpuid_count(x, 0, out[0], out[1], out[2], out[3]); } uint64_t cpu_x86::xgetbv(unsigned int index){ uint32_t eax, edx; __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); return ((uint64_t)edx << 32) | eax;} @@ -94,6 +99,4 @@ void cpu_x86::detect_host(){ OS_x64 = detect_OS_x64(); OS_AVX = detect_OS_AV if (nIds >= 0x00000007){ cpuid(info, 0x00000007); HW_AVX2 = (info[1] & ((int)1 << 5)) != 0; HW_BMI1 = (info[1] & ((int)1 << 3)) != 0; HW_BMI2 = (info[1] & ((int)1 << 8)) != 0; HW_ADX = (info[1] & ((int)1 << 19)) != 0; HW_MPX = (info[1] & ((int)1 << 14)) != 0; HW_SHA = (info[1] & ((int)1 << 29)) != 0; HW_PREFETCHWT1 = (info[2] & ((int)1 << 0)) != 0; HW_AVX512_F = (info[1] & ((int)1 << 16)) != 0; HW_AVX512_CD = (info[1] & ((int)1 << 28)) != 0; HW_AVX512_PF = (info[1] & ((int)1 << 26)) != 0; HW_AVX512_ER = (info[1] & ((int)1 << 27)) != 0; HW_AVX512_VL = (info[1] & ((int)1 << 31)) != 0; HW_AVX512_BW = (info[1] & ((int)1 << 30)) != 0; HW_AVX512_DQ = (info[1] & ((int)1 << 17)) != 0; HW_AVX512_IFMA = (info[1] & ((int)1 << 21)) != 0; HW_AVX512_VBMI = (info[2] & ((int)1 << 1)) != 0; } if (nExIds >= 0x80000001){ cpuid(info, 0x80000001); HW_x64 = (info[3] & ((int)1 << 29)) != 0; HW_ABM = (info[2] & ((int)1 << 5)) != 0; HW_SSE4a = (info[2] & ((int)1 << 6)) != 0; HW_FMA4 = (info[2] & ((int)1 << 16)) != 0; HW_XOP = (info[2] & ((int)1 << 11)) != 0; } } - -} #endif diff --git a/src/fbow.cpp b/src/fbow.cpp index c10e067..bd0cdf8 100644 --- a/src/fbow.cpp +++ b/src/fbow.cpp @@ -45,7 +45,11 @@ void Vocabulary::setParams(int aligment, int k, int desc_type, int desc_size, in //give memory _params._total_size=_params._block_size_bytes_wp*_params._nblocks; +#if _WIN32 + _data = (char*)_aligned_malloc(_params._aligment, _params._total_size); +#else _data=(char*)aligned_alloc(_params._aligment,_params._total_size); +#endif memset( _data,0,_params._total_size); } @@ -147,7 +151,13 @@ void Vocabulary::fromStream(std::istream &str)throw(std::exception) if (sig!=55824124) throw std::runtime_error("Vocabulary::fromStream invalid signature"); //read string str.read((char*)&_params,sizeof(params)); - _data=(char*)aligned_alloc(_params._aligment,_params._total_size); + +#if _WIN32 + _data = (char*)_aligned_malloc(_params._aligment, _params._total_size); +#else + _data = (char*)aligned_alloc(_params._aligment, _params._total_size); +#endif + if (_data==0) throw std::runtime_error("Vocabulary::fromStream Could not allocate data"); str.read(_data,_params._total_size); } diff --git a/src/fbow.h b/src/fbow.h index 5b816c3..1bc931e 100644 --- a/src/fbow.h +++ b/src/fbow.h @@ -190,7 +190,12 @@ class FBOW_API Vocabulary _block_desc_size_bytes_wp=block_desc_size_bytes_wp; assert(_block_desc_size_bytes_wp%sizeof(register_type )==0); _nwords=_block_desc_size_bytes_wp/sizeof(register_type );//number of aligned words - feature=(register_type*)aligned_alloc(aligment,_nwords*sizeof(register_type )); + +#if _WIN32 + feature = (register_type*)_aligned_malloc(aligment, _nwords * sizeof(register_type)); +#else + feature = (register_type*)aligned_alloc(aligment, _nwords * sizeof(register_type)); +#endif memset(feature,0,_nwords*sizeof(register_type )); } inline void startwithfeature(const register_type *feat_ptr){memcpy(feature,feat_ptr,_desc_size);} diff --git a/tests/test_cpu_x86.cpp b/tests/test_cpu_x86.cpp index 33e7a3c..8a874a2 100644 --- a/tests/test_cpu_x86.cpp +++ b/tests/test_cpu_x86.cpp @@ -75,7 +75,7 @@ void print(cpu_x86 host_info) { int main(){ - cout << "CPU Vendor String: " << cpu_x86::get_vendor_string() << endl; + cout << "CPU Vendor String: " << cpu_x86::get_vendor_string().c_str() << endl; cout << endl; cpu_x86 features; features.detect_host(); From f5733f56078762d198fec5b5fa379b89f867d053 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Thu, 7 Jun 2018 12:46:44 +0200 Subject: [PATCH 02/12] bugfix: resolved windows seg fault --- src/fbow.cpp | 4 ++-- src/fbow.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fbow.cpp b/src/fbow.cpp index bd0cdf8..b601d14 100644 --- a/src/fbow.cpp +++ b/src/fbow.cpp @@ -46,7 +46,7 @@ void Vocabulary::setParams(int aligment, int k, int desc_type, int desc_size, in //give memory _params._total_size=_params._block_size_bytes_wp*_params._nblocks; #if _WIN32 - _data = (char*)_aligned_malloc(_params._aligment, _params._total_size); + _data = (char*)_aligned_malloc(_params._total_size, _params._aligment); #else _data=(char*)aligned_alloc(_params._aligment,_params._total_size); #endif @@ -153,7 +153,7 @@ void Vocabulary::fromStream(std::istream &str)throw(std::exception) str.read((char*)&_params,sizeof(params)); #if _WIN32 - _data = (char*)_aligned_malloc(_params._aligment, _params._total_size); + _data = (char*)_aligned_malloc(_params._total_size, _params._aligment); #else _data = (char*)aligned_alloc(_params._aligment, _params._total_size); #endif diff --git a/src/fbow.h b/src/fbow.h index 1bc931e..6a5cb89 100644 --- a/src/fbow.h +++ b/src/fbow.h @@ -192,7 +192,7 @@ class FBOW_API Vocabulary _nwords=_block_desc_size_bytes_wp/sizeof(register_type );//number of aligned words #if _WIN32 - feature = (register_type*)_aligned_malloc(aligment, _nwords * sizeof(register_type)); + feature = (register_type*)_aligned_malloc(_nwords * sizeof(register_type), aligment); #else feature = (register_type*)aligned_alloc(aligment, _nwords * sizeof(register_type)); #endif From c8bc7cf2286d53b40727f0f9ef77daeaa7d13063 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Fri, 8 Jun 2018 12:04:46 +0200 Subject: [PATCH 03/12] Modified destructors for windows --- src/fbow.cpp | 8 +++++++- src/fbow.h | 10 +++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/fbow.cpp b/src/fbow.cpp index b601d14..7fd8009 100644 --- a/src/fbow.cpp +++ b/src/fbow.cpp @@ -6,7 +6,13 @@ namespace fbow{ Vocabulary::~Vocabulary(){ - if (_data!=0) free( _data); + if (_data != 0) { +#if WIN32 + _aligned_free(_data); +#else + free(_data); +#endif + } } diff --git a/src/fbow.h b/src/fbow.h index 6a5cb89..b0a36e2 100644 --- a/src/fbow.h +++ b/src/fbow.h @@ -183,7 +183,15 @@ class FBOW_API Vocabulary int _block_desc_size_bytes_wp; register_type *feature=0; public: - ~Lx(){if (feature!=0)free(feature);} + ~Lx(){ + if (feature != 0) { +#if WIN32 + _aligned_free(feature); +#else + free(feature); +#endif + } + } void setParams(int desc_size, int block_desc_size_bytes_wp){ assert(block_desc_size_bytes_wp%aligment==0); _desc_size=desc_size; From 3ab283ae7e5836bb41ad0b58e59144b3248f6802 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Fri, 8 Jun 2018 16:37:22 +0200 Subject: [PATCH 04/12] Image matching files added --- ImageMatching.py | 29 ++++++++ utils/CMakeLists.txt | 1 + utils/image_matching.cpp | 149 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 ImageMatching.py create mode 100644 utils/image_matching.cpp diff --git a/ImageMatching.py b/ImageMatching.py new file mode 100644 index 0000000..5d4eb09 --- /dev/null +++ b/ImageMatching.py @@ -0,0 +1,29 @@ +from os import walk +import os +DBDIR = "Database dir" #the dir where images reside e.g. C:/database +DBNAME = "Databasename" #e.g. database (in the line above) +CODEDIR = "" #e.g. H:/fbow-windows/build/bin/Release +DESCRIPTOR = "orb" +RESULTSDIR = ""#e.g. "C:/FBoWResults" +OUTPUT = RESULTSDIR + "/" + DESCRIPTOR + DBNAME +MKDIRCMD = "mkdir " + OUTPUT +FeaturesExtractCmd = CODEDIR + "/" + "fbow_create_voc_step0.exe " + DESCRIPTOR + " " + OUTPUT + "/features" +VocabCreateCmd = CODEDIR + "/" + "fbow_create_voc_step1.exe " + OUTPUT + "/features " + OUTPUT + "/out.fbow" +ImageMatchingCmd = CODEDIR + "/" + "image_matching.exe " + OUTPUT + "/out.fbow " + OUTPUT + " " + +imagesFileName = "" +i = 1 +for (dirpath, dirnames, filenames) in walk(DBDIR): + for filename in filenames: + imagesFileName += " " + DBDIR + "/" + filename + break +FeaturesExtractCmd += imagesFileName +ImageMatchingCmd += imagesFileName +print("cd " + RESULTSDIR + " & " + "mkdir " + DESCRIPTOR + DBNAME) +os.system("cd " + RESULTSDIR + " & " + "mkdir " + DESCRIPTOR + DBNAME) +print(FeaturesExtractCmd) +os.system(FeaturesExtractCmd) +print(VocabCreateCmd) +os.system(VocabCreateCmd) +print(ImageMatchingCmd) +os.system(ImageMatchingCmd) \ No newline at end of file diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 1c17e27..7857d86 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -6,5 +6,6 @@ ADD_EXECUTABLE(fbow_create_voc_step0 fbow_create_voc_step0.cpp) ADD_EXECUTABLE(fbow_create_voc_step1 fbow_create_voc_step1.cpp) #ADD_EXECUTABLE(fbow_create_voc_step1_opencv fbow_create_voc_step1_opencv.cpp) ADD_EXECUTABLE(fbow_transform fbow_transform.cpp) +ADD_EXECUTABLE(image_matching image_matching.cpp) #INSTALL(TARGETS slammarker RUNTIME DESTINATION bin) diff --git a/utils/image_matching.cpp b/utils/image_matching.cpp new file mode 100644 index 0000000..a562914 --- /dev/null +++ b/utils/image_matching.cpp @@ -0,0 +1,149 @@ +//loads a vocabulary, and a image. Extracts image feaures and then compute the bow of the image +#include "fbow.h" +#include +#include +using namespace std; + +// OpenCV +#include +#include +#include +#ifdef USE_CONTRIB +#include +#include +#endif + + +#include +class CmdLineParser { int argc; char **argv; public: CmdLineParser(int _argc, char **_argv) :argc(_argc), argv(_argv) {} bool operator[] (string param) { int idx = -1; for (int i = 0; i loadFeatures(std::vector path_to_images, string descriptor = "") throw (std::exception) { + //select detector + cv::Ptr fdetector; + if (descriptor == "orb") fdetector = cv::ORB::create(2000); + else if (descriptor == "brisk") fdetector = cv::BRISK::create(); +#ifdef OPENCV_VERSION_3 + else if (descriptor == "akaze") fdetector = cv::AKAZE::create(cv::AKAZE::DESCRIPTOR_MLDB, 0, 3, 1e-4); +#endif +#ifdef USE_CONTRIB + else if (descriptor == "surf") fdetector = cv::xfeatures2d::SURF::create(15, 4, 2); +#endif + + else throw std::runtime_error("Invalid descriptor"); + assert(!descriptor.empty()); + vector features; + + + cout << "Extracting features..." << endl; + for (size_t i = 0; i < path_to_images.size(); ++i) + { + vector keypoints; + cv::Mat descriptors; + cout << "reading image: " << path_to_images[i] << endl; + cv::Mat image = cv::imread(path_to_images[i], 0); + if (image.empty())throw std::runtime_error("Could not open image" + path_to_images[i]); + cout << "extracting features" << endl; + fdetector->detectAndCompute(image, cv::Mat(), keypoints, descriptors); + features.push_back(descriptors); + cout << "done detecting features" << endl; + } + return features; +} + +int main(int argc, char **argv) { + CmdLineParser cml(argc, argv); + try { + if (argc<3 || cml["-h"]) throw std::runtime_error("Usage: fbow image [descriptor]"); + fbow::Vocabulary voc; + voc.readFromFile(argv[1]); + + string desc_name = voc.getDescName(); + cout << "voc desc name=" << desc_name << endl; + vector > features(argc - 3); + vector > scores; + vector filenames(argc - 3); + string outDir = argv[2]; + for (int i = 3; i < argc; ++i) + { + filenames[i - 3] = { argv[i] }; + } + for (int i = 0; i score; + for (int j = 0; j 0.01f) + { + score.insert(pair(score1, j)); + } + printf("%f, ", score1); + } + printf("\n"); + scores.push_back(score); + } + auto t_end = std::chrono::high_resolution_clock::now(); + avgScore += double(std::chrono::duration_cast(t_end - t_start).count()); + + std::string command; + int j = 0; + for (int i = 0; i < scores.size(); i++) + { + std::stringstream str; + + command = "mkdir "; + str << i; + command += str.str(); + command += "/"; + system(command.c_str()); + + command = "cp "; + command += filenames[i]; + command += " "; + command += str.str(); + command += "/source.JPG"; + + system((string("cd ") + outDir).c_str()); + system(command.c_str()); + j = 0; + for (auto it = scores[i].begin(); it != scores[i].end(); it++) + { + ++j; + std::stringstream str2; + command = "cp "; + command += filenames[it->second]; + command += " "; + command += str.str(); + command += "/"; + str2 << j << "-"; + str2 << it->first; + command += str2.str(); + command += ".JPG"; + system(command.c_str()); + } + + } + /* + { + cout<first<<" "<second<first<<" "<second< Date: Tue, 12 Jun 2018 13:49:53 +0200 Subject: [PATCH 05/12] added io on yml files: the binary io was not cross platform --- utils/fbow_create_voc_step0.cpp | 80 ++++++++++++++++++++++----------- utils/fbow_create_voc_step1.cpp | 51 ++++++++++++++------- 2 files changed, 91 insertions(+), 40 deletions(-) diff --git a/utils/fbow_create_voc_step0.cpp b/utils/fbow_create_voc_step0.cpp index ada21d4..a8f205f 100644 --- a/utils/fbow_create_voc_step0.cpp +++ b/utils/fbow_create_voc_step0.cpp @@ -17,7 +17,6 @@ using namespace fbow; using namespace std; - //command line parser class CmdLineParser{int argc; char **argv; public: CmdLineParser(int _argc,char **_argv):argc(_argc),argv(_argv){} bool operator[] ( string param ) {int idx=-1; for ( int i=0; i readImagePaths(int argc,char **argv,int start){ return paths; } -vector< cv::Mat > loadFeatures( std::vector path_to_images,string descriptor="") throw (std::exception){ +vector< cv::Mat > loadFeatures( vector path_to_images,string descriptor="") throw (exception){ //select detector cv::Ptr fdetector; if (descriptor=="orb") fdetector=cv::ORB::create(2000); @@ -50,7 +49,7 @@ vector< cv::Mat > loadFeatures( std::vector path_to_images,string desc else if(descriptor=="surf" ) fdetector=cv::xfeatures2d::SURF::create(15, 4, 2); #endif - else throw std::runtime_error("Invalid descriptor"); + else throw runtime_error("Invalid descriptor"); assert(!descriptor.empty()); vector features; @@ -62,9 +61,10 @@ vector< cv::Mat > loadFeatures( std::vector path_to_images,string desc cv::Mat descriptors; cout<<"reading image: "<detectAndCompute(image, cv::Mat(), keypoints, descriptors); + cout << path_to_images[i] << " : " << descriptors.rows << endl; features.push_back(descriptors); cout<<"done detecting features"< loadFeatures( std::vector path_to_images,string desc } // ---------------------------------------------------------------------------- -void saveToFile(string filename,const vector &features, std::string desc_name,bool rewrite =true)throw (std::exception){ +void saveToFile(string filename, const vector &features, string desc_name, bool rewrite = true)throw (exception) { //test it is not created - if (!rewrite){ - std::fstream ifile(filename); + if (!rewrite) { + fstream ifile(filename); if (ifile.is_open())//read size and rewrite - std::runtime_error( "ERROR::: Output File "+filename+" already exists!!!!!" ); + runtime_error("ERROR::: Output File " + filename + " already exists!!!!!"); } - std::ofstream ofile(filename); - if (!ofile.is_open()){cerr<<"could not open output file"<(0), f.total()*f.elemSize()); + } +} + +// ---------------------------------------------------------------------------- +void saveToYMLFile(string filename, const vector &features, string desc_name, bool rewrite = true)throw (exception) { + + //test it is not created + if (!rewrite) { + fstream ifile(filename); + if (ifile.is_open())//read size and rewrite + runtime_error("ERROR::: Output File " + filename + " already exists!!!!!"); + } + + cv::FileStorage file(filename, cv::FileStorage::WRITE); + if (!file.isOpened()) { cerr << "could not open output file" << endl; exit(0); } + + // Declare what you need + file << "descriptor name" << desc_name; + file << "num features" << (int)(features.size());//does not handle size_t for some reason! + for (int i = 0; i < features.size();++i) { + if (!features[i].isContinuous()) { + cerr << "Matrices should be continuous" << endl; exit(0); } - uint32_t aux=f.cols; ofile.write( (char*)&aux,sizeof(aux)); - aux=f.rows; ofile.write( (char*)&aux,sizeof(aux)); - aux=f.type(); ofile.write( (char*)&aux,sizeof(aux)); - ofile.write( (char*)f.ptr(0),f.total()*f.elemSize()); + stringstream str; + str << "featureidx" << i; + // Write to file! + file << str.str() << features[i]; } + file.release(); } // ---------------------------------------------------------------------------- @@ -120,9 +150,9 @@ int main(int argc,char **argv) vector< cv::Mat > features= loadFeatures(images,descriptor); //save features to file - saveToFile(argv[2],features,descriptor); + saveToYMLFile(argv[2],features,descriptor); - }catch(std::exception &ex){ + }catch(exception &ex){ cerr< readFeaturesFromFile(string filename,std::string &desc_name){ -vector features; +vector readFeaturesFromFile(string filename, std::string &desc_name) { + vector features; //test it is not created std::ifstream ifile(filename); - if (!ifile.is_open()){cerr<<"could not open input file"<(0),features[i].total()*features[i].elemSize()); + for (size_t i = 0; i(0), features[i].total()*features[i].elemSize()); + } + return features; +} + +vector readFeaturesFromYMLFile(string filename, std::string &desc_name) { + vector features; + cv::FileStorage file(filename, cv::FileStorage::READ); + //test it is not created + std::ifstream ifile(filename); + if (!file.isOpened()) { cerr << "could not open input file" << endl; exit(0); } + int size; + + file["descriptor name"] >> desc_name; + file["num features"] >> size;//does not support uint32_t + features.resize(size); + for (size_t i = 0; i> features[i]; + } return features; } @@ -55,7 +76,7 @@ int main(int argc,char **argv) string desc_name; - auto features=readFeaturesFromFile(argv[1],desc_name); + auto features= readFeaturesFromYMLFile(argv[1],desc_name); cout<<"DescName="< Date: Tue, 12 Jun 2018 16:05:43 +0200 Subject: [PATCH 06/12] Added Cross platform features to ImageMatching.py --- ImageMatching.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/ImageMatching.py b/ImageMatching.py index 5d4eb09..cac0053 100644 --- a/ImageMatching.py +++ b/ImageMatching.py @@ -1,26 +1,39 @@ from os import walk import os -DBDIR = "Database dir" #the dir where images reside e.g. C:/database -DBNAME = "Databasename" #e.g. database (in the line above) + +#---------------Configs--------------------- +DBDIR = "" #the dir where images reside e.g. C:/database +DBNAME = "" #e.g. database (in the line above) CODEDIR = "" #e.g. H:/fbow-windows/build/bin/Release -DESCRIPTOR = "orb" +DESCRIPTOR = "akaze" RESULTSDIR = ""#e.g. "C:/FBoWResults" +OS = "Windows" # or "LinuxBase" + +#----------------Path Setting--------------- +Extension = ".exe" if OS == "Windows" else "" +ENDCMD = "&" if OS == "Windows" else ";" OUTPUT = RESULTSDIR + "/" + DESCRIPTOR + DBNAME MKDIRCMD = "mkdir " + OUTPUT -FeaturesExtractCmd = CODEDIR + "/" + "fbow_create_voc_step0.exe " + DESCRIPTOR + " " + OUTPUT + "/features" -VocabCreateCmd = CODEDIR + "/" + "fbow_create_voc_step1.exe " + OUTPUT + "/features " + OUTPUT + "/out.fbow" -ImageMatchingCmd = CODEDIR + "/" + "image_matching.exe " + OUTPUT + "/out.fbow " + OUTPUT + " " +#---------------Commands-------------------- +FeaturesExtractCmd = CODEDIR + "/" + "fbow_create_voc_step0" + Extension + " " + DESCRIPTOR + " " + OUTPUT + "/features.yml" +VocabCreateCmd = CODEDIR + "/" + "fbow_create_voc_step1" + Extension + " " + OUTPUT + "/features.yml " + OUTPUT + "/out.fbow" +ImageMatchingCmd = CODEDIR + "/" + "image_matching" + Extension + " " + OUTPUT + "/out.fbow " + OUTPUT + " " + +#---------------List Images----------------- imagesFileName = "" i = 1 for (dirpath, dirnames, filenames) in walk(DBDIR): + filenames.sort() for filename in filenames: imagesFileName += " " + DBDIR + "/" + filename break FeaturesExtractCmd += imagesFileName ImageMatchingCmd += imagesFileName -print("cd " + RESULTSDIR + " & " + "mkdir " + DESCRIPTOR + DBNAME) -os.system("cd " + RESULTSDIR + " & " + "mkdir " + DESCRIPTOR + DBNAME) + +#---------------Run Commands---------------- +print("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) +os.system("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) print(FeaturesExtractCmd) os.system(FeaturesExtractCmd) print(VocabCreateCmd) From ce28780ca1e8198df864c23d5fd183dad868c955 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Thu, 14 Jun 2018 09:34:51 +0200 Subject: [PATCH 07/12] Image matching problems resolved for Windows --- utils/image_matching.cpp | 277 +++++++++++++++++++++++---------------- 1 file changed, 163 insertions(+), 114 deletions(-) diff --git a/utils/image_matching.cpp b/utils/image_matching.cpp index a562914..9857b2d 100644 --- a/utils/image_matching.cpp +++ b/utils/image_matching.cpp @@ -1,149 +1,198 @@ -//loads a vocabulary, and a image. Extracts image feaures and then compute the bow of the image -#include "fbow.h" #include -#include -using namespace std; +#include +#include +// +#include "vocabulary_creator.h" // OpenCV #include -#include -#include -#ifdef USE_CONTRIB -#include -#include -#endif - +using namespace std; -#include +//command line parser class CmdLineParser { int argc; char **argv; public: CmdLineParser(int _argc, char **_argv) :argc(_argc), argv(_argv) {} bool operator[] (string param) { int idx = -1; for (int i = 0; i loadFeatures(std::vector path_to_images, string descriptor = "") throw (std::exception) { - //select detector - cv::Ptr fdetector; - if (descriptor == "orb") fdetector = cv::ORB::create(2000); - else if (descriptor == "brisk") fdetector = cv::BRISK::create(); -#ifdef OPENCV_VERSION_3 - else if (descriptor == "akaze") fdetector = cv::AKAZE::create(cv::AKAZE::DESCRIPTOR_MLDB, 0, 3, 1e-4); -#endif -#ifdef USE_CONTRIB - else if (descriptor == "surf") fdetector = cv::xfeatures2d::SURF::create(15, 4, 2); -#endif +// ---------------------------------------------------------------------------- - else throw std::runtime_error("Invalid descriptor"); - assert(!descriptor.empty()); - vector features; +// ---------------------------------------------------------------------------- +vector readFeaturesFromFile(string filename, std::string &desc_name) { + vector features; + //test it is not created + std::ifstream ifile(filename); + if (!ifile.is_open()) { cerr << "could not open input file" << endl; exit(0); } - cout << "Extracting features..." << endl; - for (size_t i = 0; i < path_to_images.size(); ++i) - { - vector keypoints; - cv::Mat descriptors; - cout << "reading image: " << path_to_images[i] << endl; - cv::Mat image = cv::imread(path_to_images[i], 0); - if (image.empty())throw std::runtime_error("Could not open image" + path_to_images[i]); - cout << "extracting features" << endl; - fdetector->detectAndCompute(image, cv::Mat(), keypoints, descriptors); - features.push_back(descriptors); - cout << "done detecting features" << endl; + char _desc_name[20]; + ifile.read(_desc_name, 20); + desc_name = _desc_name; + + uint32_t size; + ifile.read((char*)&size, sizeof(size)); + features.resize(size); + for (size_t i = 0; i(0), features[i].total()*features[i].elemSize()); } return features; } -int main(int argc, char **argv) { - CmdLineParser cml(argc, argv); - try { - if (argc<3 || cml["-h"]) throw std::runtime_error("Usage: fbow image [descriptor]"); - fbow::Vocabulary voc; - voc.readFromFile(argv[1]); +vector readFeaturesFromYMLFile(string filename, std::string &desc_name) { + vector features; + cv::FileStorage file(filename, cv::FileStorage::READ); + //test it is not created + std::ifstream ifile(filename); + if (!file.isOpened()) { cerr << "could not open input file" << endl; exit(0); } + int size; + + file["descriptor name"] >> desc_name; + file["num features"] >> size;//does not support uint32_t + features.resize(size); + for (size_t i = 0; i> features[i]; - string desc_name = voc.getDescName(); - cout << "voc desc name=" << desc_name << endl; - vector > features(argc - 3); - vector > scores; - vector filenames(argc - 3); - string outDir = argv[2]; - for (int i = 3; i < argc; ++i) - { - filenames[i - 3] = { argv[i] }; - } - for (int i = 0; i &features, Vocabulary &voc, vector > &scores, vector &filenames, string outDir) +{ + + fbow::fBow vv, vv2; + int avgScore = 0; + int counter = 0; + auto t_start = std::chrono::high_resolution_clock::now(); + for (int i = 0; i score; + for (int j = 0; j score; - for (int j = 0; j 0.01f) - { - score.insert(pair(score1, j)); - } - printf("%f, ", score1); + vv2 = voc.transform(features[j]); + double score1 = vv.score(vv, vv2); + counter++; + // if(score1 > 0.01f) + { + score.insert(pair(score1, j)); } - printf("\n"); - scores.push_back(score); + printf("%f, ", score1); } - auto t_end = std::chrono::high_resolution_clock::now(); - avgScore += double(std::chrono::duration_cast(t_end - t_start).count()); + printf("\n"); + scores.push_back(score); + } + auto t_end = std::chrono::high_resolution_clock::now(); + avgScore += double(std::chrono::duration_cast(t_end - t_start).count()); - std::string command; - int j = 0; - for (int i = 0; i < scores.size(); i++) + std::string command; + int j = 0; + for (int i = 0; i < scores.size(); i++) + { + std::stringstream str; + + command = string("cd ") + outDir + string("&"); + command += "mkdir "; + str << i; + command += str.str(); + command += ""; + system(command.c_str()); + + command = "cd " + outDir + "&"; +#ifdef WIN32 + command += "copy "; +#else + command += "cp "; +#endif + command += filenames[i]; + command += " "; + command += str.str(); + command += "\\source.JPG"; + + system(command.c_str()); + std::cout << command << std::endl; + j = 0; + for (auto it = scores[i].begin(); it != scores[i].end(); it++) { - std::stringstream str; - - command = "mkdir "; - str << i; - command += str.str(); - command += "/"; - system(command.c_str()); - - command = "cp "; - command += filenames[i]; + ++j; + std::stringstream str2; + command = string("cd ") + outDir + string("&"); +#ifdef WIN32 + command += "copy "; +#else + command += "cp "; +#endif + command += filenames[it->second]; command += " "; command += str.str(); - command += "/source.JPG"; - - system((string("cd ") + outDir).c_str()); + command += "\\"; + str2 << j << "-"; + str2 << it->first; + command += str2.str(); + command += ".JPG"; system(command.c_str()); - j = 0; - for (auto it = scores[i].begin(); it != scores[i].end(); it++) - { - ++j; - std::stringstream str2; - command = "cp "; - command += filenames[it->second]; - command += " "; - command += str.str(); - command += "/"; - str2 << j << "-"; - str2 << it->first; - command += str2.str(); - command += ".JPG"; - system(command.c_str()); - } + std::cout << command << std::endl; + } + } + /* + { + cout<first<<" "<second<first<<" "<second< filenames; + string outDir = argv[3]; + for (int i = 4; i < argc; ++i) { - cout<first<<" "<second<first<<" "<second< > scores; + ImageMatching(features, voc, scores, filenames, outDir); + } catch (std::exception &ex) { cerr << ex.what() << endl; } + return 0; } From eb2bd234ae08d49ffd4d741114307f06cc324bfa Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Thu, 14 Jun 2018 09:54:03 +0200 Subject: [PATCH 08/12] Fbow score function --- src/fbow.cpp | 104 ++++++++++++++++++++++++++------------------------- src/fbow.h | 51 ++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 52 deletions(-) diff --git a/src/fbow.cpp b/src/fbow.cpp index 7fd8009..9a87315 100644 --- a/src/fbow.cpp +++ b/src/fbow.cpp @@ -142,22 +142,22 @@ void Vocabulary::saveToFile(const std::string &filepath)throw(std::exception){ ///save/load to binary streams void Vocabulary::toStream(std::ostream &str)const{ //magic number - uint64_t sig=55824124; + int sig=55824124; str.write((char*)&sig,sizeof(sig)); //save string str.write((char*)&_params,sizeof(params)); str.write(_data,_params._total_size); + } void Vocabulary::fromStream(std::istream &str)throw(std::exception) { if (_data!=0) free (_data); - uint64_t sig; + int sig; str.read((char*)&sig,sizeof(sig)); if (sig!=55824124) throw std::runtime_error("Vocabulary::fromStream invalid signature"); //read string str.read((char*)&_params,sizeof(params)); - #if _WIN32 _data = (char*)_aligned_malloc(_params._total_size, _params._aligment); #else @@ -166,57 +166,59 @@ void Vocabulary::fromStream(std::istream &str)throw(std::exception) if (_data==0) throw std::runtime_error("Vocabulary::fromStream Could not allocate data"); str.read(_data,_params._total_size); + } -double fBow::score(const fBow &v1,const fBow &v2){ - - - fBow::const_iterator v1_it, v2_it; - const fBow::const_iterator v1_end = v1.end(); - const fBow::const_iterator v2_end = v2.end(); - - v1_it = v1.begin(); - v2_it = v2.begin(); - - double score = 0; - - while(v1_it != v1_end && v2_it != v2_end) - { - const auto& vi = v1_it->second; - const auto& wi = v2_it->second; +//double fBow::score(const fBow &v1,const fBow &v2){ +// +// +// fBow::const_iterator v1_it, v2_it; +// const fBow::const_iterator v1_end = v1.end(); +// const fBow::const_iterator v2_end = v2.end(); +// +// v1_it = v1.begin(); +// v2_it = v2.begin(); +// +// double score = 0; +// +// while(v1_it != v1_end && v2_it != v2_end) +// { +// const auto& vi = v1_it->second; +// const auto& wi = v2_it->second; +// +// if(v1_it->first == v2_it->first) +// { +// score += vi * wi; +// +// // move v1 and v2 forward +// ++v1_it; +// ++v2_it; +// } +// else if(v1_it->first < v2_it->first) +// { +// // move v1 forward +// v1_it = v1.lower_bound(v2_it->first); +// // v1_it = (first element >= v2_it.id) +// } +// else +// { +// // move v2 forward +// v2_it = v2.lower_bound(v1_it->first); +// // v2_it = (first element >= v1_it.id) +// } +// } +// +// // ||v - w||_{L2} = sqrt( 2 - 2 * Sum(v_i * w_i) ) +// // for all i | v_i != 0 and w_i != 0 ) +// // (Nister, 2006) +// if(score >= 1) // rounding errors +// score = 1.0; +// else +// score = 1.0 - sqrt(1.0 - score); // [0..1] +// +// return score; +//} - if(v1_it->first == v2_it->first) - { - score += vi * wi; - - // move v1 and v2 forward - ++v1_it; - ++v2_it; - } - else if(v1_it->first < v2_it->first) - { - // move v1 forward - v1_it = v1.lower_bound(v2_it->first); - // v1_it = (first element >= v2_it.id) - } - else - { - // move v2 forward - v2_it = v2.lower_bound(v1_it->first); - // v2_it = (first element >= v1_it.id) - } - } - - // ||v - w||_{L2} = sqrt( 2 - 2 * Sum(v_i * w_i) ) - // for all i | v_i != 0 and w_i != 0 ) - // (Nister, 2006) - if(score >= 1) // rounding errors - score = 1.0; - else - score = 1.0 - sqrt(1.0 - score); // [0..1] - - return score; -} uint64_t fBow::hash()const{ uint64_t seed = 0; for(auto e:*this) diff --git a/src/fbow.h b/src/fbow.h index b0a36e2..e2d6c17 100644 --- a/src/fbow.h +++ b/src/fbow.h @@ -40,8 +40,57 @@ struct fBow:std::map{ //returns a hash identifying this uint64_t hash()const; +public: //returns the similitude score between to image descriptors using L2 norm - static double score(const fBow &v1, const fBow &v2); + double score(const fBow &v1, const fBow &v2) { + + + fBow::const_iterator v1_it, v2_it; + const fBow::const_iterator v1_end = v1.end(); + const fBow::const_iterator v2_end = v2.end(); + + v1_it = v1.begin(); + v2_it = v2.begin(); + + double score = 0; + + while (v1_it != v1_end && v2_it != v2_end) + { + const auto& vi = v1_it->second; + const auto& wi = v2_it->second; + + if (v1_it->first == v2_it->first) + { + score += vi * wi; + + // move v1 and v2 forward + ++v1_it; + ++v2_it; + } + else if (v1_it->first < v2_it->first) + { + // move v1 forward + v1_it = v1.lower_bound(v2_it->first); + // v1_it = (first element >= v2_it.id) + } + else + { + // move v2 forward + v2_it = v2.lower_bound(v1_it->first); + // v2_it = (first element >= v1_it.id) + } + } + + // ||v - w||_{L2} = sqrt( 2 - 2 * Sum(v_i * w_i) ) + // for all i | v_i != 0 and w_i != 0 ) + // (Nister, 2006) + if (score >= 1) // rounding errors + score = 1.0; + else + score = 1.0 - sqrt(1.0 - score); // [0..1] + + return score; + } }; From 0d980f2787c7d0cb9ec89ea86588fa4affd36c62 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Thu, 14 Jun 2018 11:23:24 +0200 Subject: [PATCH 09/12] Store MatchingMatrix --- ImageMatching.py | 40 ++++++++++++++---------------- utils/fbow_create_voc_step0.cpp | 17 ++++++++++++- utils/image_matching.cpp | 44 +++++++++++++++++++++++---------- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/ImageMatching.py b/ImageMatching.py index cac0053..35bf7be 100644 --- a/ImageMatching.py +++ b/ImageMatching.py @@ -1,42 +1,40 @@ from os import walk import os - +import subprocess +#in order to use this script: +#1. Prepare a database +#2. Compile the code +#3. Create a directory for the results +#4. Set the configurations below +#5. Run this script by the following command +# python ImageMatching.py #---------------Configs--------------------- DBDIR = "" #the dir where images reside e.g. C:/database DBNAME = "" #e.g. database (in the line above) CODEDIR = "" #e.g. H:/fbow-windows/build/bin/Release -DESCRIPTOR = "akaze" +DESCRIPTOR = "akaze" #orb, surf RESULTSDIR = ""#e.g. "C:/FBoWResults" OS = "Windows" # or "LinuxBase" #----------------Path Setting--------------- Extension = ".exe" if OS == "Windows" else "" ENDCMD = "&" if OS == "Windows" else ";" -OUTPUT = RESULTSDIR + "/" + DESCRIPTOR + DBNAME +OUTPUT = RESULTSDIR + "\\" + DESCRIPTOR + DBNAME MKDIRCMD = "mkdir " + OUTPUT +MatchMatrixFile = OUTPUT + "\\" + "MatchingMatrix.txt" #---------------Commands-------------------- -FeaturesExtractCmd = CODEDIR + "/" + "fbow_create_voc_step0" + Extension + " " + DESCRIPTOR + " " + OUTPUT + "/features.yml" -VocabCreateCmd = CODEDIR + "/" + "fbow_create_voc_step1" + Extension + " " + OUTPUT + "/features.yml " + OUTPUT + "/out.fbow" -ImageMatchingCmd = CODEDIR + "/" + "image_matching" + Extension + " " + OUTPUT + "/out.fbow " + OUTPUT + " " - -#---------------List Images----------------- -imagesFileName = "" -i = 1 -for (dirpath, dirnames, filenames) in walk(DBDIR): - filenames.sort() - for filename in filenames: - imagesFileName += " " + DBDIR + "/" + filename - break -FeaturesExtractCmd += imagesFileName -ImageMatchingCmd += imagesFileName +FeaturesExtractCmd = CODEDIR + "\\" + "fbow_create_voc_step0" + Extension + " " + DESCRIPTOR + " " + OUTPUT + "\\features.yml " + DBDIR +VocabCreateCmd = CODEDIR + "\\" + "fbow_create_voc_step1" + Extension + " " + OUTPUT + "\\features.yml " + OUTPUT + "\\out.fbow" +ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + OUTPUT + "\\features.yml " + OUTPUT + "\\out.fbow " + OUTPUT + " " + DBDIR + " " + MatchMatrixFile #---------------Run Commands---------------- print("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) os.system("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) print(FeaturesExtractCmd) -os.system(FeaturesExtractCmd) -print(VocabCreateCmd) -os.system(VocabCreateCmd) +result = subprocess.check_output(FeaturesExtractCmd, shell=True) +print(result) + print(ImageMatchingCmd) -os.system(ImageMatchingCmd) \ No newline at end of file +result = subprocess.check_output(ImageMatchingCmd, shell=True) +print(result) \ No newline at end of file diff --git a/utils/fbow_create_voc_step0.cpp b/utils/fbow_create_voc_step0.cpp index a8f205f..bbf8faf 100644 --- a/utils/fbow_create_voc_step0.cpp +++ b/utils/fbow_create_voc_step0.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "fbow.h" // OpenCV @@ -132,6 +133,19 @@ void saveToYMLFile(string filename, const vector &features, string des } // ---------------------------------------------------------------------------- +vector ListFilenames(string dbPath) +{ + namespace fs = std::experimental::filesystem; + vector filenames; + for (auto & p : fs::directory_iterator(dbPath)) + { + stringstream str; + str << p; + filenames.push_back(str.str()); + + } + return filenames; +} int main(int argc,char **argv) { @@ -146,7 +160,8 @@ int main(int argc,char **argv) string descriptor=argv[1]; string output=argv[2]; - auto images=readImagePaths(argc,argv,3); + auto images = ListFilenames(argv[3]); + //auto images=readImagePaths(argc,argv,3); vector< cv::Mat > features= loadFeatures(images,descriptor); //save features to file diff --git a/utils/image_matching.cpp b/utils/image_matching.cpp index 9857b2d..956515b 100644 --- a/utils/image_matching.cpp +++ b/utils/image_matching.cpp @@ -1,7 +1,7 @@ #include #include #include - +#include // #include "vocabulary_creator.h" // OpenCV @@ -62,13 +62,16 @@ vector readFeaturesFromYMLFile(string filename, std::string &desc_name) } // ---------------------------------------------------------------------------- -void ImageMatching(vector &features, Vocabulary &voc, vector > &scores, vector &filenames, string outDir) +void ImageMatching(vector &features, Vocabulary &voc, vector > &scores, vector &filenames, string outDir, string MatchMatrixFile) { fbow::fBow vv, vv2; int avgScore = 0; int counter = 0; auto t_start = std::chrono::high_resolution_clock::now(); + ofstream fstr(MatchMatrixFile); + if (fstr.is_open() == false) {std::cerr << " error openning file : " << MatchMatrixFile << endl;} + stringstream sstr; for (int i = 0; i &features, Vocabulary &voc, vector(score1, j)); } - printf("%f, ", score1); + fstr << score1 << "\t"; } - printf("\n"); + fstr << endl; scores.push_back(score); } + fstr.close(); auto t_end = std::chrono::high_resolution_clock::now(); avgScore += double(std::chrono::duration_cast(t_end - t_start).count()); @@ -149,6 +153,21 @@ void ImageMatching(vector &features, Vocabulary &voc, vector ListFilenames(string dbPath) +{ + namespace fs = std::experimental::filesystem; + vector filenames; + for (auto & p : fs::directory_iterator(dbPath)) + { + stringstream str; + str << p; + filenames.push_back(str.str()); + + } + return filenames; +} + int main(int argc, char **argv) { @@ -161,8 +180,14 @@ int main(int argc, char **argv) string desc_name; - auto features = readFeaturesFromYMLFile(argv[1], desc_name); + string outDir = argv[3]; + string DBDir = argv[4]; + string MatchMatrixFile = argv[5]; + vector filenames; + + filenames = ListFilenames(DBDir); + auto features = readFeaturesFromYMLFile(argv[1], desc_name); cout << "DescName=" << desc_name << endl; const int k = stoi(cml("-k", "10")); const int L = stoi(cml("-l", "6")); @@ -179,15 +204,8 @@ int main(int argc, char **argv) cerr << "Saving " << argv[2] << endl; voc.saveToFile(argv[2]); - vector filenames; - string outDir = argv[3]; - for (int i = 4; i < argc; ++i) - { - filenames.push_back(argv[i]); - } - vector > scores; - ImageMatching(features, voc, scores, filenames, outDir); + ImageMatching(features, voc, scores, filenames, outDir, MatchMatrixFile); } catch (std::exception &ex) { From 388984b627a42dfa61f34d0da17d75db11c192fa Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Sat, 16 Jun 2018 09:51:21 +0200 Subject: [PATCH 10/12] Serial function call (temporary) --- ImageMatching.py | 22 ++++++--- utils/image_matching.cpp | 104 ++++++++++++++++++++++++++++++--------- 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/ImageMatching.py b/ImageMatching.py index 35bf7be..c7e416f 100644 --- a/ImageMatching.py +++ b/ImageMatching.py @@ -24,17 +24,23 @@ MatchMatrixFile = OUTPUT + "\\" + "MatchingMatrix.txt" #---------------Commands-------------------- -FeaturesExtractCmd = CODEDIR + "\\" + "fbow_create_voc_step0" + Extension + " " + DESCRIPTOR + " " + OUTPUT + "\\features.yml " + DBDIR -VocabCreateCmd = CODEDIR + "\\" + "fbow_create_voc_step1" + Extension + " " + OUTPUT + "\\features.yml " + OUTPUT + "\\out.fbow" -ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + OUTPUT + "\\features.yml " + OUTPUT + "\\out.fbow " + OUTPUT + " " + DBDIR + " " + MatchMatrixFile +FeaturesExtractCmd = CODEDIR + "\\" + "fbow_create_voc_step0" + Extension + " " + DESCRIPTOR + " " + OUTPUT + "\\features " + DBDIR +VocabCreateCmd = CODEDIR + "\\" + "fbow_create_voc_step1" + Extension + " " + OUTPUT + "\\features " + OUTPUT + "\\out.fbow" +#ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + OUTPUT + "\\features " + OUTPUT + "\\out.fbow " + OUTPUT + " " + DBDIR + " " + MatchMatrixFile +ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + DESCRIPTOR + " " + DBDIR + " " + MatchMatrixFile + " " + OUTPUT #---------------Run Commands---------------- print("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) +print("\n") os.system("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) -print(FeaturesExtractCmd) -result = subprocess.check_output(FeaturesExtractCmd, shell=True) -print(result) +print("\n") + +# print(FeaturesExtractCmd) +# print("\n") +# os.system(FeaturesExtractCmd) +# print("\n") print(ImageMatchingCmd) -result = subprocess.check_output(ImageMatchingCmd, shell=True) -print(result) \ No newline at end of file +print("\n") +os.system(ImageMatchingCmd) +print("\n") \ No newline at end of file diff --git a/utils/image_matching.cpp b/utils/image_matching.cpp index 956515b..d07ea7d 100644 --- a/utils/image_matching.cpp +++ b/utils/image_matching.cpp @@ -3,6 +3,14 @@ #include #include // +#include +#include +#include +#ifdef USE_CONTRIB +#include +#include +#endif + #include "vocabulary_creator.h" // OpenCV #include @@ -19,7 +27,7 @@ vector readFeaturesFromFile(string filename, std::string &desc_name) { //test it is not created std::ifstream ifile(filename); if (!ifile.is_open()) { cerr << "could not open input file" << endl; exit(0); } - + char _desc_name[20]; ifile.read(_desc_name, 20); @@ -27,9 +35,12 @@ vector readFeaturesFromFile(string filename, std::string &desc_name) { uint32_t size; ifile.read((char*)&size, sizeof(size)); + ifile.close(); features.resize(size); for (size_t i = 0; i readFeaturesFromFile(string filename, std::string &desc_name) { ifile.read((char*)&type, sizeof(type)); features[i].create(rows, cols, type); ifile.read((char*)features[i].ptr(0), features[i].total()*features[i].elemSize()); + ifile.close(); } return features; } @@ -167,7 +179,40 @@ vector ListFilenames(string dbPath) } return filenames; } +//------------------------------------------------------------------------------- +vector< cv::Mat > loadFeatures(vector path_to_images, string descriptor = "") throw (exception) { + //select detector + cv::Ptr fdetector; + if (descriptor == "orb") fdetector = cv::ORB::create(2000); + else if (descriptor == "brisk") fdetector = cv::BRISK::create(); +#ifdef OPENCV_VERSION_3 + else if (descriptor == "akaze") fdetector = cv::AKAZE::create(cv::AKAZE::DESCRIPTOR_MLDB, 0, 3, 1e-4); +#endif +#ifdef USE_CONTRIB + else if (descriptor == "surf") fdetector = cv::xfeatures2d::SURF::create(15, 4, 2); +#endif + + else throw runtime_error("Invalid descriptor"); + assert(!descriptor.empty()); + vector features; + + cout << "Extracting features..." << endl; + for (size_t i = 0; i < path_to_images.size(); ++i) + { + vector keypoints; + cv::Mat descriptors; + cout << "reading image: " << path_to_images[i] << endl; + cv::Mat image = cv::imread(path_to_images[i], 0); + if (image.empty())throw runtime_error("Could not open image" + path_to_images[i]); + cout << "extracting features" << endl; + fdetector->detectAndCompute(image, cv::Mat(), keypoints, descriptors); + cout << path_to_images[i] << " : " << descriptors.rows << endl; + features.push_back(descriptors); + cout << "done detecting features" << endl; + } + return features; +} int main(int argc, char **argv) { @@ -179,33 +224,48 @@ int main(int argc, char **argv) } - string desc_name; - string outDir = argv[3]; - string DBDir = argv[4]; - string MatchMatrixFile = argv[5]; - vector filenames; + //string desc_name; + //string outDir = argv[3]; + //string DBDir = argv[4]; + //string MatchMatrixFile = argv[5]; + //vector filenames; + + //filenames = ListFilenames(DBDir); - filenames = ListFilenames(DBDir); + ////auto features = readFeaturesFromYMLFile(argv[1], desc_name); + //auto features = readFeaturesFromFile(argv[1], desc_name); + //cout << "DescName=" << desc_name << endl; + //const int k = stoi(cml("-k", "10")); + //const int L = stoi(cml("-l", "6")); + //const int nThreads = stoi(cml("-t", "1")); + //srand(0); + //fbow::VocabularyCreator voc_creator; + //fbow::Vocabulary voc; + //cout << "Creating a " << k << "^" << L << " vocabulary..." << endl; + //auto t_start = std::chrono::high_resolution_clock::now(); + //voc_creator.create(voc, features, desc_name, fbow::VocabularyCreator::Params(k, L, nThreads)); + //auto t_end = std::chrono::high_resolution_clock::now(); + //cout << "time=" << double(std::chrono::duration_cast(t_end - t_start).count()) << " msecs" << endl; + //cout << "vocabulary size : " << voc.size() << endl; + //cerr << "Saving " << argv[2] << endl; + //voc.saveToFile(argv[2]); - auto features = readFeaturesFromYMLFile(argv[1], desc_name); - cout << "DescName=" << desc_name << endl; + //akaze DBadress Matrix output + string descriptor = argv[1]; + string MatchMatrixFile = argv[3]; + string outDir = argv[4]; + fbow::Vocabulary voc; + fbow::VocabularyCreator voc_creator; const int k = stoi(cml("-k", "10")); const int L = stoi(cml("-l", "6")); const int nThreads = stoi(cml("-t", "1")); - srand(0); - fbow::VocabularyCreator voc_creator; - fbow::Vocabulary voc; - cout << "Creating a " << k << "^" << L << " vocabulary..." << endl; - auto t_start = std::chrono::high_resolution_clock::now(); - voc_creator.create(voc, features, desc_name, fbow::VocabularyCreator::Params(k, L, nThreads)); - auto t_end = std::chrono::high_resolution_clock::now(); - cout << "time=" << double(std::chrono::duration_cast(t_end - t_start).count()) << " msecs" << endl; - cout << "vocabulary size : " << voc.size() << endl; - cerr << "Saving " << argv[2] << endl; - voc.saveToFile(argv[2]); + auto images = ListFilenames(argv[2]); + //auto images=readImagePaths(argc,argv,3); + vector< cv::Mat > features = loadFeatures(images, descriptor); + voc_creator.create(voc, features, descriptor, fbow::VocabularyCreator::Params(k, L, nThreads)); vector > scores; - ImageMatching(features, voc, scores, filenames, outDir, MatchMatrixFile); + ImageMatching(features, voc, scores, images, outDir, MatchMatrixFile); } catch (std::exception &ex) { From 2813efe000c4b6ac4f5c6a69a2178ca4fa101cb9 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Wed, 20 Jun 2018 13:03:27 +0200 Subject: [PATCH 11/12] Bugfix: read/write binary files --- ImageMatching.py | 11 +++--- utils/fbow_create_voc_step0.cpp | 25 ++++++++---- utils/image_matching.cpp | 68 ++++++++++++++++++++++++++++----- 3 files changed, 81 insertions(+), 23 deletions(-) diff --git a/ImageMatching.py b/ImageMatching.py index c7e416f..66160b0 100644 --- a/ImageMatching.py +++ b/ImageMatching.py @@ -26,8 +26,7 @@ #---------------Commands-------------------- FeaturesExtractCmd = CODEDIR + "\\" + "fbow_create_voc_step0" + Extension + " " + DESCRIPTOR + " " + OUTPUT + "\\features " + DBDIR VocabCreateCmd = CODEDIR + "\\" + "fbow_create_voc_step1" + Extension + " " + OUTPUT + "\\features " + OUTPUT + "\\out.fbow" -#ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + OUTPUT + "\\features " + OUTPUT + "\\out.fbow " + OUTPUT + " " + DBDIR + " " + MatchMatrixFile -ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + DESCRIPTOR + " " + DBDIR + " " + MatchMatrixFile + " " + OUTPUT +ImageMatchingCmd = CODEDIR + "\\" + "image_matching" + Extension + " " + OUTPUT + "\\features " + DBDIR + " " + MatchMatrixFile + " " + OUTPUT #---------------Run Commands---------------- print("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) @@ -35,10 +34,10 @@ os.system("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME) print("\n") -# print(FeaturesExtractCmd) -# print("\n") -# os.system(FeaturesExtractCmd) -# print("\n") +print(FeaturesExtractCmd) +print("\n") +os.system(FeaturesExtractCmd) +print("\n") print(ImageMatchingCmd) print("\n") diff --git a/utils/fbow_create_voc_step0.cpp b/utils/fbow_create_voc_step0.cpp index bbf8faf..a876495 100644 --- a/utils/fbow_create_voc_step0.cpp +++ b/utils/fbow_create_voc_step0.cpp @@ -80,8 +80,10 @@ void saveToFile(string filename, const vector &features, string desc_n fstream ifile(filename); if (ifile.is_open())//read size and rewrite runtime_error("ERROR::: Output File " + filename + " already exists!!!!!"); + ifile.close(); } - ofstream ofile(filename); + + ofstream ofile(filename, ios_base::binary); if (!ofile.is_open()) { cerr << "could not open output file" << endl; exit(0); } char _desc_name[20]; @@ -91,16 +93,23 @@ void saveToFile(string filename, const vector &features, string desc_n uint32_t size = features.size(); ofile.write((char*)&size, sizeof(size)); + ofile.close(); + int i = 0; for (auto &f : features) { + stringstream str; + str << i; + ofstream ffile(filename + str.str(), ios_base::binary); if (!f.isContinuous()) { cerr << "Matrices should be continuous" << endl; exit(0); } - uint32_t aux = f.cols; ofile.write((char*)&aux, sizeof(aux)); - cout << "i : " << i++ << "rows : " << f.rows << endl; - aux = f.rows; ofile.write((char*)&aux, sizeof(aux)); - aux = f.type(); ofile.write((char*)&aux, sizeof(aux)); - ofile.write((char*)f.ptr(0), f.total()*f.elemSize()); + uint32_t aux = f.cols; ffile.write((char*)&aux, sizeof(aux)); + aux = f.rows; ffile.write((char*)&aux, sizeof(aux)); + aux = f.type(); ffile.write((char*)&aux, sizeof(aux)); + ffile.write((char*)f.data, f.total()*f.elemSize()); + + ffile.close(); + i++; } } @@ -165,8 +174,8 @@ int main(int argc,char **argv) vector< cv::Mat > features= loadFeatures(images,descriptor); //save features to file - saveToYMLFile(argv[2],features,descriptor); - + //saveToYMLFile(argv[2],features,descriptor); + saveToFile(argv[2], features, descriptor); }catch(exception &ex){ cerr< readFeaturesFromFile(string filename, std::string &desc_name) { vector features; //test it is not created - std::ifstream ifile(filename); + std::ifstream ifile(filename, ios_base::binary); if (!ifile.is_open()) { cerr << "could not open input file" << endl; exit(0); } @@ -37,17 +37,20 @@ vector readFeaturesFromFile(string filename, std::string &desc_name) { ifile.read((char*)&size, sizeof(size)); ifile.close(); features.resize(size); + vector > tmp; + tmp.resize(size); for (size_t i = 0; i(0), features[i].total()*features[i].elemSize()); + ifile.read((char*)features[i].data, features[i].total() * features[i].elemSize()); ifile.close(); } return features; @@ -213,6 +216,49 @@ vector< cv::Mat > loadFeatures(vector path_to_images, string descripto } return features; } + +// ---------------------------------------------------------------------------- +void saveToFile(string filename, const vector &features, string desc_name, bool rewrite = true)throw (exception) { + + //test it is not created + if (!rewrite) { + fstream ifile(filename); + if (ifile.is_open())//read size and rewrite + runtime_error("ERROR::: Output File " + filename + " already exists!!!!!"); + ifile.close(); + } + + ofstream ofile(filename, ios_base::binary); + if (!ofile.is_open()) { cerr << "could not open output file" << endl; exit(0); } + + char _desc_name[20]; + desc_name.resize(min(size_t(19), desc_name.size())); + strcpy(_desc_name, desc_name.c_str()); + ofile.write(_desc_name, 20); + + uint32_t size = features.size(); + ofile.write((char*)&size, sizeof(size)); + ofile.close(); + + int i = 0; + for (auto &f : features) { + stringstream str; + str << i; + ofstream ffile(filename + str.str(), ios_base::binary); + if (!f.isContinuous()) { + cerr << "Matrices should be continuous" << endl; exit(0); + } + uint32_t aux = f.cols; ffile.write((char*)&aux, sizeof(aux)); + aux = f.rows; ffile.write((char*)&aux, sizeof(aux)); + aux = f.type(); ffile.write((char*)&aux, sizeof(aux)); + ffile.write((char*)f.data, f.total()*f.elemSize()); + + ffile.close(); + i++; + } +} + + int main(int argc, char **argv) { @@ -251,9 +297,9 @@ int main(int argc, char **argv) //voc.saveToFile(argv[2]); //akaze DBadress Matrix output - string descriptor = argv[1]; - string MatchMatrixFile = argv[3]; - string outDir = argv[4]; + string descriptor; + string outDir = argv[3]; + string MatchMatrixFile = argv[4]; fbow::Vocabulary voc; fbow::VocabularyCreator voc_creator; const int k = stoi(cml("-k", "10")); @@ -262,10 +308,14 @@ int main(int argc, char **argv) auto images = ListFilenames(argv[2]); //auto images=readImagePaths(argc,argv,3); - vector< cv::Mat > features = loadFeatures(images, descriptor); + //vector features = loadFeatures(images, descriptor); + //saveToFile(argv[2], features, descriptor); + vector features = readFeaturesFromFile(argv[1], descriptor); + voc_creator.create(voc, features, descriptor, fbow::VocabularyCreator::Params(k, L, nThreads)); vector > scores; ImageMatching(features, voc, scores, images, outDir, MatchMatrixFile); + } catch (std::exception &ex) { From 4cdf019ccef0196bf64d5104d4d88a7b47cb3aad Mon Sep 17 00:00:00 2001 From: Mohammad Shafiei Date: Wed, 20 Jun 2018 15:59:10 +0200 Subject: [PATCH 12/12] Bugfix: arguments read --- utils/image_matching.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/image_matching.cpp b/utils/image_matching.cpp index e254d8c..4604284 100644 --- a/utils/image_matching.cpp +++ b/utils/image_matching.cpp @@ -298,8 +298,8 @@ int main(int argc, char **argv) //akaze DBadress Matrix output string descriptor; - string outDir = argv[3]; - string MatchMatrixFile = argv[4]; + string MatchMatrixFile = argv[3]; + string outDir = argv[4]; fbow::Vocabulary voc; fbow::VocabularyCreator voc_creator; const int k = stoi(cml("-k", "10"));