Training SVM for image recognition with BOW: error on prediction
Hello!
Context: I am currently attempting to train a SVM to recognize a specific building in a scene vs. different buildings. After attempting simpler approaches like direct image feature matching + homography and such, I want to attempt something a bit more flexible and/or powerful. Hence, I have set my gaze upon BOW+SVM.
Problem: As far as I am aware, the training phase goes without a hitch. However, when I reuse (either straight in code or after reloading the saved text format) my trained vocabulary and SVM to attempt a prediction on a new image, I get an out of memory error on the svm.predict(descriptors) function:
Unhandled exception at 0x7594C41F in MachineLearningTrainerBOW.exe: Microsoft C++ exception: cv::Exception at memory location 0x0037F288.
I honestly don't know what's wrong, as I have followed examples setup in a similar manner to my current code and at a glance I do not seem to do anything outlandish or different than what they do:
https://gilscvblog.com/2013/08/23/bag...
http://www.morethantechnical.com/2011...
http://answers.opencv.org/question/27...
http://answers.opencv.org/question/24...
Could anyone point the way to a complete OpenCV tutorial or exemple covering the use of BOW+SVM, or maybe point out what I might be doing wrong from my code? Thank you!
// cluster count
const int CLUSTER_COUNT = 1000;
// create global bow vocabulary with TermCriteria as per tutorial
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
Ptr<DescriptorExtractor> extractor = SurfDescriptorExtractor::create();
BOWImgDescriptorExtractor bowDE(extractor, matcher);
Ptr<SURF> detector = SURF::create(400);
BOWKMeansTrainer bowTrainer(CLUSTER_COUNT, TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, FLT_EPSILON), 1, KMEANS_PP_CENTERS);
//
//... some irrelevant functions for loading files and such...
//
void ComputeBow(vector<Mat> positives, vector<Mat> negatives, string vocabularySave)
{
// get SURF descriptors and add to BOW each input files
cout << "Acquiring descriptors, this might take a while... ";
for (int i = 0; i < positives.size(); i++)
{
vector<KeyPoint> keypoints;
detector->detect(positives[i], keypoints);
Mat descriptors;
extractor->compute(positives[i], keypoints, descriptors);
if (!descriptors.empty()) bowTrainer.add(descriptors);
}
/*for (int i = 0; i < negatives.size(); i++)
{
vector<KeyPoint> keypoints;
detector->detect(negatives[i], keypoints);
Mat descriptors;
extractor->compute(negatives[i], keypoints, descriptors);
if (!descriptors.empty()) bowTrainer.add(descriptors);
}*/
cout << "Description complete!" << endl;
// Create the vocabulary with KMeans.
cout << "Clustering features, this might take a while... ";
Mat vocabulary;
vocabulary = bowTrainer.cluster();
bowDE.setVocabulary(vocabulary);
SaveVocabulary(vocabulary, vocabularySave);
cout << "Clustering complete!" << endl;
}
void TrainSVM(vector<Mat> positiveMats, vector<Mat> negativeMats, string svmSave, string vocabularySave)
{
//Setup the BOW
ComputeBow(positiveMats, negativeMats, vocabularySave);
// create training data positive and negative
Mat train, response;
cout << "Creating training sets, this might take a while... ";
for (int i = 0; i < positiveMats.size(); i++)
{
// set training data using BOWImgDescriptorExtractor
vector<KeyPoint> keypoints;
detector->detect(positiveMats[i], keypoints);
Mat descriptors;
bowDE.compute(positiveMats[i], keypoints, descriptors);
if (!descriptors.empty())
{
train.push_back(descriptors); // update training data
response.push_back(1); // update response data
}
}
for (int i = 0; i < negativeMats.size(); i++)
{
// set training data using BOWImgDescriptorExtractor
vector<KeyPoint> keypoints;
detector->detect(negativeMats[i], keypoints);
Mat descriptors ...