[英]Face recognition using SVM
我曾嘗試使用 SVM 進行人臉識別,下面是我用於訓練和測試的代碼。 問題是我沒有得到准確的結果,有時我總是將預測值設為“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;
}
好吧,您的代碼看起來很臟,所以我不會詳細介紹它們,但我會嘗試為您提供有關該過程的一些提示。
首先,您需要訓練集,並確保負面訓練數據多於正面訓練數據以獲得良好結果。 另請注意,您將需要安靜的大量面孔才能獲得良好的結果,對於平均或低於平均水平的簡單分類器,可能需要大約 100-200。
第二次從面部提取特征,您可以在其中使用顏色、邊緣直方圖或二進制樣圖等。選擇權在您手中。 但是少量的卷積會產生更多更好的結果。
使用准備好的數據訓練 SVM 並進行預測。
這是來自麻省理工學院學生 Roy 的鏈接,他使用 SVM 訓練食物分類器。 代碼易於理解,您可以按照它們來獲得 SVM 分類器的要點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.