thanks for your help...
I wrote some code a while ago that successfully detects cars in a moving video of traffic. So lets consider the output of that code and the eventual input of this code to be 150x200 sized images of vehicles.
What I am trying to implement is an SVM that takes those vehicles and can classify them between sedans and SUVs. (Assume there are only sedans and SUVs).
The following code was implemented by closely following the information on this link: https://docs.opencv.org/3.0-beta/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html and this link: using OpenCV and SVM with images
Be aware that the syntax affiliated with these links are slightly outdated for SVM implementation on the newest version of SVMs which I have.
//Used to read multiple files from folder
stringstream ss;
string name = "Vehicle_";
string type = ".jpg";
int num_train_images = 29; //29 images will be used to train the SVM
int image_area = 150 * 200;
Mat training_mat(num_train_images, image_area, CV_32FC1); // Creates a 29 rows by 30000 columns... 29 150x200 images will be put into 1 row per image
//Converts 29 2D images into a really long row per image
for (int file_count = 1; file_count < (num_train_images + 1); file_count++)
{
ss << name << file_count << type; //'Vehicle_1.jpg' ... 'Vehicle_2.jpg' ... etc ...
string filename = ss.str();
ss.str("");
Mat training_img = imread(filename, 1); //Reads the training images from the folder
int ii = 0; //Scans each column
for (int i = 0; i < training_img.rows; i++)
{
for (int j = 0; j < training_img.cols; j++)
{
training_mat.at<float>(file_count - 1, ii) = training_img.at<uchar>(i, j); //Fills the training_mat with the read image
ii++;
}
}
}
//Labels are used as the supervised learning portion of the SVM. If it is a 1, its an SUV test image. -1 means a sedan.
float labels[29] = { 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1 };
//Place the labels into into a 29 row by 1 column matrix.
Mat labels_mat(num_train_images, 1, CV_32FC1, labels);
cout << "Beginning Training..." << endl;
//Set SVM Parameters (not sure about these values)
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
svm->train(training_mat, ROW_SAMPLE, labels_mat);
cout << "End Training" << endl;
waitKey(0);
Mat test_image(1, image_area, CV_32FC1); //Creates a 1 x 30000 matrix to house the test image.
Mat SUV_image = imread("SUV_1.jpg", 0); //Read the file folder
int jj = 0;
for (int i = 0; i < SUV_image.rows; i++)
{
for (int j = 0; j < SUV_image.cols; j++)
{
test_image.at<float>(0, jj) = SUV_image.at<uchar>(i, j); //Fills the training_mat
jj++;
}
}
//Should return a 1 if its an SUV, or a -1 if its a sedan
svm->predict(test_image);
waitKey(0);
So what I do here is I take the test images and then transform each 150 by 200 image into a 1 row by 30,000 column row in the training_mat.
labels_mat is the supervised learning portion of the SVM which tells if the training images are SUVs or sedans.
The code builds fine, but unfortunately right as it gets to svm->train it fails and I get an abort error that says: "OpenCV Error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainData, or pass integer responses) in cv::ml::SVMImpl::train"
Not quite sure what this means, could be something wrong with my parameters. A friend suggested I may need to extract features of the images before I can feed it into the SVM, to which I'm not sure if its necessary.
Thanks