Ask Your Question

Training SVM for image recognition with BOW: error on prediction

asked 2016-09-09 15:42:41 -0500

Reeven gravatar image

updated 2016-09-13 10:08:28 -0500


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:

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);

//... 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();
    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 ...
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2016-09-12 08:56:00 -0500

Reeven gravatar image

Answer: I was loading the SVM incorrectly, as per this other question:

in opencv3, Algorithm::load() creates a new instance, so you have to load your SVM like:

Ptr<ml::svm> classifier = Algorithm::load<ml::svm>(filename); (in your original code, the newly loaded model was discarded, never transferred to your classifier instance)

edit flag offensive delete link more

Question Tools



Asked: 2016-09-09 15:38:02 -0500

Seen: 1,229 times

Last updated: Sep 13 '16