Assertion Failure in SVM Predcit (OpenCV 3.0)

asked 2017-10-24 16:31:25 -0500

asa gravatar image

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 ... (more)

edit retag flag offensive close merge delete

Comments

there are some problems here:

1) you can only use float descriptors, like SIFT,SURF or KAZE with BowKMeans. NOT ORB, which is a binary one. trying to cheat, by converting it to float won't help. there is simply no mean value between bits.

2) all your conversions and preallocated output Mat's are useless, and only fool yourself making wrong assumptions about sizes and datatypes. converting features to float is as wrong as converting the vocabulary to uchar.

berak gravatar imageberak ( 2017-10-25 01:28:19 -0500 )edit