28 #include <opencv2/core/core.hpp> 29 #include <opencv2/core/types_c.h> 30 #include <opencv2/highgui/highgui_c.h> 31 #include <opencv2/imgproc/imgproc_c.h> 32 #include <opencv2/flann/miniflann.hpp> 33 #include <opencv2/features2d/features2d.hpp> 34 #include <opencv2/nonfree/features2d.hpp> 49 "vocabularyComparison.exe \"dictionary/path\"\n" 50 " Dictionary path example: \"data/Dictionary49k.txt\"" 51 " Note that 400 first descriptors in the file are used as queries.\n");
55 int main(
int argc,
char * argv[])
64 std::string dictionaryPath = argv[argc-1];
65 std::list<std::vector<float> > objectDescriptors;
67 std::map<int, std::vector<float> > descriptors;
70 int objectDescriptorsSize= 400;
73 if(!dictionaryPath.empty())
75 file.open(dictionaryPath.c_str(), std::ifstream::in);
79 UDEBUG(
"Loading the dictionary from \"%s\"", dictionaryPath.c_str());
83 std::list<std::string> strList;
84 std::getline(file, str);
86 for(std::list<std::string>::iterator iter = strList.begin(); iter != strList.end(); ++iter)
90 dimension = std::atoi(iter->c_str());
95 if(dimension == 0 || dimension > 1000)
97 UERROR(
"Invalid dictionary file, visual word dimension (%d) is not valid, \"%s\"", dimension, dictionaryPath.c_str());
101 int descriptorsLoaded = 0;
105 std::getline(file, str);
107 if((
int)strList.size() == dimension+1)
110 std::list<std::string>::iterator iter = strList.begin();
111 int id = atoi(iter->c_str());
114 std::vector<float> descriptor(dimension);
118 for(;i<dimension && iter != strList.end(); ++i, ++iter)
127 if(++descriptorsLoaded<=objectDescriptorsSize)
129 objectDescriptors.push_back(descriptor);
134 descriptors.insert(std::make_pair(
id, descriptor));
139 UWARN(
"Cannot parse line \"%s\"", str.c_str());
144 UDEBUG(
"Time loading dictionary = %fs, dimension=%d", timer.
ticks(), dimension);
148 UERROR(
"Cannot open dictionary file \"%s\"", dictionaryPath.c_str());
152 if(descriptors.size() && objectDescriptors.size() && dimension)
157 UDEBUG(
"Creating data structures...");
159 dataTree = cv::Mat((
int)descriptors.size(), dimension, CV_32F);
162 std::map<int, std::vector<float> >::const_iterator iter = descriptors.begin();
163 for(
unsigned int i=0; i < descriptors.size(); ++i, ++iter)
167 memcpy(dataTree.ptr<
float>(i), iter->second.data(), dimension*
sizeof(float));
173 queries = cv::Mat((
int)objectDescriptors.size(), dimension, CV_32F);
175 std::list<std::vector<float> >::const_iterator iter = objectDescriptors.begin();
176 for(
unsigned int i=0; i < objectDescriptors.size(); ++i, ++iter)
179 memcpy(queries.ptr<
float>(i), iter->data(), dimension*
sizeof(float));
185 UDEBUG(
"descriptors.size()=%d, objectDescriptorsSize=%d, copying data = %f s",descriptors.size(), objectDescriptors.size(), timer.
ticks());
187 UDEBUG(
"Creating indexes...");
189 UDEBUG(
"Time to create linearIndex = %f s", timer.
ticks());
192 UDEBUG(
"Time to create kdTreeIndex1 = %f s", timer.
ticks());
195 UDEBUG(
"Time to create kdTreeIndex4 = %f s", timer.
ticks());
198 UDEBUG(
"Time to create kMeansIndex = %f s", timer.
ticks());
201 UDEBUG(
"Time to create compositeIndex = %f s", timer.
ticks());
207 UDEBUG(
"Search indexes...");
209 cv::Mat results(queries.rows, k, CV_32SC1);
210 cv::Mat dists(queries.rows, k, CV_32FC1);
212 linearIndex->knnSearch(queries, results, dists, k);
214 cv::Mat transposedLinear = dists.t();
215 UDEBUG(
"Time to search linearIndex = %f s", timer.
ticks());
217 kdTreeIndex1->knnSearch(queries, results, dists, k);
219 cv::Mat transposed = dists.t();
220 UDEBUG(
"Time to search kdTreeIndex1 = %f s (size=%d, dist error(k1,k2)=(%f,%f))",
225 (
float*)transposedLinear.data,
226 transposedLinear.cols),
229 &transposedLinear.at<
float>(1,0),
230 transposedLinear.cols));
232 kdTreeIndex4->knnSearch(queries, results, dists, k);
234 transposed = dists.t();
235 UDEBUG(
"Time to search kdTreeIndex4 = %f s (size=%d, dist error(k1,k2)=(%f,%f))",
240 (
float*)transposedLinear.data,
241 transposedLinear.cols),
244 &transposedLinear.at<
float>(1,0),
245 transposedLinear.cols));
247 kMeansIndex->knnSearch(queries, results, dists, k);
249 transposed = dists.t();
250 UDEBUG(
"Time to search kMeansIndex = %f s (size=%d, dist error(k1,k2)=(%f,%f))",
255 (
float*)transposedLinear.data,
256 transposedLinear.cols),
259 &transposedLinear.at<
float>(1,0),
260 transposedLinear.cols));
262 compositeIndex->knnSearch(queries, results, dists, k);
264 transposed = dists.t();
265 UDEBUG(
"Time to search compositeIndex = %f s (size=%d, dist error(k1,k2)=(%f,%f))",
270 (
float*)transposedLinear.data,
271 transposedLinear.cols),
274 &transposedLinear.at<
float>(1,0),
275 transposedLinear.cols));
284 delete compositeIndex;
bool uIsDigit(const char c)
float UTILITE_EXP uStr2Float(const std::string &str)
Basic mathematics functions.
Some conversion functions.
static void setLevel(ULogger::Level level)
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
Wrappers of STL for convenient functions.
int main(int argc, char *argv[])
static void setType(Type type, const std::string &fileName=kDefaultLogFileName, bool append=true)
T uMeanSquaredError(const T *x, unsigned int sizeX, const T *y, unsigned int sizeY)
std::list< std::string > uSplitNumChar(const std::string &str)
ULogger class and convenient macros.