OpenCV BoW assert error while computing histograms for SVM training - c++

I am trying to do classification of images with combining SIFT features, Bag of Visual Words and SVM.
Now I am on training part. I need to get BoW histograms for each training image to be able to train SVM. For this I am using BOWImgDescriptorExtractor from OpenCV. I am using OpenCV version 3.1.0.
The problem is that it computes histogram for some images, but for some of images it gives me this error:
OpenCV Error: Assertion failed (queryIdx == (int)i) in compute,
file /Users/opencv-3.1.0/modules/features2d/src/bagofwords.cpp, line 200
libc++abi.dylib: terminating with uncaught exception of type
cv::Exception: /Users/opencv-3.1.0/modules/feature/src/bagofwords.cpp:200: error: (-215) queryIdx == (int)i in function compute
Training images are all of the same size, all have same number of channels.
For creating dictionary I use another image set than for training SVM.
Here's part of code:
Ptr<FeatureDetector> detector(cv::xfeatures2d::SIFT::create());
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_L2, true));
BOWImgDescriptorExtractor bow_descr(det, matcher);
bow_descr.setVocabulary(dict);
Mat features_svm;
for (int i = 0; i < num_svm_data; ++i) {
Mat hist;
std::vector<KeyPoint> keypoints;
detector->detect(data_svm[i], keypoints);
bow_descr.compute(data_svm[i], keypoints, hist);
features_svm.push_back(hist);
}
data_svm is a vector<Mat> type. It is my training set images which I will use in SVM.
What the problem can be?

I ran into the same issue. I was able to fix it by changing the cross check option of the Brute Force matcher to False. I think its because the cross check option keeps only a select few matches and removes the rest and messes up the indexes in the process

Related

Learning a SVM with Bag of features

Hello I try to learn a SVM with a Dataset of negative and positive examples.
Iam using the Kmeans Clustering and Bag of Words for it.
My steps are:
compute the descriptors and key points for each image with surf
put all descriptors in one mat (unclustered mat) and create the label mat(1 and -1)
using K-Means for clustering put in the unclustered mat and run the algorithm the result is the vocabulary
start the Bag of features procedure with BowImgDescriptorExtractor using the FlannBasedMatcher and the Surf detector for it
set the extracted vocabulary to BowImgDescriptorExtractor
compute bow with img, imgkeypoints
the result is a bow descriptor
train the SVM with the bowdescritpor and the labels
The syntax is correct, but if I use svm->islearned the svm returns false.
Something in my procedure is wrong. Please give me some advice what Iam doing wrong

Opencv 3.0 Brisk feature detection with a ROI and Flann matching

I have a simple program that uses Brisk detection and flann matching. I'm looking to improve the efficiency by applying the detection to a specific region of interest in each frame. I've tried the following:
cv::Mat ROI_scene, scene;
//region of interest
cv::Rect myROI(10, 10, 100, 100);
cv::Ptr<BRISK> detector = BRISK::create();
cv::Ptr<BRISK> descriptorExtractor = BRISK::create();
while ( capture.read(scene) )
{
ROI_scene = scene(myROI);
detector->detect(ROI_scene, keypoints_scene);
descriptorExtractor->compute(ROI_scene, keypoints_scene, descriptors_scene);
matcher.match(descriptors_object, descriptors_scene, matches);
}
The above returns this error:
OpenCV Error: Bad argument (Only continuous arrays are supported) in
buildIndex_, file opencv/3.0.0/modules/flann/src/miniflann.cpp, line
317 libc++abi.dylib: terminating with uncaught exception of type
cv::Exception: opencv/3.0.0/modules/flann/src/miniflann.cpp:317:
error: (-5) Only continuous arrays are supported in function
buildIndex_
Abort trap: 6
I've also tried using copyTO and then I get a Arrays must be 2d or 3d error.
Any insight would be really helpful
Here is a gist of the working code:
https://gist.github.com/DevN00b1/63eba5813926e4d0ea32

Assertion failed (queryDescriptors.type() == trainDescCollection[0].type()) in knnMatchImpl,

when using BOWImgDescriptorExtractor with DescriptorExtractor as SIFT and DescriptorMatcher as ButeForce i am getting error as
OpenCV Error: Assertion failed (queryDescriptors.type() == trainDescCollection[0].type()) in knnMatchImpl,
what could me my error.
when i am trying to compute
eg.
bowide->compute(img, keypoints, response_hist);
I had the same error using the Surf feature detector and extractor with BFMatcher.
The error occurs because the query descriptor mat and train descriptor mat doesn't have the same type - as stated in your error message.
This happened to me only when no keypoints for the train or query image could be calculated by the feature detector.
Check that the size of your keypoints vector is not zero before doing the matching.
I also had the same error. There is another possible reason: the dtype of the dictionary should be float32. It turns out that I did some operations with the dictionary with numpy before calling the setVocabulary function, which changed the dtype of the dictionary implicitly.

OpenCV SVM throwing exception on train, "Bad argument (There is only a single class)"

