32 #include <QtCore/QVector> 33 #include <QDataStream> 35 #if CV_MAJOR_VERSION < 3 36 #include <opencv2/gpu/gpu.hpp> 37 #define CVCUDA cv::gpu 39 #include <opencv2/core/cuda.hpp> 40 #define CVCUDA cv::cuda 41 #ifdef HAVE_OPENCV_CUDAFEATURES2D 42 #include <opencv2/cudafeatures2d.hpp> 62 if(Settings::getGeneral_vocabularyFixed() && Settings::getGeneral_invertedSearch())
95 streamSessionPtr >> rows >> cols >> type >> dataSize;
97 streamSessionPtr >> data;
106 cv::FileStorage fs(filename.toStdString(), cv::FileStorage::WRITE);
114 UERROR(
"Failed to open vocabulary file \"%s\"", filename.toStdString().c_str());
122 cv::FileStorage fs(filename.toStdString(), cv::FileStorage::READ);
126 fs[
"Descriptors"] >> tmp;
138 UERROR(
"Failed to read \"Descriptors\" matrix field (doesn't exist or is empty) from vocabulary file \"%s\"", filename.toStdString().c_str());
143 UERROR(
"Failed to open vocabulary file \"%s\"", filename.toStdString().c_str());
150 QMultiMap<int, int> words;
151 if (descriptorsIn.empty())
157 if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat())
159 descriptorsIn.convertTo(descriptors, CV_32F);
163 descriptors = descriptorsIn;
166 if(Settings::getGeneral_vocabularyIncremental() || Settings::getGeneral_vocabularyFixed())
172 bool globalSearch =
false;
177 if(Settings::getGeneral_vocabularyFixed())
179 UERROR(
"Descriptors (type=%d size=%d) to search in vocabulary are not the same type/size as those in the vocabulary (type=%d size=%d)! Empty words returned.",
185 UFATAL(
"Descriptors (type=%d size=%d) to search in vocabulary are not the same type/size as those in the vocabulary (type=%d size=%d)!",
190 this->
search(descriptors, results, dists, k);
192 if( dists.type() == CV_32S )
195 dists.convertTo(temp, CV_32F);
202 if(!Settings::getGeneral_vocabularyFixed())
208 for(
int i = 0; i < descriptors.rows; ++i)
210 QMultiMap<float, int> fullResults;
219 if(descriptors.type()==CV_8U)
225 int normType = cv::NORM_HAMMING;
227 (Settings::getFeature2D_ORB_WTA_K()==3 || Settings::getFeature2D_ORB_WTA_K()==4))
229 normType = cv::NORM_HAMMING2;
232 cv::batchDistance( descriptors.row(i),
245 cv::flann::Index tmpIndex;
246 #if CV_MAJOR_VERSION == 2 and CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >= 12 247 tmpIndex.build(
notIndexedDescriptors_, cv::Mat(), cv::flann::LinearIndexParams(), cvflann::FLANN_DIST_L2);
251 tmpIndex.knnSearch(descriptors.row(i), tmpResults, tmpDists,
notIndexedDescriptors_.rows>1?k:1, cvflann::FLANN_DIST_L2);
254 if( tmpDists.type() == CV_32S )
257 tmpDists.convertTo(temp, CV_32F);
261 for(
int j = 0; j < tmpResults.cols; ++j)
263 if(tmpResults.at<
int>(0,j) >= 0)
266 fullResults.insert(tmpDists.at<
float>(0,j),
notIndexedWordIds_.at(tmpResults.at<
int>(0,j)));
273 for(
int j=0; j<k; ++j)
275 if(results.at<
int>(i,j) >= 0)
278 fullResults.insert(dists.at<
float>(i,j), results.at<
int>(i,j));
283 bool matched =
false;
284 if(Settings::getNearestNeighbor_3nndrRatioUsed() &&
285 fullResults.size() >= 2 &&
286 fullResults.begin().key() <= Settings::getNearestNeighbor_4nndrRatio() * (++fullResults.begin()).key())
290 if((matched || !Settings::getNearestNeighbor_3nndrRatioUsed()) &&
291 Settings::getNearestNeighbor_5minDistanceUsed())
293 if(fullResults.begin().key() <= Settings::getNearestNeighbor_6minDistance())
302 if(!matched && !Settings::getNearestNeighbor_3nndrRatioUsed() && !Settings::getNearestNeighbor_5minDistanceUsed())
309 words.insert(fullResults.begin().value(), i);
313 else if(!Settings::getGeneral_invertedSearch() || !Settings::getGeneral_vocabularyFixed())
329 for(
int i = 0; i < descriptors.rows; ++i)
362 #if CV_MAJOR_VERSION == 2 and CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >= 12 376 if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat())
378 descriptorsIn.convertTo(descriptors, CV_32F);
382 descriptors = descriptorsIn;
389 std::vector<std::vector<cv::DMatch> > matches;
390 if(Settings::getNearestNeighbor_BruteForce_gpu() && CVCUDA::getCudaEnabledDeviceCount())
392 CVCUDA::GpuMat newDescriptorsGpu(descriptors);
394 #if CV_MAJOR_VERSION < 3 397 CVCUDA::BruteForceMatcher_GPU<cv::Hamming> gpuMatcher;
398 gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
402 CVCUDA::BruteForceMatcher_GPU<cv::L2<float> > gpuMatcher;
403 gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
406 #ifdef HAVE_OPENCV_CUDAFEATURES2D 407 cv::Ptr<cv::cuda::DescriptorMatcher> gpuMatcher;
410 gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING);
411 gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
415 gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_L2);
416 gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
419 UERROR(
"OpenCV3 is not built with CUDAFEATURES2D module, cannot do brute force matching on GPU!");
430 results = cv::Mat((
int)matches.size(), k, CV_32SC1);
431 dists = cv::Mat((
int)matches.size(), k, CV_32FC1);
432 for(
unsigned int i=0; i<matches.size(); ++i)
434 for(
int j=0; j<k; ++j)
436 results.at<
int>(i, j) = matches[i].at(j).trainIdx;
437 dists.at<
float>(i, j) = matches[i].at(j).distance;
443 flannIndex_.knnSearch(descriptors, results, dists, k,
444 cv::flann::SearchParams(
445 Settings::getNearestNeighbor_search_checks(),
446 Settings::getNearestNeighbor_search_eps(),
447 Settings::getNearestNeighbor_search_sorted()));
450 if( dists.type() == CV_32S )
453 dists.convertTo(temp, CV_32F);
static cv::flann::IndexParams * createFlannIndexParams()
cv::Mat indexedDescriptors_
cv::Mat notIndexedDescriptors_
void save(QDataStream &streamSessionPtr) const
void load(QDataStream &streamSessionPtr)
QVector< int > notIndexedWordIds_
static cvflann::flann_distance_t getFlannDistanceType()
#define UASSERT(condition)
cv::flann::Index flannIndex_
QMultiMap< int, int > addWords(const cv::Mat &descriptors, int objectId)
void search(const cv::Mat &descriptors, cv::Mat &results, cv::Mat &dists, int k)
QMultiMap< int, int > wordToObjects_
static QString currentDescriptorType()
static bool isBruteForceNearestNeighbor()
ULogger class and convenient macros.