Skip to content

bkornel/OpenCV_BOW_SVM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenCV_BOW_SVM

A simple object classifier with Bag-of-Words using OpenCV 3.0

The vocabulary is created by BOWKMeansTrainer and we have a feature detector, extractor, matcher and a BOW image descriptor extractor (to compute an image descriptor using the bag of visual words) such as:

cv::Ptr<cv::FeatureDetector> detector = cv::FeatureDetector::create("SURF");
cv::Ptr<cv::DescriptorExtractor> extractor = cv::DescriptorExtractor::create("SURF");
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce ");

cv::BOWImgDescriptorExtractor bowide(extractor, matcher);
bowide->setVocabulary(vocabulary);

First of all we need to scour the training set for our histograms:

cv::Mat samples;
cv::Mat labels(0, 1, CV_32FC1);
	
for(auto& it : imagePosDir)
{
	cv::Mat image = cv::imread(it);
	
	std::vector<cv::KeyPoint> keypoints;
	detector->detect(image, keypoints);
	
	if(keypoints.empty()) continue;
	
	// Responses to the vocabulary
	cv::Mat imgDescriptor;
	bowide.compute(image, keypoints, imgDescriptor);
	
	if(imgDescriptor.empty()) continue;
	
	if(samples.empty())
	{
		samples.create(0, imgDescriptor.cols, imgDescriptor.type());
	}
	
	// Copy class samples and labels
	std::cout << "Adding " << imgDescriptor.rows << " positive sample." << std::endl;
	samples.push_back(imgDescriptor);
	
	cv::Mat classLabels = cv::Mat::ones(imgDescriptor.rows, 1, CV_32FC1);
	labels.push_back(classLabels);
}

Do the same for imagePosNeg except that classLabels will have zero values, such as:

...
cv::Mat classLabels = cv::Mat::zeros(imgDescriptor.rows, 1, CV_32FC1);
labels.push_back(classLabels);
...

Note how I build the samples and the labels, I marked the positive samples with labels '1', and then the negatives with label '0'. So we have the training data for each class (here for positives and negatives) in samples. Lets's get training:

cv::Mat samples_32f; 
samples.convertTo(samples_32f, CV_32F);

CvSVM svm; 
svm.train(samples_32f, labels);
// Do something with the classifier, like saving it to file

Then testing let's get testing the classifier:

for(auto& it : testDir)
{
	cv::Mat image = cv::imread(it);
	
	std::vector<cv::KeyPoint> keypoints;
	detector->detect(image, keypoints);
	
	if(keypoints.empty()) continue;
	
	// Responses to the vocabulary
	cv::Mat imgDescriptor;
	bowide.compute(image, keypoints, imgDescriptor);
	
	if(imgDescriptor.empty()) continue;
	
	float res = svm.predict(imgDescriptor, true);
	
	std::cout << "- Result of prediction: " << res << std::endl;
}