Assertion Failure in SVM Predcit (OpenCV 3.0) [closed]
Hi I was trying out the Bag of Words to classify images. I tried a simple example:
- train n images of same object (n = 4 for starter)
- create BoW vocabulary: I used ORB feature descriptors to create my BoW vocab
- train svm with the histogram responses from BoW
- 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 ...
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.