SVM trained model recognizes false image as true
I have a simple SVM code to train and test the model for checking whether the image is an eye or not. While testing the generated model using the same train images, for a non-eye image, it returns 1(which means eye). Here is the training code and testing code.
int main ( int argc, char** argv )
{
cout << "OpenCV Training SVM Eye Recognition\n";
cout << "\n";
char *Eyes;
char *NoEyes;
int numEyes;
int numNoEyes;
int imageWidth=16;
int imageHeight=16;
int imgSize = (imageWidth * imageHeight);
unsigned char buffer[imgSize];
//Validate the arguments
if(argc >= 5 )
{
numEyes= atoi(argv[1]);
numNoEyes= atoi(argv[2]);
Eyes= argv[3];
NoEyes= argv[4];
}else{
cout << "Usage:\n" << argv[0] << " <num Eye Files> <num Non Eye Files> <path to eye folder files> <path to non eye files> \n";
return 0;
}
int num_files = (numEyes + numNoEyes);
int file_num = 0;
Mat training_mat(num_files,imgSize,CV_32FC1);
Mat labels(num_files, 1, CV_32SC1);
for(int m = 0; m < numEyes; m++)
{
stringstream ss(stringstream::in | stringstream::out);
ss << Eyes << m << ".yuv";
cout << ss.str() << endl;
FILE *fp;
fp = fopen(ss.str().c_str(), "rb");
if (fp == NULL) {
break;
} else {
if (fread(buffer, 1, imgSize, fp) != imgSize) {
break;
}
fclose(fp);
}
for (int i = 0; i < imageWidth*imageHeight; i++) {
training_mat.at<float>(file_num, i) = ((float)buffer[i] / 1000.0f);
}
labels.at<int>(file_num) = 1;
file_num++;
}
for(int m = 0; m < numNoEyes; m++)
{
stringstream ss(stringstream::in | stringstream::out);
ss << NoEyes << m << ".yuv";
cout << ss.str() << endl;
FILE *fp;
unsigned char buffer[imgSize];
fp = fopen(ss.str().c_str(), "rb");
if (fp == NULL) {
break;
} else {
if (fread(buffer, 1, imgSize, fp) != imgSize) {
break;
}
fclose(fp);
}
for (int i = 0; i < imgSize; i++) {
training_mat.at<float>(file_num, i) = ((float)buffer[i] / 1000.0f);
}
labels.at<int>(file_num) = -1;
file_num++;
}
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::RBF;
params.C = 10.0f;
params.gamma = 8;
params.term_crit = cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001);
CvSVM SVM;
SVM.train(training_mat, labels, Mat(), Mat(), params);
SVM.save("train.xml");
return 0;
}
Here is the code for testing the model :
using namespace std;
using namespace cv;
int main ( int argc, char** argv )
{
cout << "OpenCV Test - checking whether the given image is eye or not\n";
cout << "\n";
int segWidth=16;
int segHeight=16;
int imgSize = (segWidth * segHeight);
//Validate argument
if(argc < 2 )
{
cout << "Usage:\n" << argv[0] << " <Test image file> \n";
return 0;
}
stringstream ss(stringstream::in | stringstream::out);
ss << argv[1];
cout << ss.str() << endl;
Mat test_data(1, imgSize, CV_32FC1);
FILE *fp;
unsigned char buffer[imgSize];
fp = fopen(ss.str().c_str(), "rb");
if (fp != NULL) {
fread(buffer, 1, imgSize, fp);
fclose(fp);
}
CvSVM svm;
svm.load("train.xml");
for (int m = 0; m < imgSize; m++) {
test_data.at<float>(0, m++) = ((float)buffer[m] / 1000.0f);
}
float response = svm.predict(test_data);
cout << response << endl;
return 0;
}
Note: I am using OpenCV 2.4.8. I have ...
"I am using OpenCV 2.4.8" -- that's sad.
"I have given 7 eye images and 4 non-eye images " -- you would need ~500 images each.
you also have to consider left and right eyes here, imho.
Even to test against the same trained images?
testing against trained images is wrong, too.