Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Assertion Failure in SVM Predcit (OpenCV 3.0)

Hi I was trying out the Bag of Words to classify images. I tried a simple example:

  1. train n images of same object (n = 4 for starter)
  2. create BoW vocabulary: I used ORB feature descriptors to create my BoW vocab
  3. train svm with the histogram responses from BoW
  4. use trained svm for prediction

The first 3 steps seems to be working fine: Here is code of training part (upto step 3):

// Read All image files in training directory and save their names //
std::vector<cv::String> filenames;
cv::String directory = argv[1];
cv::glob(directory, filenames);

// detect ORB features from each image and store them //
cv::Mat orb_cluster;
cv::Mat orb_descriptor;
cv::Ptr<cv::Feature2D> orb_detector = cv::ORB::create(500, 1.2f, 8, 31, 0,2, cv::ORB::HARRIS_SCORE, 31, 20);
cv::Ptr<cv::DescriptorExtractor> orb_extractor = cv::ORB::create();

std::vector<cv::KeyPoint> orb_kp;

for(size_t t = 0; t < filenames.size(); t++)
{
    cv::Mat input;
    input = cv::imread(filenames[t], 0);

    orb_detector->detect(input, orb_kp);            // detect keypoints
    orb_extractor->compute(input, orb_kp, orb_descriptor);  // extract orb descriptors
    orb_cluster.push_back(orb_descriptor);          // store the descriptors

}

cv::Mat orb_cluster_f(orb_cluster.rows, orb_cluster.cols, CV_32F);
orb_cluster.convertTo(orb_cluster_f, CV_32F);

cv::Mat orb_dictionary; 
int bag_size = 100;
cv::TermCriteria bow_tc(CV_TERMCRIT_ITER,100,0.001);

cv::BOWKMeansTrainer bow_km_trainer(bag_size, bow_tc, 2);
orb_dictionary = bow_km_trainer.cluster(orb_cluster_f);     // train the BoW and create the dictionary

std::cout << "ORB Dictionary Created" << std::endl;

// Store the dictionary //
cv::FileStorage orb_fs("./train_vocab/orb_dict.yml", cv::FileStorage::WRITE);
orb_fs << "orb_vocabulary" << orb_dictionary;
orb_fs.release();

std::cout << "ORB Dictionary Stored" << std::endl;

// *************** Create Training Data ********************* //

cv::Mat t_orb_dictionary_f;
cv::FileStorage t_orb_fs("./train_vocab/orb_dict.yml", cv::FileStorage::READ);
t_orb_fs["orb_vocabulary"] >> t_orb_dictionary_f;
t_orb_fs.release();

cv::Mat t_orb_dict(t_orb_dictionary_f.rows, t_orb_dictionary_f.cols, CV_8U);
t_orb_dictionary_f.convertTo(t_orb_dict, CV_8U);

cv::Mat bow_histogram;
cv::Mat train_data;

std::vector<cv::KeyPoint> t_orb_kp; // keypoints
cv::Ptr<cv::Feature2D> t_orb_detector = cv::ORB::create(500, 1.2f, 8, 31, 0,2, cv::ORB::HARRIS_SCORE, 31, 20);  // detector
cv::Ptr<cv::DescriptorExtractor> t_orb_extractor = cv::ORB::create();   //extractor

cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");   
cv::Ptr<cv::BOWImgDescriptorExtractor> bow_de(new cv::BOWImgDescriptorExtractor(t_orb_extractor, matcher));     // BOW extractor

bow_de->setVocabulary(t_orb_dict);  // set the vocabulary //

for(size_t t = 0; t < filenames.size(); t++)
{
    cv::Mat t_input;
    t_input = cv::imread(filenames[t], 0);

    t_orb_detector->detect(t_input, t_orb_kp);      // detect keypoints
    bow_de->compute(t_input, t_orb_kp, bow_histogram);  // create the response histogram        
    train_data.push_back(bow_histogram);    // create the training data     
}

std::cout << "Training SVM..." << std::endl;

