#include #include "opencv2/features2d/features2d.hpp" #include #include using namespace cv; using namespace std; const char dlmtr = '/'; void maskMatchesByTrainImgIdx( const vector& matches, int trainImgIdx, vector& mask ); void readTrainFilenames( const string& filename, string& dirName, vector& trainFilenames ); int main(int argc, char** argv) { Mat queryImg; vector queryPoints; Mat queryDescs; vector trainImgCollection; vector > trainPointCollection; vector trainDescCollection; vector matches; if( argc != 7 ) { cout << "Format:" << endl; cout << argv[0] << "[detectorType] [descriptorType] [matcherType] [queryImage] [fileWithTrainImages] [dirToSaveResImages]" << endl; return -1; } cout << "< 1.) Creating feature detector, descriptor extractor and descriptor matcher ..." << endl; Ptr detector = createFeatureDetector( argv[1] ); Ptr descriptorExtractor = createDescriptorExtractor( argv[2] ); Ptr descriptorMatcher = createDescriptorMatcher( argv[3] ); cout << ">" << endl; if( detector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() ) { cout << "Can not create feature detector or descriptor exstractor or descriptor matcher of given types." << endl << ">" << endl; return -1; } cout << "< 2.) Reading the images..." << endl; queryImg = imread( argv[4], CV_LOAD_IMAGE_GRAYSCALE); if( queryImg.empty() ) { cout << "Query image can not be read." << endl << ">" << endl; return -1; } string trainDirName; vector trainFilenames; vector usedTrainImgIdxs; readTrainFilenames( argv[5], trainDirName, trainFilenames ); if( trainFilenames.empty() ) { cout << "Train image filenames can not be read." << endl << ">" << endl; return -1; } for( size_t i = 0; i < trainFilenames.size(); i++ ) { Mat img = imread( trainDirName + trainFilenames[i], CV_LOAD_IMAGE_GRAYSCALE ); if( img.empty() ) cout << "Train image " << trainDirName + trainFilenames[i] << " can not be read." << endl; trainImgCollection.push_back( img ); usedTrainImgIdxs.push_back( i ); } if( trainImgCollection.empty() ) { cout << "All train images can not be read." << endl << ">" << endl; return -1; } else cout << trainImgCollection.size() << " train images were read." << endl; cout << ">" << endl; cout << endl << "< 3.) Extracting keypoints from images..." << endl; detector->detect( queryImg, queryPoints ); detector->detect( trainImgCollection, trainPointCollection ); cout << ">" << endl; cout << "< 4.) Computing descriptors for keypoints..." << endl; descriptorExtractor->compute( queryImg, queryPoints, queryDescs ); descriptorExtractor->compute( trainImgCollection, trainPointCollection, trainDescCollection ); cout << ">" << endl; cout << "< 5.) Set train descriptors collection in the matcher and match query descriptors to them..." << endl; descriptorMatcher->add( trainDescCollection ); descriptorMatcher->match( queryDescs, matches ); CV_Assert( queryPoints.size() == matches.size() ); cout << ">" << endl; Mat drawImg; vector mask; for( size_t i = 0; i < trainImgCollection.size(); i++ ) { maskMatchesByTrainImgIdx( matches, i, mask ); drawMatches( queryImg, queryPoints, trainImgCollection[i], trainPointCollection[i], matches, drawImg, Scalar::all(-1), Scalar::all(-1), mask ); imwrite( string(argv[6]) + "/res_" + trainFilenames[usedTrainImgIdxs[i]] + ".png", drawImg ); } return 0; } void maskMatchesByTrainImgIdx( const vector& matches, int trainImgIdx, vector& mask ) { mask.resize( matches.size() ); fill( mask.begin(), mask.end(), 0 ); for( size_t i = 0; i < matches.size(); i++ ) { if( matches[i].imgIdx == trainImgIdx ) mask[i] = 1; } } void readTrainFilenames( const string& filename, string& dirName, vector& trainFilenames ) { trainFilenames.clear(); ifstream file( filename.c_str() ); if ( !file.is_open() ) return; size_t 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(); }