refactored features2d and sample on matching to many images

This commit is contained in:
Maria Dimashova
2010-11-22 18:27:08 +00:00
parent cf0d9da643
commit e406dfee44
13 changed files with 1619 additions and 1025 deletions

View File

@@ -7,103 +7,22 @@
using namespace cv;
using namespace std;
void maskMatchesByTrainImgIdx( const vector<DMatch>& matches, int trainImgIdx, vector<char>& mask );
void readTrainFilenames( const string& filename, string& dirName, vector<string>& trainFilenames );
int main(int argc, char** argv)
{
Mat queryImg;
vector<KeyPoint> queryPoints;
Mat queryDescs;
vector<Mat> trainImgCollection;
vector<vector<KeyPoint> > trainPointCollection;
vector<Mat> trainDescCollection;
vector<DMatch> 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<FeatureDetector> detector = createFeatureDetector( argv[1] );
Ptr<DescriptorExtractor> descriptorExtractor = createDescriptorExtractor( argv[2] );
Ptr<DescriptorMatcher> 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<string> trainFilenames;
vector<int> 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;
cout << "< 6.) Save results..." << endl;
Mat drawImg;
vector<char> 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 );
}
cout << ">" << endl;
return 0;
}
/*
* This is a sample on matching descriptors detected on one image to descriptors detected in image set.
* So we have one query image and several train images. For each keypoint descriptor of query image
* the one nearest train descriptor is found the entire collection of train images. To visualize the result
* of matching we save images, each of which combines query and train image with matches between them (if they exist).
* Match is drawn as line between corresponding points. Count of all matches is equel to count of
* query keypoints, so we have the same count of lines in all set of result images (but not for each result
* (train) image).
*/
const string defaultDetectorType = "SURF";
const string defaultDescriptorType = "SURF";
const string defaultMatcherType = "FlannBased";
const string defaultQueryImageName = "../../opencv/samples/cpp/matching_to_many_images/query.png";
const string defaultFileWithTrainImages = "../../opencv/samples/cpp/matching_to_many_images/train/trainImages.txt";
const string defaultDirToSaveResImages = "../../opencv/samples/cpp/matching_to_many_images/results";
void maskMatchesByTrainImgIdx( const vector<DMatch>& matches, int trainImgIdx, vector<char>& mask )
{
@@ -136,3 +55,180 @@ void readTrainFilenames( const string& filename, string& dirName, vector<string>
}
file.close();
}
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 = createFeatureDetector( detectorType );
descriptorExtractor = createDescriptorExtractor( descriptorType );
descriptorMatcher = createDescriptorMatcher( matcherType );
cout << ">" << endl;
bool isCreated = !( featureDetector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() );
if( !isCreated )
cout << "Can not create feature detector or descriptor exstractor or descriptor matcher of given types." << endl << ">" << endl;
return isCreated;
}
bool readImages( const string& queryImageName, const string& trainFilename,
Mat& queryImage, vector <Mat>& trainImages, vector<string>& trainImageNames )
{
cout << "< Reading the images..." << endl;
queryImage = imread( queryImageName, CV_LOAD_IMAGE_GRAYSCALE);
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, CV_LOAD_IMAGE_GRAYSCALE );
if( img.empty() )
cout << "Train image " << filename << " can not be read." << endl;
else
readImageCount++;
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;
}
void detectKeypoints( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints,
Ptr<FeatureDetector>& featureDetector )
{
cout << endl << "< Extracting keypoints from images..." << endl;
featureDetector->detect( queryImage, queryKeypoints );
featureDetector->detect( trainImages, trainKeypoints );
cout << ">" << endl;
}
void computeDescriptors( const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Mat& queryDescriptors,
const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints, vector<Mat>& trainDescriptors,
Ptr<DescriptorExtractor>& descriptorExtractor )
{
cout << "< Computing descriptors for keypoints..." << endl;
descriptorExtractor->compute( queryImage, queryKeypoints, queryDescriptors );
descriptorExtractor->compute( trainImages, trainKeypoints, trainDescriptors );
cout << ">" << endl;
}
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;
descriptorMatcher->add( trainDescriptors );
descriptorMatcher->match( queryDescriptors, matches );
CV_Assert( queryDescriptors.rows == (int)matches.size() || matches.empty() );
cout << ">" << endl;
}
void saveResultImages( const Mat& queryImage, const vector<KeyPoint>& queryKeypoints,
const vector<Mat>& trainImages, const vector<vector<KeyPoint> >& trainKeypoints,
const vector<DMatch>& matches, const vector<string>& trainImagesNames, const string& resultDir )
{
cout << "< Save results..." << endl;
Mat drawImg;
vector<char> mask;
for( size_t i = 0; i < trainImages.size(); i++ )
{
if( !trainImages[i].empty() )
{
maskMatchesByTrainImgIdx( matches, i, mask );
drawMatches( queryImage, queryKeypoints, trainImages[i], trainKeypoints[i],
matches, drawImg, Scalar::all(-1), Scalar::all(-1), mask );
string filename = resultDir + "/res_" + trainImagesNames[i];
if( !imwrite( filename, drawImg ) )
cout << "Image " << filename << " can not be saved (may be because directory " << resultDir << " does not exist)." << endl;
}
}
cout << ">" << endl;
}
void printPrompt( const string& applName )
{
cout << endl << "Format:" << endl;
cout << applName << " [detectorType] [descriptorType] [matcherType] [queryImage] [fileWithTrainImages] [dirToSaveResImages]" << endl;
cout << endl << "Example:" << endl
<< defaultDetectorType << " " << defaultDescriptorType << " " << defaultMatcherType << " "
<< defaultQueryImageName << " " << defaultFileWithTrainImages << " " << defaultDirToSaveResImages << endl;
}
int main(int argc, char** argv)
{
string detectorType = defaultDetectorType;
string descriptorType = defaultDescriptorType;
string matcherType = defaultMatcherType;
string queryImageName = defaultQueryImageName;
string fileWithTrainImages = defaultFileWithTrainImages;
string dirToSaveResImages = defaultDirToSaveResImages;
if( argc != 7 && argc != 1 )
{
printPrompt( argv[0] );
return -1;
}
if( argc != 1 )
{
detectorType = argv[1]; descriptorType = argv[2]; matcherType = argv[3];
queryImageName = argv[4]; fileWithTrainImages = argv[5];
dirToSaveResImages = argv[6];
}
Ptr<FeatureDetector> featureDetector;
Ptr<DescriptorExtractor> descriptorExtractor;
Ptr<DescriptorMatcher> descriptorMatcher;
if( !createDetectorDescriptorMatcher( detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher ) )
{
printPrompt( argv[0] );
return -1;
}
Mat queryImage;
vector<Mat> trainImages;
vector<string> trainImagesNames;
if( !readImages( queryImageName, fileWithTrainImages, queryImage, trainImages, trainImagesNames ) )
{
printPrompt( argv[0] );
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 );
saveResultImages( queryImage, queryKeypoints, trainImages, trainKeypoints,
matches, trainImagesNames, dirToSaveResImages );
return 0;
}