//int labels[1] = {1};
//cv::Mat m_labels = cv::Mat::ones(train_data.rows, 1, CV_32SC1);
//cv::Mat m_labels(1, 1, CV_32SC1, labels);
// i have only 1 class, hence added labels 1 for all samples 
std::vector<int> m_labels;
for(int i = 0; i < train_data.rows; i++)
{
    m_labels.push_back(1);
}

cv::Ptr<cv::ml::SVM> svm_classifier = cv::ml::SVM::create();    

svm_classifier->setType(cv::ml::SVM::ONE_CLASS);
svm_classifier->setKernel(cv::ml::SVM::POLY);
svm_classifier->setGamma(3);
svm_classifier->setDegree(2);
svm_classifier->setCoef0(1.0);
svm_classifier->setNu(0.5);

svm_classifier->train( train_data , cv::ml::ROW_SAMPLE , m_labels );

svm_classifier->save("./train_svm/svm_bow.yml");

up to this point the code runs fine. I get the .yml files.

This is the testing code:

// ************ Test the Classifier ************* //
cv::Ptr<cv::ml::SVM> test_svm = cv::ml::SVM::create();
test_svm->load("./train_svm/svm_bow.yml");

cv::Mat test_orb_dict_f;
cv::FileStorage test_orb_fs("./train_vocab/orb_dict.yml", cv::FileStorage::READ);
test_orb_fs["orb_vocabulary"] >> test_orb_dict_f;
test_orb_fs.release();

cv::Mat test_orb_dict(test_orb_dict_f.rows, test_orb_dict_f.cols, CV_8U);
test_orb_dict_f.convertTo(test_orb_dict, CV_8U);

std::vector<cv::KeyPoint> test_orb_kp;  // keypoints
cv::Ptr<cv::Feature2D> test_orb_detector = cv::ORB::create(500, 1.2f, 8, 31, 0,2, cv::ORB::HARRIS_SCORE, 31, 20);   // detector
cv::Ptr<cv::DescriptorExtractor> test_orb_extractor = cv::ORB::create();    //extractor

cv::Ptr<cv::DescriptorMatcher> test_matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");  
cv::Ptr<cv::BOWImgDescriptorExtractor> test_bow_de(new cv::BOWImgDescriptorExtractor(test_orb_extractor, test_matcher));        // BOW extractor

test_bow_de->setVocabulary(test_orb_dict);  // set the vocabulary //

cv::Mat test_in = cv::imread("./test_img/t1.tif", 0);   
cv::Mat test_bow_histogram;
test_orb_detector->detect(test_in, test_orb_kp);        // detect keypoints
test_bow_de->compute(test_in, test_orb_kp, test_bow_histogram); // create the response histogram
cv::Mat test_bow_hist_f(test_bow_histogram.rows, test_bow_histogram.cols, CV_32FC1);
test_bow_histogram.convertTo(test_bow_hist_f, CV_32FC1);

cv::Mat result;
float r = test_svm->predict(test_bow_hist_f, result); // this is where the assertion falis

The error message:

OpenCV Error: Assertion failed (samples.cols == var_count && samples.type() == CV_32F) in predict, file /home/asa/asa_wd_mount/trunk/projects/mvs/3rd_party/opencv/opencv-master/modules/ml/src/svm.cpp, line 1930 terminate called after throwing an instance of 'cv::Exception' what(): /home/asa/asa_wd_mount/trunk/projects/mvs/3rd_party/opencv/opencv-master/modules/ml/src/svm.cpp:1930: error: (-215) samples.cols == var_count && samples.type() == CV_32F in function predict

Now, I am using one of the training image as test image. the svm .yml file says var_count = 100 part of the .yml file:

%YAML:1.0 opencv_ml_svm:
format: 3 svmType: ONE_CLASS
kernel: type: POLY degree: 2. gamma: 3. coef0: 1.
nu: 5.0000000000000000e-01
term_criteria: { epsilon:1.1920928955078125e-07, iterations:1000 }
var_count: 100
class_count: 1
sv_total: 2

I have also checked the size of the test histogram "test_bow_hist_f". it has 1 row and 100 columns. my training data has 4 training samples, each 100 columns.

I have been getting the same assertion fail.

any help on what am I doing wrong would be greatly appreciated.

Thanks