Skip to content
45 changes: 45 additions & 0 deletions ImageMatching.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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" #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
MKDIRCMD = "mkdir " + OUTPUT
MatchMatrixFile = OUTPUT + "\\" + "MatchingMatrix.txt"

#---------------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 " + DBDIR + " " + MatchMatrixFile + " " + OUTPUT

#---------------Run Commands----------------
print("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME)
print("\n")
os.system("cd " + RESULTSDIR + " " + ENDCMD + " " + "mkdir " + DESCRIPTOR + DBNAME)
print("\n")

print(FeaturesExtractCmd)
print("\n")
os.system(FeaturesExtractCmd)
print("\n")

print(ImageMatchingCmd)
print("\n")
os.system(ImageMatchingCmd)
print("\n")
13 changes: 8 additions & 5 deletions src/cpu_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -50,15 +54,16 @@ BOOL IsWow64()
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) return FALSE;
return bIsWow64 ;
}
#endif

bool cpu_x86::cpu_x86::detect_OS_x64(){
#ifdef _M_X64
return true;
#else
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;}
Expand Down Expand Up @@ -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
122 changes: 70 additions & 52 deletions src/fbow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}


Expand Down Expand Up @@ -45,7 +51,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._total_size, _params._aligment);
#else
_data=(char*)aligned_alloc(_params._aligment,_params._total_size);
#endif
memset( _data,0,_params._total_size);

}
Expand Down Expand Up @@ -132,75 +142,83 @@ 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));
_data=(char*)aligned_alloc(_params._aligment,_params._total_size);
#if _WIN32
_data = (char*)_aligned_malloc(_params._total_size, _params._aligment);
#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);

}

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)
Expand Down
68 changes: 65 additions & 3 deletions src/fbow.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,57 @@ struct fBow:std::map<uint32_t,_float>{

//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;
}

};

Expand Down Expand Up @@ -183,14 +232,27 @@ 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;
_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(_nwords * sizeof(register_type), aligment);
#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);}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cpu_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Loading