I have a question about the following code:
#include "iostream"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/flann/flann.hpp>
#include "opencv2/flann/miniflann.hpp"
#include <opencv2/legacy/legacy.hpp>
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/core/version.hpp"
#include "opencv2/core/operations.hpp"
#include "opencv2/core/mat.hpp"
#include "opencv2/core/types_c.h"
#include <limits>
#include <vector>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
static void readTrainFilenames( const string& filename, string& dirName, vector<string>& trainFilenames )
{
trainFilenames.clear();
ifstream file( filename.c_str() );
if ( !file.is_open() )
return;
size_t pos = filename.rfind('\\');
char dlmtr = '\\';
if (pos == String::npos)
{
pos = filename.rfind('/');
dlmtr = '/';
}
dirName = pos == string::npos ? "" : filename.substr(0, pos) + dlmtr;
while( !file.eof() )
{
string str; getline( file, str );
if( str.empty() ) break;
trainFilenames.push_back(str);
}
file.close();
}
static bool createDetectorDescriptorMatcher( const string& detectorType, const string& descriptorType, const string& matcherType,
Ptr<FeatureDetector>& featureDetector,
Ptr<DescriptorExtractor>& descriptorExtractor,
Ptr<DescriptorMatcher>& descriptorMatcher )
{
cout << "< Creating feature detector, descriptor extractor and descriptor matcher ..." << endl;
featureDetector = FeatureDetector::create( detectorType );
descriptorExtractor = DescriptorExtractor::create( descriptorType );
descriptorMatcher = DescriptorMatcher::create( matcherType );
cout << ">" << endl;
bool isCreated = !( featureDetector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() );
if( !isCreated )
cout << "Can not create feature detector or descriptor extractor or descriptor matcher of given types." << endl << ">" << endl;
return isCreated;
}
static bool readImages( const string& queryImageName, const string& trainFilename,
Mat& queryImage, vector <Mat>& trainImages, vector<string>& trainImageNames )
{
cout << "< Reading the images..." << endl;
queryImage = imread( queryImageName);
if( queryImage.empty() )
{
cout << "Query image can not be read." << endl << ">" << endl;
return false;
}
string trainDirName;
readTrainFilenames( trainFilename, trainDirName, trainImageNames );
if( trainImageNames.empty() )
{
cout << "Train image filenames can not be read." << endl << ">" << endl;
return false;
}
int readImageCount = 0;
for( size_t i = 0; i < trainImageNames.size(); i++ )
{
string filename = trainDirName + trainImageNames[i];
Mat img = imread( filename );
if( img.empty() )
cout << "Train image " << filename << " can not be read." << endl;
else {
readImageCount++;
double min, max;
minMaxLoc(img, &min, &max);
if (min!=max) {
trainImages.push_back( img );
}
}
}
if( !readImageCount )
{
cout << "All train images can not be read." << endl << ">" << endl;
return false;
}
else
cout << readImageCount << " train images were read." << endl;
cout << ">" << endl;
return true;
}
static void detectKeypoints( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints,
Ptr<FeatureDetector>& featureDetector )
{
TickMeter tm;
tm.start();
cout << endl << "< Extracting keypoints from images..." << endl;
featureDetector->detect( queryImage, queryKeypoints );
featureDetector->detect( trainImages, trainKeypoints );
cout << ">" << endl;
tm.stop();
double exttime = tm.getTimeMilli();
cout << "Extraction time: " << exttime << endl;
}
static void computeDescriptors( const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Mat& queryDescriptors,
const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints, vector<Mat>& trainDescriptors,
Ptr<DescriptorExtractor>& descriptorExtractor )
{
TickMeter tm;
tm.start();
cout << "< Computing descriptors for keypoints..." << endl;
descriptorExtractor->compute( queryImage, queryKeypoints, queryDescriptors );
descriptorExtractor->compute( trainImages, trainKeypoints, trainDescriptors );
int totalTrainDesc = 0;
for( vector<Mat>::const_iterator tdIter = trainDescriptors.begin(); tdIter != trainDescriptors.end(); tdIter++ )
totalTrainDesc += tdIter->rows;
cout << "Query descriptors count: " << queryDescriptors.rows << "; Total train descriptors count: " << totalTrainDesc << endl;
cout << ">" << endl;
tm.stop();
double exttime = tm.getTimeMilli();
cout << "Description time: " << exttime << endl;
}
static void matchDescriptors( const Mat& queryDescriptors, const vector<Mat>& trainDescriptors,
vector<DMatch>& matches, Ptr<DescriptorMatcher>& descriptorMatcher )
{
cout << "< Set train descriptors collection in the matcher and match query descriptors to them..." << endl;
TickMeter tm;
tm.start();
descriptorMatcher->add( trainDescriptors );
descriptorMatcher->train();
tm.stop();
double buildTime = tm.getTimeMilli();
tm.start();
descriptorMatcher->match( queryDescriptors, matches );
tm.stop();
double matchTime = tm.getTimeMilli();
CV_Assert( queryDescriptors.rows == (int)matches.size() || matches.empty() );
cout << "Number of matches: " << matches.size() << endl;
cout << "Build time: " << buildTime << " ms; Match time: " << matchTime << " ms" << endl;
cout << ">" << endl;
}
int main(int argc, char** argv)
{
string detectorType = "SURF";
string descriptorType = "SURF";
string matcherType = "FlannBased";
string fileWithTrainImages = "/home/juan/workspace/keypoint/Debug/matching_to_many_images/train/keyframes.txt";
string dirToSaveResImages = "/home/juan/workspace/keypoint/Debug/matching_to_many_images/results";
string queryImageName = "/home/juan/workspace/keypoint/Debug/keyframe0.jpg";
Ptr<FeatureDetector> featureDetector;
Ptr<DescriptorExtractor> descriptorExtractor;
Ptr<DescriptorMatcher> descriptorMatcher;
createDetectorDescriptorMatcher( detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher );
Mat queryImage;
vector<Mat> trainImages;
vector<string> trainImagesNames;
if( !readImages( queryImageName, fileWithTrainImages, queryImage, trainImages, trainImagesNames ) )
{
cout << "Error!!" << endl;
return -1;
}
vector<KeyPoint> queryKeypoints;
vector<vector<KeyPoint> > trainKeypoints;
detectKeypoints( queryImage, queryKeypoints, trainImages, trainKeypoints, featureDetector );
Mat queryDescriptors;
vector<Mat> trainDescriptors;
computeDescriptors( queryImage, queryKeypoints, queryDescriptors,
trainImages, trainKeypoints, trainDescriptors,
descriptorExtractor );
vector<DMatch> matches;
matchDescriptors( queryDescriptors, trainDescriptors, matches, descriptorMatcher );
return 0;
}
The main functionality of the program is: It reads a query image and a set of train images. Then, it detects the keypoints using the detectorType established (SURF, SIFT, FAST...). After that, it extracts the descriptors of these keypoints using the descriptorType established (FREAK, SIFT...). Finally, there are given the matches between the query image and the entire set of train images, based on the matcher established by the variable matcherType (BruteForce, FlannBased...). My problem is that I have tried to use all the detector, descriptor and matcher types (variables detectorType, descriptorType, matcherType) that OpenCV provides in its methods. However, I have only got results with a few number of them. For example, the combination Detector-Descriptor-Matcher "SURF-SURF-FlannBased" does not works for me, and gives me the following error:
juan@juan-HP-G62-NoteBook-PC:~/workspace/keypoint/Debug$ ./keypoint < Creating feature detector, descriptor extractor and descriptor matcher ...
Can not create feature detector or descriptor extractor or descriptor matcher of given types. < Reading the images... 77 train images were read.
< Extracting keypoints from images... Violación de segmento (`core' generado)
However, the combination FAST-FREAK-BruteForce works fine for me:
< Creating feature detector, descriptor extractor and descriptor matcher ...
< Reading the images... 77 train images were read.
< Extracting keypoints from images...
Extraction time: 374.277 < Computing descriptors for keypoints... Query descriptors count: 786; Total train descriptors count: 154417 Description time: 1489.24 < Set train descriptors collection in the matcher and match query descriptors to them... Number of matches: 786 Build time: 0.024077 ms; Match time: 14292.6 ms
I am using OpenCV 2.4.9, with Eclipse as IDE and Linux as SO. Can anyone help me? I am very interested on using the FlannBased matcher to deal with a large database of comparisons, since the BruteForce matcher works good but it is very slowly in this situation. Thank you!