Object Detection using SVM
I was following this answer, which explains step by step the coding for svm. But I am having a runtime error in the predict function, here is the code I came up with
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/ml.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
using namespace cv::ml;
int main ( int argc, char** argv )
{
cout << "Manas\n";
char* filename;
Mat input_image;
VideoCapture capture(0);
FileStorage fs;
fs.open("SVM.xml", FileStorage::READ);
Mat SVM_TrainingData;
Mat SVM_Classes;
fs["TrainingData"] >> SVM_TrainingData;
fs["classes"] >> SVM_Classes;
Ptr<SVM> SVM_params = SVM::create();
SVM_params->setType(SVM::C_SVC);
SVM_params->setKernel(SVM::LINEAR);
SVM_params->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 0.01));
Ptr<TrainData> td = TrainData::create(SVM_TrainingData, ROW_SAMPLE, SVM_Classes);
SVM_params->train(td);
while (true)
{
capture.read(input_image);
resize(input_image, input_image, Size(200, 200));
Mat img_gray;
cvtColor(input_image, img_gray, CV_BGR2GRAY);
blur(img_gray, img_gray, Size(5,5));
Mat p= img_gray.reshape(1, img_gray.channels()*img_gray.size().area());
p.convertTo(p, CV_32F);
int response = (int)SVM_params->predict( p );
if(response==1) cout<<"Detected";
imshow("Plate Detected", input_image);
int c = waitKey(10);
if (c == 27)
break;
}
return 0;
}
I am sure I am missing something, but i can't figure out what.Please suggest what else shall i include.
Update
Here is the code that I am using for training my images
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cv.h>
#include <highgui.h>
#include <cvaux.h>
#include <iostream>
#include <vector>
#include<string.h>
using namespace std;
using namespace cv;
int main ( int argc, char** argv )
{
cout << "OpenCV Training SVM Automatic Number Plate Recognition\n";
cout << "\n";
char* path_Plates;
char* path_NoPlates;
int numPlates;
int numNoPlates;
int imageWidth=150;
int imageHeight=150;
//Check if user specify image to process
if(1)
{
numPlates= 12;
numNoPlates= 90 ;
path_Plates= "/home/kaushik/opencv_work/Manas6/Pics/Positive_Images/";
path_NoPlates= "/home/kaushik/opencv_work/Manas6/Pics/Negative_Images/i";
}else{
cout << "Usage:\n" << argv[0] << " <num Plate Files> <num Non Plate Files> <path to plate folder files> <path to non plate files> \n";
return 0;
}
Mat classes;//(numPlates+numNoPlates, 1, CV_32FC1);
Mat trainingData;//(numPlates+numNoPlates, imageWidth*imageHeight, CV_32FC1 );
Mat trainingImages;
vector<int> trainingLabels;
for(int i=1; i<= numPlates; i++)
{
stringstream ss(stringstream::in | stringstream::out);
ss<<path_Plates<<i<<".jpg";
try{
const char* a = ss.str().c_str();
printf("\n%s\n",a);
Mat img = imread(ss.str(), CV_LOAD_IMAGE_UNCHANGED);
img= img.clone().reshape(1, 1);
//imshow("Window",img);
//cout<<ss.str();
trainingImages.push_back(img);
trainingLabels.push_back(1);
}
catch(Exception e){;}
}
for(int i=0; i< numNoPlates; i++)
{
stringstream ss(stringstream::in | stringstream::out);
ss << path_NoPlates<<i << ".jpg";
try
{
const char* a = ss.str().c_str();
printf("\n%s\n",a);
Mat img=imread(ss.str(),CV_LOAD_IMAGE_UNCHANGED);
//imshow("Win",img);
img= img.clone().reshape(1, 1);
trainingImages.push_back(img);
trainingLabels.push_back(0);
//cout<<ss.str();
}
catch(Exception e){;}
}
Mat(trainingImages).copyTo(trainingData);
//trainingData = trainingData.reshape(1,trainingData.rows);
trainingData.convertTo(trainingData, CV_32FC1);
Mat(trainingLabels).copyTo(classes);
FileStorage fs ...
And what is the error? And by the way, are you re-training the SVM in each loop iteration? That's a clear waste of time
Thanx for the suggestion. I removed the train() function outside the loop. The error is samples.cols == var_count. in predict fnction
That means that the sample vectors used for training do not have the same length as the vector provided to the predict function. Make sure you're doing the same operations/resizing in both parts
Thanx @LorenaGdL, but how do I do it ? Shall I upload my train function which saves the xml file?
Let's write-down the proper workflow, because I feel you're not sure about what you're expected to do:
@LorenaGdL thanx for the steps. Seems as if I already have covered the second and third points. But I don't have any clue about the first step. Can you please help me with it. I was using this for converting to 1d array
Mat p= img_gray.reshape(1, img_gray.channels()*img_gray.size().area());
.As I said, you need to use the same function as the one used during the preparation of samples. That for the program to work. To make it work properly (i.e. correctly detecting objects) you will need to use other features rather than pixel values. The topic is extensive, Google will help better there