0 down vote favorite
I am working on project and using SIFT features (OpenCV implementation) for image matching. I need to return top 10-15 images in the database which are similar to the query image. I'm using a visual bag-of-words approach to make a vocabulary first and then do the matching. I've found similar questions but didn't find the appropriate answer.
Here is code to generate a dictionary from database images:
char * filename = new char[100];
Mat input;
//To store the keypoints that will be extracted by SIFT vector<keypoint> keypoints;
//To store the SIFT descriptor of current image Mat descriptor;
//To store all the descriptors that are extracted from all the images. Mat featuresUnclustered;
//The SIFT feature extractor and descriptor SiftDescriptorExtractor detector;
for(int f=1;f<20;f++) // 20 images in database
{
sprintf(filename,"/home/kamikaze/testing/bagofwords/images/%i.jpg",f);
input = imread(filename, CV_LOAD_IMAGE_GRAYSCALE); //Load as grayscale
//detect feature points
detector.detect(input, keypoints);
//compute the descriptors for each keypoint
detector.compute(input, keypoints,descriptor);
//put the all feature descriptors in a single Mat object
featuresUnclustered.push_back(descriptor);
}
int dictionarySize=200;
TermCriteria tc(CV_TERMCRIT_ITER,100,0.001);
int retries=1;
int flags=KMEANS_PP_CENTERS;
//Create the BoW (or BoF) trainer BOWKMeansTrainer bowTrainer(dictionarySize,tc,retries,flags);
//cluster the feature vectors Mat dictionary=bowTrainer.cluster(featuresUnclustered);
//store the vocabulary FileStorage fs("dictionary.yml", FileStorage::WRITE); fs << "vocabulary" << dictionary; fs.release();
Here's my code to extract a BoW descriptor from query image using this vocabulary:
Mat dictionary; FileStorage fs("dictionary.yml", FileStorage::READ); fs["vocabulary"] >> dictionary; fs.release();
Ptr<descriptormatcher> matcher(new FlannBasedMatcher);
Ptr<featuredetector> detector(new SiftFeatureDetector());
Ptr<descriptorextractor> extractor(new SiftDescriptorExtractor);
BOWImgDescriptorExtractor bowDE(extractor,matcher);
bowDE.setVocabulary(dictionary);
char * filename = new char[100]; char * imageTag = new char[10];
//open the file to write the resultant descriptor FileStorage fs1("descriptor.yml", FileStorage::WRITE);
//the image file with the location.
sprintf(filename,"G:\testimages\image\1.jpg");
Mat img=imread(filename,CV_LOAD_IMAGE_GRAYSCALE);
//To store the keypoints that will be extracted by SIFT vector<keypoint> keypoints;
//Detect SIFT keypoints (or feature points) detector->detect(img,keypoints);
//To store the BoW (or BoF) representation of the image Mat bowDescriptor;
//extract BoW (or BoF) descriptor from given image bowDE.compute(img,keypoints,bowDescriptor);
sprintf(imageTag,"img1");
fs1 << imageTag << bowDescriptor;
fs1.release();
I don't know how can I make use of bowDescriptor for getting similar images in the database.