2012-11-02 4 views
6

私はopencv 2.4.2 C++を実行しています。SVM for People Recognitionの使い方は?

私はopencvを使って人々の認識をしようとしています。

私は、さまざまな方向の異なる人を含むVidTIMITデータセットを使用しています。

私はCvSVMを使ってこれらの人々を分類しています。

私の問題は、svmの出力は常に同じであるということです。

私は従うアルゴリズムは次のとおりです。顔のハールを使用して

  1. 顔検出
  2. リサイズ(58 * 58)
  3. SVMトレーニング
  4. 分類

今、私は訓練に何か間違っていたのだろうかと思っています。

私は5(num_name)person、10(num_images)の異なる画像を考えてこのメソッドを試しています。

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)); 
} 

検証コード:

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"; 
} 

はあなたが私を助けることができると思います。

答えて

2

あなたは完全な58 * 58の顔であなたのSVMをトレーニングしているようです。 SVMが動作するためには、すでにOpenCVに含まれているPCA(プリンシパルコンポーネント分析)のような方法を使用して、ディメンションを減らす(主要コンポーネントを取得する)必要があります。

58 * 58アレイからn *を主な特徴とするn * nアレイに次元を縮小すると、SVMのトレーニングで主な機能のみが使用され、改善されたソリューションが得られます。

OpenCVで顔認識のドキュメントがたくさんある場合は、hereを起動できます。

+1

を取得するには、このリンクを見て、CA – Gappa

4

SVMが機能するためには、SVMがPCAを使用しなければならないという点で、他の答えは正しくありません。私はPCAなしで128x128の画像にSVMを使用し、良い結果を得ました。私はcohn-kanadeデータセットと同様のことをしました。いくつかのソースコードがあります。

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"); 
    } 
} 
+0

どうもありがとうございましたあなたが訓練するために、生の画像を使用していますか?特徴抽出部分はありません。私はLBPを使って特徴を抽出し、それをSVM列の入力として使うのですか? LBP機能をLBPヒストグラムに変換してトレーニングする必要がありますか? – Jame

+0

@ user8430:lpbフィーチャを抽出した後、対応するヒストグラムを計算し、そのヒストグラムベクトルをSVM分類器に渡す必要があります。 – Derman

+0

@ user8430はい、私は生の画像を使って訓練しました。私が訓練に先立って行った唯一のことは、画像とクロッピング/アラインメントのイルミネーションのイコライゼーションでした。 – jmo