I'm stuck on this one.
I am trying to do some object classification through OpenCV feature 2d framework, but am running into troubles on training my SVM.
I am able to extract vocabularies and cluster them using BowKMeansTrainer, but after I extract features from training data to add to the trainer and run SVM.train method, I get the following exception.
OpenCV Error: Bad argument (There is only a single class) in cvPreprocessCategoricalResponses, file /home/tbu/prog/OpenCV-2.4.2/modules/ml/src /inner_functions.cpp, line 729
terminate called after throwing an instance of 'cv::Exception'
what(): /home/tbuchy/prog/OpenCV-2.4.2/modules/ml/src/inner_functions.cpp:729: error: (-5) There is only a single class in function cvPreprocessCategoricalResponses
I have tried modifying dictionary size, using different trainers, ensuring my matrix types are correct (to the best of my ability, still new to opencv).
Has any seen this error or have any insight on how to fix it?
My code looks like this:
trainingPaths = getFilePaths();
extractTrainingVocab(trainingPaths);
cout<<"Clustering..."<<endl;
Mat dictionary = bowTrainer.cluster();
bowDE.setVocabulary(dictionary);
Mat trainingData(0, dictionarySize, CV_32FC1);
Mat labels(0, 1, CV_32FC1);
extractBOWDescriptor(trainingPaths, trainingData, labels);
//making the classifier
CvSVM classifier;
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
classifier.train(trainingData, labels, Mat(), Mat(), params);
Based on the error, it looks like your labels only contains one category of data. That is, all of the features in your trainingData have the same label.
For example, say you're trying to use the SVM to determine whether an image contains a cat or not. If every entry in the labels is the same, then either...
all your training images are labeled as "yes this is a cat"
or, all your training images are labeled as "no, this is not a cat."
SVMs try to separate two (or sometimes more) classes of data, so the SVM library complains if you only only provide one class of data.
To see if this is the problem, I recommend adding a print statement to check whether labels only contains one category. Here's some code to do this:
//check: are the printouts all the same?
for(int i=0; i<labels.rows; i++)
for(int j=0; j<labels.cols; j++)
printf("labels(%d, %d) = %f \n", i, j, labels.at<float>(i,j));
Once your extractBOWDescriptor() loads data into labels, I'm assuming that labels is of size (trainingData.rows, trainingData.cols). If not, this could be a problem.

Trying to match two images using sift in OpenCv, but too many matches

I am trying to implement a program which will input two images one is an image of a box alone and one which includes the box in the scene. Basically, the program is supposed to find keypoints in these two images and will show the images with keypoints matched. That is in the end I expect to see an appended image of two input images together with their matched keypoints connected. My code is as follows:
#include <opencv2\opencv.hpp>
#include <iostream>
int main(int argc, const char* argv[]) {
cv::Mat input1 = cv::imread("input.jpg", 1); //Load as grayscale
//cv::cvtColor(input1,input1,CV_BGR2GRAY);
//second input load as grayscale
cv::Mat input2 = cv::imread("input2.jpg",1);
cv::SiftFeatureDetector detector;
//cv::SiftFeatureDetector
detector(
1, 1,
cv::SIFT::CommonParams::DEFAULT_NOCTAVES,
cv::SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
cv::SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
cv::SIFT::CommonParams::FIRST_ANGLE );
std::vector<cv::KeyPoint> keypoints1;
detector.detect(input1, keypoints1);
// Add results to image and save.
cv::Mat output1;
cv::drawKeypoints(input1, keypoints1, output1);
cv::imshow("Sift_result1.jpg", output1);
cv::imwrite("Sift_result1.jpg",output1);
//keypoints array for input 2
std::vector<cv::KeyPoint> keypoints2;
//output array for ouput 2
cv::Mat output2;
//Sift extractor of opencv
cv::SiftDescriptorExtractor extractor;
cv::Mat descriptors1,descriptors2;
cv::BruteForceMatcher<cv::L2<float>> matcher;
cv::vector<cv::DMatch> matches;
cv::Mat img_matches;
detector.detect(input2,keypoints2);
cv::drawKeypoints(input2,keypoints2,output2);
cv::imshow("Sift_result2.jpg",output2);
cv::imwrite("Sift_result2.jpg",output2);
extractor.compute(input1,keypoints1,descriptors1);
extractor.compute(input2,keypoints2,descriptors2);
matcher.match(descriptors1,descriptors2,matches);
//show result
cv::drawMatches(input1,keypoints1,input2,keypoints2,matches,img_matches);
cv::imshow("matches",img_matches);
cv::imwrite("matches.jpg",img_matches);
cv::waitKey();
return 0;
}
The problem is there are two many many matches than expected. I tried to debug the program and looked what is inside the keypoints vectors and so on, everything looks to be fine, at least I think they are, the keypoints are detected with orientation etc.
I am using OpenCV v2.3 and checked its documentation for the types of classes I am using and tried to solve the problem but that did not work. I am working on this for a 3 days did not make much of an improvement.
Here is an output i get from my program.
I should have remove the image.
I know that should not give me too much matches, because I have tested the exact same images with another implemenation in matlab that was quite good.
Rather than using BruteForceMatcher try to use FlannBasedMatcher and also calculate max and min distances between keypoints to keep only the good matches. See "Feature Matching with FLANN" for an example.
I faced the same problem for SIFT.
I used knn matcher (K=3). and followed following procedure iteratively
{
Calculated best affine transform with least square method.
Found out the transform for all keypoints in source image.
Checked out MaxError and MinError.
Points with Error near MaxError are removed from the matching list
}