38 #include <opencv2/opencv_modules.hpp> 40 #if CV_MAJOR_VERSION < 3 41 #ifdef HAVE_OPENCV_GPU 42 #include <opencv2/gpu/gpu.hpp> 45 #include <opencv2/core/cuda.hpp> 46 #ifdef HAVE_OPENCV_CUDAFEATURES2D 47 #include <opencv2/cudafeatures2d.hpp> 64 _totalActiveReferences(0),
65 _incrementalDictionary(
Parameters::defaultKpIncrementalDictionary()),
66 _incrementalFlann(
Parameters::defaultKpIncrementalFlann()),
67 _rebalancingFactor(
Parameters::defaultKpFlannRebalancingFactor()),
68 _byteToFloat(
Parameters::defaultKpByteToFloat()),
70 _newDictionaryPath(
Parameters::defaultKpDictionaryPath()),
71 _newWordsComparedTogether(
Parameters::defaultKpNewWordsComparedTogether()),
73 useDistanceL1_(
false),
75 _strategy(kNNBruteForce)
89 ParametersMap::const_iterator iter;
100 if((iter=parameters.find(Parameters::kKpDictionaryPath())) != parameters.end())
104 if((iter=parameters.find(Parameters::kKpIncrementalDictionary())) != parameters.end())
106 incrementalDictionary =
uStr2Bool((*iter).second.c_str());
110 bool treeUpdated =
false;
111 if((iter=parameters.find(Parameters::kKpNNStrategy())) != parameters.end())
118 UINFO(
"KDTree: Binary to Float conversion approach has changed, re-initialize kd-tree.");
125 if(incrementalDictionary)
139 UWARN(
"Incremental dictionary set: already loaded visual words (%d) from the fixed dictionary will be included in the incremental one.",
_visualWords.size());
149 if(!dictionaryPath.empty())
154 UINFO(
"incremental=%d, oldPath=%s newPath=%s, visual words=%d",
159 UWARN(
"Loading fixed vocabulary \"%s\", this may take a while...", dictionaryPath.c_str());
161 if(driver->openConnection(dictionaryPath,
false))
163 driver->load(
this,
false);
166 iter->second->setSaved(
true);
169 driver->closeConnection(
false);
173 UERROR(
"Could not load dictionary from database %s", dictionaryPath.c_str());
179 UWARN(
"Loading fixed vocabulary \"%s\", this may take a while...", dictionaryPath.c_str());
181 file.open(dictionaryPath.c_str(), std::ifstream::in);
184 UDEBUG(
"Deleting old dictionary and loading the new one from \"%s\"", dictionaryPath.c_str());
189 std::list<std::string> strList;
190 std::getline(file, str);
193 for(std::list<std::string>::iterator iter = strList.begin(); iter != strList.end(); ++iter)
197 dimension = std::atoi(iter->c_str());
201 UDEBUG(
"descriptor dimension = %d", dimension);
203 if(dimension <= 0 || dimension > 1000)
205 UERROR(
"Invalid dictionary file, visual word dimension (%d) is not valid, \"%s\"", dimension, dictionaryPath.c_str());
212 std::getline(file, str);
214 if((
int)strList.size() == dimension+1)
217 std::list<std::string>::iterator iter = strList.begin();
218 int id = std::atoi(iter->c_str());
219 cv::Mat descriptor(1, dimension, CV_32F);
224 for(;i<dimension && iter != strList.end(); ++i, ++iter)
230 UERROR(
"Loaded word has not the same size (%d) than descriptor size previously detected (%d).", i, dimension);
239 else if(!str.empty())
241 UWARN(
"Cannot parse line \"%s\"", str.c_str());
252 UERROR(
"Cannot open dictionary file \"%s\"", dictionaryPath.c_str());
260 UWARN(
"No words loaded, cannot set a fixed dictionary.", (
int)
_visualWords.size());
273 UDEBUG(
"Dictionary \"%s\" already loaded...", dictionaryPath.c_str());
277 UERROR(
"Cannot change to a fixed dictionary if there are already words (%d) in the incremental one.",
_visualWords.size());
282 UWARN(
"Cannot change to fixed dictionary, %d words already loaded as incremental", (
int)
_visualWords.size());
294 #if CV_MAJOR_VERSION < 3 295 #ifdef HAVE_OPENCV_GPU 298 UERROR(
"Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");
304 UERROR(
"Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but OpenCV is not built with GPU/cuda module! Doing \"kNNBruteForce\" instead.");
309 #ifdef HAVE_OPENCV_CUDAFEATURES2D 312 UERROR(
"Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but no CUDA devices found! Doing \"kNNBruteForce\" instead.");
318 UERROR(
"Nearest neighobr strategy \"kNNBruteForceGPU\" chosen but OpenCV cudafeatures2d module is not found! Doing \"kNNBruteForce\" instead.");
326 UERROR(
"Nearest neighobr strategy \"%d\" chosen but this strategy cannot be used with a dictionary! Doing \"kNNBruteForce\" instead.");
336 UINFO(
"Nearest neighbor strategy has changed, re-initialize search tree.");
376 memoryUsage +=
_visualWords.size()*(
sizeof(int) +
_visualWords.rbegin()->second->getMemoryUsed() +
sizeof(std::map<int, VisualWord *>::iterator)) +
sizeof(std::map<int, VisualWord *>);
378 _visualWords.begin()->second->getDescriptor().type() == CV_8U &&
388 memoryUsage +=
_unusedWords.size()*(
sizeof(int) +
sizeof(
VisualWord *)+
sizeof(std::map<int, VisualWord *>::iterator)) +
sizeof(std::map<int, VisualWord *>);
390 memoryUsage +=
_mapIndexId.size() * (
sizeof(int)*2+
sizeof(std::map<int ,int>::iterator)) +
sizeof(std::map<int ,int>);
391 memoryUsage +=
_mapIdIndex.size() * (
sizeof(int)*2+
sizeof(std::map<int ,int>::iterator)) +
sizeof(std::map<int ,int>);
392 memoryUsage +=
_notIndexedWords.size() * (
sizeof(int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
393 memoryUsage +=
_removedIndexedWords.size() * (
sizeof(int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
402 cv::Mat descriptorsOut;
403 descriptorsIn.convertTo(descriptorsOut, CV_32F);
404 return descriptorsOut;
409 UASSERT(descriptorsIn.type() == CV_8UC1);
410 cv::Mat descriptorsOut(descriptorsIn.rows, descriptorsIn.cols*8, CV_32FC1);
411 for(
int i=0; i<descriptorsIn.rows; ++i)
413 const unsigned char * ptrIn = descriptorsIn.ptr(i);
414 float * ptrOut = descriptorsOut.ptr<
float>(i);
415 for(
int j=0; j<descriptorsIn.cols; ++j)
418 ptrOut[jo] = (ptrIn[j] & 1) == 1?1.0
f:0.0
f;
419 ptrOut[jo+1] = (ptrIn[j] & (1<<1)) != 0?1.0f:0.0f;
420 ptrOut[jo+2] = (ptrIn[j] & (1<<2)) != 0?1.0f:0.0f;
421 ptrOut[jo+3] = (ptrIn[j] & (1<<3)) != 0?1.0f:0.0f;
422 ptrOut[jo+4] = (ptrIn[j] & (1<<4)) != 0?1.0f:0.0f;
423 ptrOut[jo+5] = (ptrIn[j] & (1<<5)) != 0?1.0f:0.0f;
424 ptrOut[jo+6] = (ptrIn[j] & (1<<6)) != 0?1.0f:0.0f;
425 ptrOut[jo+7] = (ptrIn[j] & (1<<7)) != 0?1.0f:0.0f;
428 return descriptorsOut;
437 cv::Mat descriptorsOut;
438 descriptorsIn.convertTo(descriptorsOut, CV_8UC1);
439 return descriptorsOut;
444 UASSERT(descriptorsIn.type() == CV_32FC1 && descriptorsIn.cols % 8 == 0);
445 cv::Mat descriptorsOut(descriptorsIn.rows, descriptorsIn.cols/8, CV_8UC1);
446 for(
int i=0; i<descriptorsIn.rows; ++i)
448 const float * ptrIn = descriptorsIn.ptr<
float>(i);
449 unsigned char * ptrOut = descriptorsOut.ptr(i);
450 for(
int j=0; j<descriptorsOut.cols; ++j)
454 (
unsigned char)(ptrIn[jo] == 0?0:1) |
455 (ptrIn[jo+1] == 0?0:(1<<1)) |
456 (ptrIn[jo+2] == 0?0:(1<<2)) |
457 (ptrIn[jo+3] == 0?0:(1<<3)) |
458 (ptrIn[jo+4] == 0?0:(1<<4)) |
459 (ptrIn[jo+5] == 0?0:(1<<5)) |
460 (ptrIn[jo+6] == 0?0:(1<<6)) |
461 (ptrIn[jo+7] == 0?0:(1<<7));
464 return descriptorsOut;
531 UDEBUG(
"Building FLANN index...");
538 UASSERT_MSG(descriptor.type() == CV_32F,
"To use KdTree dictionary, float descriptors are required!");
542 UASSERT_MSG(descriptor.type() == CV_8U,
"To use LSH dictionary, binary descriptors are required!");
546 UFATAL(
"Not supposed to be here!");
549 UDEBUG(
"Building FLANN index... done!");
558 std::pair<std::map<int, int>::iterator,
bool> inserted;
559 inserted =
_mapIndexId.insert(std::pair<int, int>(index, w->
id()));
561 inserted =
_mapIdIndex.insert(std::pair<int, int>(w->
id(), index));
584 std::pair<std::map<int, int>::iterator,
bool> inserted =
_mapIdIndex.insert(std::pair<int, int>(w->
id(), i));
601 int dim =
_visualWords.begin()->second->getDescriptor().cols;
603 if(
_visualWords.begin()->second->getDescriptor().type() == CV_8U)
616 type =
_visualWords.begin()->second->getDescriptor().type();
621 type =
_visualWords.begin()->second->getDescriptor().type();
624 UASSERT(type == CV_32F || type == CV_8U);
629 std::map<int, VisualWord*>::const_iterator iter =
_visualWords.begin();
630 for(
unsigned int i=0; i <
_visualWords.size(); ++i, ++iter)
633 if(iter->second->getDescriptor().type() == CV_8U)
641 descriptor = iter->second->getDescriptor();
646 descriptor = iter->second->getDescriptor();
649 UASSERT_MSG(descriptor.type() == type,
uFormat(
"%d vs %d", descriptor.type(), type).c_str());
650 UASSERT_MSG(descriptor.cols == dim,
uFormat(
"%d vs %d", descriptor.cols, dim).c_str());
666 UASSERT_MSG(type == CV_32F,
"To use KdTree dictionary, float descriptors are required!");
670 UASSERT_MSG(type == CV_8U,
"To use LSH dictionary, binary descriptors are required!");
680 UDEBUG(
"Dictionary updated! (size=%d added=%d removed=%d)",
685 UDEBUG(
"Dictionary has not changed, so no need to update it! (size=%d)",
_dataTree.rows);
695 if(printWarningsIfNotEmpty)
699 UWARN(
"Visual dictionary would be already empty here (%d words still in dictionary).", (
int)
_visualWords.size());
703 UWARN(
"Not indexed words should be empty here (%d words still not indexed)", (
int)
_notIndexedWords.size());
760 const cv::Mat & descriptorsIn,
763 UDEBUG(
"id=%d descriptors=%d", signatureId, descriptorsIn.rows);
765 std::list<int> wordIds;
766 if(descriptorsIn.rows == 0 || descriptorsIn.cols == 0)
768 UERROR(
"Descriptors size is null!");
774 UERROR(
"Dictionary mode is set to fixed but no words are in it!");
783 dim =
_visualWords.begin()->second->getDescriptor().cols;
784 type =
_visualWords.begin()->second->getDescriptor().type();
785 UASSERT(type == CV_32F || type == CV_8U);
787 if(dim && dim != descriptorsIn.cols)
789 UERROR(
"Descriptors (size=%d) are not the same size as already added words in dictionary(size=%d)", descriptorsIn.cols, dim);
792 if(type>=0 && type != descriptorsIn.type())
794 UERROR(
"Descriptors (type=%d) are not the same type as already added words in dictionary(type=%d)", descriptorsIn.type(), type);
800 if(descriptorsIn.type() == CV_8U)
809 descriptors = descriptorsIn;
814 descriptors = descriptorsIn;
822 UASSERT(type == CV_32F || type == CV_8U);
825 if(dim && dim != descriptors.cols)
827 UERROR(
"Descriptors (size=%d) are not the same size as already added words in dictionary(size=%d)", descriptors.cols, dim);
831 if(type>=0 && type != descriptors.type())
833 UERROR(
"Descriptors (type=%d) are not the same type as already added words in dictionary(type=%d)", descriptors.type(), type);
837 int dupWordsCountFromDict= 0;
838 int dupWordsCountFromLast= 0;
843 std::vector<int> newWordsId;
847 std::vector<std::vector<cv::DMatch> > matches;
848 bool bruteForce =
false;
849 bool isL2NotSqr =
false;
857 UDEBUG(
"newPts.total()=%d ", descriptors.rows);
866 cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR);
867 matcher.knnMatch(descriptors,
_dataTree, matches, k);
872 #if CV_MAJOR_VERSION < 3 873 #ifdef HAVE_OPENCV_GPU 874 cv::gpu::GpuMat newDescriptorsGpu(descriptors);
875 cv::gpu::GpuMat lastDescriptorsGpu(
_dataTree);
876 if(descriptors.type()==CV_8U)
878 cv::gpu::BruteForceMatcher_GPU<cv::Hamming> gpuMatcher;
879 gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
883 cv::gpu::BruteForceMatcher_GPU<cv::L2<float> > gpuMatcher;
884 gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
888 UERROR(
"Cannot use brute Force GPU because OpenCV is not built with gpu module.");
891 #ifdef HAVE_OPENCV_CUDAFEATURES2D 892 cv::cuda::GpuMat newDescriptorsGpu(descriptors);
893 cv::cuda::GpuMat lastDescriptorsGpu(
_dataTree);
894 cv::Ptr<cv::cuda::DescriptorMatcher> gpuMatcher;
895 if(descriptors.type()==CV_8U)
897 gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING);
898 gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
902 gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_L2);
903 gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
907 UERROR(
"Cannot use brute Force GPU because OpenCV is not built with cuda module.");
917 if(dists.type() == CV_32S)
920 dists.convertTo(temp, CV_32F);
924 UDEBUG(
"Time to find nn = %f s", timerLocal.
ticks());
928 for(
int i = 0; i < descriptors.rows; ++i)
930 std::multimap<float, int> fullResults;
931 if(!bruteForce && dists.cols)
933 for(
int j=0; j<dists.cols; ++j)
935 float d = dists.at<
float>(i,j);
937 if (
sizeof(
size_t) == 8)
939 index = *((
size_t*)&results.at<
double>(i, j));
943 index = *((
size_t*)&results.at<
int>(i, j));
946 if(d >= 0.0
f &&
id != 0)
948 fullResults.insert(std::pair<float, int>(d,
id));
956 else if(bruteForce && matches.size())
958 for(
unsigned int j=0; j<matches.at(i).size(); ++j)
960 float d = matches.at(i).at(j).distance;
962 if(d >= 0.0
f &&
id != 0)
969 fullResults.insert(std::pair<float, int>(d,
id));
981 std::vector<std::vector<cv::DMatch> > matchesNewWords;
982 cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:
useDistanceL1_?cv::NORM_L1:cv::NORM_L2SQR);
983 UASSERT(descriptors.cols == newWords.cols && descriptors.type() == newWords.type());
984 matcher.knnMatch(descriptors.row(i), newWords, matchesNewWords, newWords.rows>1?2:1);
985 UASSERT(matchesNewWords.size() == 1);
986 for(
unsigned int j=0; j<matchesNewWords.at(0).size(); ++j)
988 float d = matchesNewWords.at(0).at(j).distance;
989 int id = newWordsId[matchesNewWords.at(0).at(j).trainIdx];
990 if(d >= 0.0
f &&
id != 0)
992 fullResults.insert(std::pair<float, int>(d,
id));
1003 bool badDist =
false;
1004 if(fullResults.size() == 0)
1010 if(fullResults.size() >= 2)
1013 if(fullResults.begin()->first >
_nndrRatio * (++fullResults.begin())->first)
1030 newWords.push_back(descriptors.row(i));
1031 newWordsId.push_back(vw->
id());
1032 wordIds.push_back(vw->
id());
1039 ++dupWordsCountFromLast;
1043 ++dupWordsCountFromDict;
1046 this->
addWordRef(fullResults.begin()->second, signatureId);
1047 wordIds.push_back(fullResults.begin()->second);
1050 else if(fullResults.size())
1053 ++dupWordsCountFromDict;
1054 this->
addWordRef(fullResults.begin()->second, signatureId);
1055 wordIds.push_back(fullResults.begin()->second);
1056 UASSERT(fullResults.begin()->second>0);
1062 ULOGGER_DEBUG(
"%d duplicated words added (from current image = %d)...",
1063 dupWordsCountFromDict+dupWordsCountFromLast, dupWordsCountFromLast);
1077 int type = (*vws.begin())->getDescriptor().type();
1078 int dim = (*vws.begin())->getDescriptor().cols;
1080 if(dim !=
_visualWords.begin()->second->getDescriptor().cols)
1082 UERROR(
"Descriptors (size=%d) are not the same size as already added words in dictionary(size=%d)", (*vws.begin())->getDescriptor().cols, dim);
1083 return std::vector<int>(vws.size(), 0);
1086 if(type !=
_visualWords.begin()->second->getDescriptor().type())
1088 UERROR(
"Descriptors (type=%d) are not the same type as already added words in dictionary(type=%d)", (*vws.begin())->getDescriptor().type(), type);
1089 return std::vector<int>(vws.size(), 0);
1095 cv::Mat query(vws.size(), dim, type);
1096 for(std::list<VisualWord *>::const_iterator iter=vws.begin(); iter!=vws.end(); ++iter, ++index)
1110 return std::vector<int>(vws.size(), 0);
1116 std::vector<int> resultIds(queryIn.rows, 0);
1122 int dim =
_visualWords.begin()->second->getDescriptor().cols;
1123 int type =
_visualWords.begin()->second->getDescriptor().type();
1124 UASSERT(type == CV_32F || type == CV_8U);
1126 if(dim != queryIn.cols)
1128 UERROR(
"Descriptors (size=%d) are not the same size as already added words in dictionary(size=%d)", queryIn.cols, dim);
1131 if(type != queryIn.type())
1133 UERROR(
"Descriptors (type=%d) are not the same type as already added words in dictionary(type=%d)", queryIn.type(), type);
1139 if(queryIn.type() == CV_8U)
1160 UASSERT(type == CV_32F || type == CV_8U);
1163 if(dim && dim != query.cols)
1165 UERROR(
"Descriptors (size=%d) are not the same size as already added words in dictionary(size=%d)", query.cols, dim);
1169 if(type>=0 && type != query.type())
1171 UERROR(
"Descriptors (type=%d) are not the same type as already added words in dictionary(type=%d)", query.type(), type);
1175 std::vector<std::vector<cv::DMatch> > matches;
1176 bool bruteForce =
false;
1177 bool isL2NotSqr =
false;
1184 UDEBUG(
"query.rows=%d ", query.rows);
1193 cv::BFMatcher matcher(query.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR);
1194 matcher.knnMatch(query,
_dataTree, matches, k);
1199 #if CV_MAJOR_VERSION < 3 1200 #ifdef HAVE_OPENCV_GPU 1201 cv::gpu::GpuMat newDescriptorsGpu(query);
1202 cv::gpu::GpuMat lastDescriptorsGpu(
_dataTree);
1203 if(query.type()==CV_8U)
1205 cv::gpu::BruteForceMatcher_GPU<cv::Hamming> gpuMatcher;
1206 gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
1210 cv::gpu::BruteForceMatcher_GPU<cv::L2<float> > gpuMatcher;
1211 gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
1215 UERROR(
"Cannot use brute Force GPU because OpenCV is not built with gpu module.");
1218 #ifdef HAVE_OPENCV_CUDAFEATURES2D 1219 cv::cuda::GpuMat newDescriptorsGpu(query);
1220 cv::cuda::GpuMat lastDescriptorsGpu(
_dataTree);
1221 cv::cuda::GpuMat matchesGpu;
1222 cv::Ptr<cv::cuda::DescriptorMatcher> gpuMatcher;
1223 if(query.type()==CV_8U)
1225 gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING);
1226 gpuMatcher->knnMatchAsync(newDescriptorsGpu, lastDescriptorsGpu, matchesGpu, k);
1230 gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_L2);
1231 gpuMatcher->knnMatchAsync(newDescriptorsGpu, lastDescriptorsGpu, matchesGpu, k);
1234 gpuMatcher->knnMatchConvert(matchesGpu, matches);
1236 UERROR(
"Cannot use brute Force GPU because OpenCV is not built with cuda module.");
1246 if(dists.type() == CV_32S)
1249 dists.convertTo(temp, CV_32F);
1255 std::map<int, int> mapIndexIdNotIndexed;
1256 std::vector<std::vector<cv::DMatch> > matchesNotIndexed;
1259 cv::Mat dataNotIndexed = cv::Mat::zeros(
_notIndexedWords.size(), query.cols, query.type());
1260 unsigned int index = 0;
1282 UASSERT(vw != 0 && descriptor.cols == query.cols && descriptor.type() == query.type());
1283 descriptor.copyTo(dataNotIndexed.row(index));
1284 mapIndexIdNotIndexed.insert(mapIndexIdNotIndexed.end(), std::pair<int,int>(index, vw->
id()));
1288 cv::BFMatcher matcher(query.type()==CV_8U?cv::NORM_HAMMING:
useDistanceL1_?cv::NORM_L1:cv::NORM_L2SQR);
1289 matcher.knnMatch(query, dataNotIndexed, matchesNotIndexed, dataNotIndexed.rows>1?2:1);
1293 for(
int i=0; i<query.rows; ++i)
1295 std::multimap<float, int> fullResults;
1296 if(!bruteForce && dists.cols)
1298 for(
int j=0; j<dists.cols; ++j)
1300 float d = dists.at<
float>(i,j);
1303 if (
sizeof(
size_t) == 8)
1305 index = *((
size_t*)&results.at<
double>(i, j));
1309 index = *((
size_t*)&results.at<
int>(i, j));
1312 if(d >= 0.0
f &&
id != 0)
1314 fullResults.insert(std::pair<float, int>(d,
id));
1318 else if(bruteForce && matches.size())
1320 for(
unsigned int j=0; j<matches.at(i).size(); ++j)
1322 float d = matches.at(i).at(j).distance;
1324 if(d >= 0.0
f &&
id != 0)
1331 fullResults.insert(std::pair<float, int>(d,
id));
1337 if(matchesNotIndexed.size())
1339 for(
unsigned int j=0; j<matchesNotIndexed.at(i).size(); ++j)
1341 float d = matchesNotIndexed.at(i).at(j).distance;
1342 int id =
uValue(mapIndexIdNotIndexed, matchesNotIndexed.at(i).at(j).trainIdx);
1343 if(d >= 0.0
f &&
id != 0)
1345 fullResults.insert(std::pair<float, int>(d,
id));
1356 bool badDist =
false;
1357 if(fullResults.size() == 0)
1363 if(fullResults.size() >= 2)
1366 if(fullResults.begin()->first >
_nndrRatio * (++fullResults.begin())->first)
1379 resultIds[i] = fullResults.begin()->second;
1382 else if(fullResults.size())
1385 resultIds[i] = fullResults.begin()->second;
1407 if(_lastWordId < vw->
id())
1437 for(
unsigned int i=0; i<words.size(); ++i)
1452 for(
unsigned int i=0; i<unusedWords.size(); ++i)
1454 delete unusedWords[i];
1463 UWARN(
"Dictionary is empty, cannot export it!");
1466 if(
_visualWords.begin()->second->getDescriptor().type() != CV_32FC1)
1468 UERROR(
"Exporting binary descriptors is not implemented!");
1474 fopen_s(&foutRef, fileNameReferences,
"w");
1475 fopen_s(&foutDesc, fileNameDescriptors,
"w");
1477 foutRef = fopen(fileNameReferences,
"w");
1478 foutDesc = fopen(fileNameDescriptors,
"w");
1483 fprintf(foutRef,
"WordID SignaturesID...\n");
1489 fprintf(foutDesc,
"WordID Descriptors...\n");
1494 fprintf(foutDesc,
"WordID Descriptors...%d\n", (*
_visualWords.begin()).second->getDescriptor().cols);
1504 fprintf(foutRef,
"%d ", (*iter).first);
1505 const std::map<int, int> ref = (*iter).second->getReferences();
1506 for(std::map<int, int>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
1508 for(
int i=0; i<(*jter).second; ++i)
1510 fprintf(foutRef,
"%d ", (*jter).first);
1513 fprintf(foutRef,
"\n");
1519 fprintf(foutDesc,
"%d ", (*iter).first);
1520 const float * desc = (
const float *)(*iter).second->getDescriptor().data;
1521 int dim = (*iter).second->getDescriptor().cols;
1523 for(
int i=0; i<dim; i++)
1525 fprintf(foutDesc,
"%f ", desc[i]);
1527 fprintf(foutDesc,
"\n");
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
void removePoint(unsigned int index)
std::vector< int > getUnusedWordIds() const
std::vector< K > uKeys(const std::multimap< K, V > &mm)
unsigned int getIndexMemoryUsed() const
bool uIsDigit(const char c)
int removeAllRef(int signatureId)
void buildLSHIndex(const cv::Mat &features, unsigned int table_number=12, unsigned int key_size=20, unsigned int multi_probe_level=2, float rebalancingFactor=2.0f)
bool UTILITE_EXP uStr2Bool(const char *str)
std::set< K > uKeysSet(const std::map< K, V > &m)
float UTILITE_EXP uStr2Float(const std::string &str)
void knnSearch(const cv::Mat &query, cv::Mat &indices, cv::Mat &dists, int knn, int checks=32, float eps=0.0, bool sorted=true) const
virtual std::list< int > addNewWords(const cv::Mat &descriptors, int signatureId)
std::map< std::string, std::string > ParametersMap
unsigned long memoryUsed() const
const std::map< int, int > & getReferences() const
void addWordRef(int wordId, int signatureId)
const VisualWord * getWord(int id) const
void exportDictionary(const char *fileNameReferences, const char *fileNameDescriptors) const
std::string getExtension()
std::map< int,int > _mapIdIndex
unsigned int getIndexedWordsCount() const
void setFixedDictionary(const std::string &dictionaryPath)
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
std::vector< VisualWord * > getUnusedWords() const
#define UASSERT(condition)
int _totalActiveReferences
void setIncrementalDictionary()
virtual void parseParameters(const ParametersMap ¶meters)
void buildLinearIndex(const cv::Mat &features, bool useDistanceL1=false, float rebalancingFactor=2.0f)
#define ULOGGER_DEBUG(...)
static cv::Mat convert32FToBin(const cv::Mat &descriptorsIn, bool byteToFloat=true)
bool _newWordsComparedTogether
unsigned long getMemoryUsed() const
#define UASSERT_MSG(condition, msg_str)
bool _incrementalDictionary
unsigned int indexedFeatures() const
std::map< int,int > _mapIndexId
const cv::Mat & getDescriptor() const
std::vector< int > findNN(const std::list< VisualWord * > &vws) const
VWDictionary(const ParametersMap ¶meters=ParametersMap())
void clear(bool printWarningsIfNotEmpty=true)
std::list< std::string > uSplitNumChar(const std::string &str)
bool uContains(const std::list< V > &list, const V &value)
static DBDriver * create(const ParametersMap ¶meters=ParametersMap())
std::vector< V > uValues(const std::multimap< K, V > &mm)
void removeWords(const std::vector< VisualWord * > &words)
std::set< int > _notIndexedWords
std::map< int, VisualWord * > _unusedWords
std::string _newDictionaryPath
int getLastIndexedWordId() const
void addRef(int signatureId)
std::set< int > _removedIndexedWords
bool setNNStrategy(NNStrategy strategy)
static const int ID_START
void removeAllWordRef(int wordId, int signatureId)
std::vector< unsigned int > addPoints(const cv::Mat &features)
void setSaved(bool saved)
T uSum(const std::list< T > &list)
void buildKDTreeIndex(const cv::Mat &features, int trees=4, bool useDistanceL1=false, float rebalancingFactor=2.0f)
static const int ID_INVALID
virtual void addWord(VisualWord *vw)
static cv::Mat convertBinTo32F(const cv::Mat &descriptorsIn, bool byteToFloat=true)
VisualWord * getUnusedWord(int id) const
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string _dictionaryPath
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
std::map< int, VisualWord * > _visualWords