I'm running opencv 2.4.2 C++.
I'm trying to do people recognition using opencv.
I'm using the VidTIMIT dataset that contains different people in different orientation.
I'm using CvSVM to classify these people.
My problem is that svm's output is always the same.
The algorithm that I follow is:
Now, I'm wondering if I did something wrong in the training.
I'm trying this method considering 5(num_name) person, 10(num_images) different images each.
void runFaceDetectionRecognition(vector<Mat_<uchar> > &images){
vector<vector<Rect> > faces;
for (unsigned i=0; i<images.size(); ++i) {
/// detection face
vector<Rect> f;
faceDetection(images[i], f);
if (!f.empty()) {
faces.push_back(f);
/// I keep only the face
Mat_<uchar> roi = ( images[i](f[0]) );
/// resize
resize(roi, roi, Size(58, 58));
roi.copyTo(images[i]);
}
}
/// Set up parameters
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
/// Set up training data
float labels[num_name][num_images];
float label = 0;
/// different label for different person
for (unsigned i=0; i<num_name; ++i) {
for (unsigned j=0; j<num_images; ++j)
labels[i][j] = label;
label++;
}
/// labeling matrix
Mat labelsMat(num_name*num_images, 1, CV_32FC1, labels);
/// unrolling images
float data[images.size()][58*58];
for (unsigned l=0; l<images.size(); ++l)
for (unsigned i=0; i<58; ++i)
for (unsigned j=0; j<58; ++j)
data[l][j+58*i] = images[l].at<float>(i,j);
/// training matrix
Mat train((int) images.size(),58*58, CV_32FC1, data);
CvSVM svm(train, labelsMat, Mat(), Mat(), params);
/// Validation
valSVM(svm, train.rowRange(0, 1));
}
The validation code:
void valSVM(CvSVM &svm, Mat train){
/// prediction
float response = svm.predict(train);
cout << "Response ===> " << response << " ";
/// output
if (response == 0) cout << "lea";
else if (response == 1) cout << "maria";
else if (response == 2) cout << "ramona";
else if (response == 3) cout << "teresa";
else if (response == 4) cout << "yan";
}
Hope you can help me.
The other answer here is not correct in saying that SVM must use PCA to function. I have used SVM on 128x128 images without PCA and achieved good results. I have done something similar with the cohn-kanade dataset. Here is some source code that may help out.
vector<Mat> preImages;//Fill this with your images from your dataset
vector<int> labels;//Fill this with the labels from the dataset
vector<Mat> images;
CascadeClassifier haar_cascade;
haar_cascade.load("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml");
vector< Rect_<int> > faces;
Mat procFace;
cout << "images: " << preImages.size() << " labels: " << labels.size() << endl;
for(unsigned int i = 0; i < preImages.size(); i++)
{
procFace = preImages[i].clone();
//haar_cascade.detectMultiScale(procFace, faces);
haar_cascade.detectMultiScale(
procFace,
faces,
1.1,
3,
CASCADE_FIND_BIGGEST_OBJECT|CASCADE_DO_ROUGH_SEARCH,
Size(110, 110)
);
if(faces.size() > 0)
{
// Process face by face:
Rect face_i = faces[0];
// Crop the face from the image.
Mat face = procFace(face_i);
////You can maybe use the equalizeHist function here instead//////
face = illuminationComp(face);
//crop face
Rect cropped(face_i.width*0.18, face_i.height*0.2, int(face_i.width*0.7), int(face_i.height*0.78));
Mat Cface = face(cropped);
Mat face_resized;
resize(Cface, face_resized, Size(128, 128), 1.0, 1.0, INTER_CUBIC);
images.push_back(face_resized);
}
}
//svm parameters:
SVMParams params = SVMParams();
params.svm_type = SVM::C_SVC;
params.kernel_type = SVM::LINEAR;
params.degree = 3.43; // for poly
params.gamma = 0.00225; // for poly / rbf / sigmoid
params.coef0 = 19.6; // for poly / sigmoid
params.C = 0.5; // for CV_SVM_C_SVC , CV_SVM_EPS_SVR and CV_SVM_NU_SVR
params.nu = 0.0; // for CV_SVM_NU_SVC , CV_SVM_ONE_CLASS , and CV_SVM_NU_SVR
params.p = 0.0; // for CV_SVM_EPS_SVR
params.class_weights = NULL; // for CV_SVM_C_SVC
params.term_crit.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
params.term_crit.max_iter = 1000;
params.term_crit.epsilon = 1e-6;
if(images.size() == labels.size())
{
cout << "Creating SVM Classification" << endl << endl;
int rowsSize = images.size();
int trainingArea = images[0].rows * images[0].cols;
Mat trainingMat = Mat::zeros(rowsSize, trainingArea, CV_32FC1);
int counter;
for(int index = 0; index < rowsSize; index++)
{
counter = 0;
for(int rows = 0; rows < images[0].rows; rows++)
{
for(int cols = 0; cols < images[0].cols; cols++)
{
trainingMat.at<float>(index, counter) = images[index].at<uchar>(rows,cols);
counter++;
}
}
}
Mat matLabels = Mat::zeros(labels.size(),1,CV_32FC1);
for(size_t index = 0; index < labels.size(); index++)
{
matLabels.at<float>(index,0) = float(labels[index]);
}
if(trainingMat.rows == matLabels.rows)
{
SVM svm;
svm.train(trainingMat,matLabels,Mat(),Mat(),params);
svm.save("svm_model.yml");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With