BoW + SVM won't work [closed]
Hello, I'm trying to implement a BoW + SVM method for classification that takes several images for class one and two and then classifies the query image based on those. For some reason after constructing bow descriptor, it returns an empty descriptor vector thus I can't train the SVM let alone classify. Relevant part of my code is below, I'd appreciate any insight. Thanks a lot.
Ptr<FeatureDetector> features = FeatureDetector::create("SIFT");
Ptr<DescriptorExtractor> descriptor = DescriptorExtractor::create("SIFT");
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
//defining terms for bowkmeans trainer
TermCriteria tc(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 10, 0.001);
int dictionarySize = 100;
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(dictionarySize, tc, retries, flags);
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
BOWImgDescriptorExtractor bowDE(descriptor, matcher);
Mat features1, features2;
Mat bowDescriptor, bowDescriptor2;
Mat trainme(0, dictionarySize, CV_32FC1);
Mat labels(0, 1, CV_32FC1);
.....
while (dirp = readdir( dp ))
{
filepath = dir + "/" + dirp->d_name;
// If the file is a directory (or is in some way invalid) we'll skip it
if (stat( filepath.c_str(), &filestat )) continue;
if (S_ISDIR( filestat.st_mode )) continue;
Mat img = imread(filepath);
if (!img.data) {
cout <<"Can't open file." << endl;
continue;
}
features->detect(img, keypoints);
descriptor->compute(img, keypoints, features1);
bowDE.compute(img, keypoints, bowDescriptor);
trainme.push_back(bowDescriptor);
float label = 1.0;
labels.push_back(label);
bowTrainer.add(features1);
cout << "." << endl;
}
while (dirp2 = readdir( dp2 ))
{
filepath2 = dir2 + "/" + dirp2->d_name;
// If the file is a directory (or is in some way invalid) we'll skip it
if (stat( filepath2.c_str(), &filestat2 )) continue;
if (S_ISDIR( filestat2.st_mode )) continue;
Mat img2 = imread(filepath2);
if (!img2.data) {
cout <<"Can't open file." << endl;
continue;
}
features->detect(img2, keypoints2);
descriptor->compute(img2, keypoints2, features2);
bowDE.compute(img2, keypoints2, bowDescriptor2);
trainme.push_back(bowDescriptor2);
float label = 0.0;
labels.push_back(label);
bowTrainer.add(features2);
cout << "." << endl;
}
Mat dictionary = bowTrainer.cluster();
bowDE.setVocabulary(dictionary);
CvSVM SVM;
SVM.train(trainme,labels);
Mat tryme(0, dictionarySize, CV_32FC1);
Mat tryDescriptor;
Mat img3 = imread("c:\\Users\\Elvan\\Desktop\\frame_0118.jpg", 0);
vector<KeyPoint> keypoints3;
features->detect(img3, keypoints3);
bowDE.compute(img3, keypoints3, tryDescriptor);
tryme.push_back(tryDescriptor);
cout<<SVM.predict(tryme)<<endl;
solved the BowDE.compute issue. But still the SVM says that the input argument is not a valid vector.
Which input argument? From your train or from your predict-statement? What is the exact error message ( and from which line does it stem ) ? Afaik the labels should be of type int ( cv::Mat1i / oder cv::Mat with type CV_32SC1 ).
Solved the problem, I was getting the "Bad input argument" in SVM.predict line, turns out the file was corrupt, that's all.