-2

我尝试过使用支持向量机进行人脸识别,下面是我用于培训和测试的代码。问题是我没有得到准确的结果,有时我总是将预测值作为“0”。使用支持向量机的人脸识别

有人能帮助我解决正确的SVM参数。

培训代码:

static void read_csv(const string& filename, vector<Mat>& images, vector<int>& label, char separator = ';') { 
    std::ifstream file(filename.c_str(), ifstream::in); 
    if (!file) { 
     string error_message = "No valid input file was given, please check the given filename."; 
     CV_Error(CV_StsBadArg, error_message); 
    } 
    string line, path, classlabel; 
    while (getline(file, line)) { 
     stringstream liness(line); 
     getline(liness, path, separator); 
     getline(liness, classlabel); 
     if(!path.empty() && !classlabel.empty()) { 
      Mat testimage = imread(path, 0); 
      imshow("testimage", testimage); 
      waitKey(10); 
      images.push_back(testimage); 
      label.push_back(atoi(classlabel.c_str())); 
     } 
    } 
} 
int svm() 
{ 
    // Data for visual representation 

    string fn_csv = string("/home/resize.csv"); 
//  These vectors hold the images and corresponding labels. 
    vector<Mat> images; 
    vector<int> label; 
//  Read in the data. This can fail if no valid 
//  input filename is given. 
    try { 
     read_csv(fn_csv, images,label); 
    } catch (cv::Exception& e) { 
     cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl; 
//   nothing more we can do 
     exit(1); 
    } 
    // Set up SVM's parameters 
    Mat labelsMat(label.size(), 1, CV_32FC1); 
     Mat trainingDataMat(images.size(),70*70, CV_32FC1); 

       //iterating through the rows 
     int c=0;int d; 
       for (int j = 0; j <label.size(); j++) { 
        //iteration through the columns 
        d=0; 
        c++; 
        labelsMat.at<float>(j,0)=float(label[j]); 
        for (int r = 0;r<images[j].rows; r++) { 
       //iterating through the rows 
       for (int c = 0; c <images[j].cols; c++) { 
       trainingDataMat.at<float>(j,d++) = images[j].at<uchar>(r,c); 

       } 
        } 
       } 

    //imshow("first",images[7]); 
     cout<<"labels"<<labelsMat<<std::endl; 
    cout<<"labels size"<<c<<std::endl; 
    // CvSVMParams params; 

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; 

    // Train the SVM 
    CvSVM SVM; 
    SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); 
    // cout<<"train row" <<trainingDataMat.rowRange()<<"cols"<<trainingDataMat.cols<<std::endl; 
SVM.save("/home/test.yml"); 

    return 0; 

}

预测代码:

int svm_test() 
{ 

    // Train the SVM 
    CvSVM SVM; 

    Mat test=imread("/home/n2.jpg",0); 
// cout<<"image size"<<(float(test.size))<<std::endl; 
Mat test_mat(1,test.cols*test.rows,CV_32FC1); 
    int ii1=0; 
for (int i1 = 0; i1<test.rows; i1++) { 
       //iterating through the rows 

       for (int j1 = 0; j1 < test.cols; j1++) { 
        //iteration through the columns 

       test_mat.at<float>(0,ii1++) = test.at<uchar>(i1,j1); 
       // labels.at<float>(filenum,1);//=float(filenum); 
       } 
      } 
    // waitKey(0); 
SVM.load("/home/smile.yml"); 

cout<<"preditction value"<<SVM.predict(test_mat)<<std::endl; 


    return 0; 

} 

回答

2

以及你的代码看起来脏脏的,所以我不会去超过他们,但我会试着给你一些关于这个过程的提示。

首先你需要训练集,并确保你有更多的负面训练数据比积极的好结果。另外请注意,您需要安静地处理大量的脸部以获得良好的效果,并且平均分辨率或平均分辨率可能低于100-200。

第二次从脸上提取特征,在那里你可以使用像,颜色,边缘直方图或二进制像Patters等。选择是你的。但少数卷积会带来更好的结果。

使用准备好的数据训练SVM并做预测。

以下是Roy和麻省理工学院学生的一个链接,他使用SVM来训练食物分类器。代码很容易理解,您可以按照它们来获取SVM分类器的要点。

Food Classifier