2013-10-30 6 views
0

나는 하나의 멍청한 질문이 있습니다. Visual Studio 2010에서 opencCV 2.4.6을 사용하여 얼굴 인식/인식 프로그램을 만들려고합니다. openCV 설명서에서 가져온 얼굴 인식 알고리즘에 문제가 있습니다. 알고리즘 자체가 어떤 오류도없이 작동하지만, 나는 그것이 출력인지, 아니면 실제로는 정확하지 않은지 확신 할 수 없다. 훈련을하고 인식하기 위해서 & T 데이터베이스를 사용 중이다. 내 CSV 파일 (at.txt)은 다음과 같습니다얼굴 인식 openCV Visual Studio 이해

내 얼굴을 인식 코드는 다음과 같습니다
C:\face\s1/1.pgm;0 
C:\face\s1/2.pgm;0 
C:\face\s1/3.pgm;0 
C:\face\s1/4.pgm;0 
C:\face\s1/5.pgm;0 
C:\face\s1/6.pgm;0 
C:\face\s1/7.pgm;0 
C:\face\s1/8.pgm;0 
C:\face\s1/9.pgm;0 
C:\face\s1/10.pgm;0 
C:\face\s2/1.pgm;1 
C:\face\s2/2.pgm;1 
C:\face\s2/3.pgm;1 
C:\face\s2/4.pgm;1 
C:\face\s2/5.pgm;1 
C:\face\s2/6.pgm;1 
C:\face\s2/7.pgm;1 
C:\face\s2/8.pgm;1 
C:\face\s2/9.pgm;1 
C:\face\s2/10.pgm;1 
C:\face\s3/1.pgm;2 
C:\face\s3/2.pgm;2 
C:\face\s3/3.pgm;2 
C:\face\s3/4.pgm;2 
C:\face\s3/5.pgm;2 
C:\face\s3/6.pgm;2 
C:\face\s3/7.pgm;2 
C:\face\s3/8.pgm;2 
C:\face\s3/9.pgm;2 
C:\face\s3/10.pgm;2 
C:\face\s4/1.pgm;3 
C:\face\s4/2.pgm;3 
C:\face\s4/3.pgm;3 
C:\face\s4/4.pgm;3 
C:\face\s4/5.pgm;3 
C:\face\s4/6.pgm;3 
C:\face\s4/7.pgm;3 
C:\face\s4/8.pgm;3 
C:\face\s4/9.pgm;3 
C:\face\s4/10.pgm;3 
C:\face\s5/1.pgm;4 
C:\face\s5/2.pgm;4 
C:\face\s5/3.pgm;4 
C:\face\s5/4.pgm;4 
C:\face\s5/5.pgm;4 
C:\face\s5/6.pgm;4 
C:\face\s5/7.pgm;4 
C:\face\s5/8.pgm;4 
C:\face\s5/9.pgm;4 
C:\face\s5/10.pgm;4 
C:\face\s6/1.pgm;5 
C:\face\s6/2.pgm;5 
C:\face\s6/3.pgm;5 
C:\face\s6/4.pgm;5 
C:\face\s6/5.pgm;5 
C:\face\s6/6.pgm;5 
C:\face\s6/7.pgm;5 
C:\face\s6/8.pgm;5 
C:\face\s6/9.pgm;5 
C:\face\s6/10.pgm;5 
C:\face\s7/1.pgm;6 
C:\face\s7/2.pgm;6 
C:\face\s7/3.pgm;6 
C:\face\s7/4.pgm;6 
C:\face\s7/5.pgm;6 
C:\face\s7/6.pgm;6 
C:\face\s7/7.pgm;6 
C:\face\s7/8.pgm;6 
C:\face\s7/9.pgm;6 
C:\face\s7/10.pgm;6 
C:\face\s8/1.pgm;7 
C:\face\s8/2.pgm;7 
C:\face\s8/3.pgm;7 
C:\face\s8/4.pgm;7 
C:\face\s8/5.pgm;7 
C:\face\s8/6.pgm;7 
C:\face\s8/7.pgm;7 
C:\face\s8/8.pgm;7 
C:\face\s8/9.pgm;7 
C:\face\s8/10.pgm;7 
C:\face\s9/1.pgm;8 
C:\face\s9/2.pgm;8 
C:\face\s9/3.pgm;8 
C:\face\s9/4.pgm;8 
C:\face\s9/5.pgm;8 
C:\face\s9/6.pgm;8 
C:\face\s9/7.pgm;8 
C:\face\s9/8.pgm;8 
C:\face\s9/9.pgm;8 
C:\face\s9/10.pgm;8 
C:\face\s10/1.pgm;9 
C:\face\s10/2.pgm;9 
C:\face\s10/3.pgm;9 
C:\face\s10/4.pgm;9 
C:\face\s10/5.pgm;9 
C:\face\s10/6.pgm;9 
C:\face\s10/7.pgm;9 
C:\face\s10/8.pgm;9 
C:\face\s10/9.pgm;9 
C:\face\s10/10.pgm;9 

:

#include "stdafx.h" 

#include "opencv2/core/core.hpp" 
#include "opencv2/contrib/contrib.hpp" 
#include "opencv2/highgui/highgui.hpp" 

#include <iostream> 
#include <fstream> 
#include <sstream> 

using namespace cv; 
using namespace std; 

static Mat norm_0_255(InputArray _src) { 
    Mat src = _src.getMat(); 
    // Create and return normalized image: 
    Mat dst; 
    switch(src.channels()) { 
    case 1: 
     cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1); 
     break; 
    case 3: 
     cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3); 
     break; 
    default: 
     src.copyTo(dst); 
     break; 
    } 
    return dst; 
} 

static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, 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()) { 
      images.push_back(imread(path, 0)); 
      labels.push_back(atoi(classlabel.c_str())); 
     } 
    } 
} 

int main(int argc, const char *argv[]) { 
    // Check for valid command line arguments, print usage 
    // if no arguments were given. 
    if (argc < 2) { 
     cout << "usage: " << argv[0] << " <csv.ext> <output_folder> " << endl; 
     exit(1); 
    } 
    string output_folder; 
    if (argc == 3) { 
     output_folder = string(argv[2]); 
    } 
    // Get the path to your CSV. 
    string fn_csv = string(argv[1]); 
    // These vectors hold the images and corresponding labels. 
    vector<Mat> images; 
    vector<int> labels; 
    // Read in the data. This can fail if no valid 
    // input filename is given. 
    try { 
     read_csv(fn_csv, images, labels); 
    } catch (cv::Exception& e) { 
     cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl; 
     // nothing more we can do 
     exit(1); 
    } 
    // Quit if there are not enough images for this demo. 
    if(images.size() <= 1) { 
     string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!"; 
     CV_Error(CV_StsError, error_message); 
    } 
    // Get the height from the first image. We'll need this 
    // later in code to reshape the images to their original 
    // size: 
    int height = images[0].rows; 
    // The following lines simply get the last images from 
    // your dataset and remove it from the vector. This is 
    // done, so that the training data (which we learn the 
    // cv::FaceRecognizer on) and the test data we test 
    // the model with, do not overlap. 
    Mat testSample = images[images.size() - 1]; 
    int testLabel = labels[labels.size() - 1]; 
    images.pop_back(); 
    labels.pop_back(); 
    // The following lines create an Eigenfaces model for 
    // face recognition and train it with the images and 
    // labels read from the given CSV file. 
    // This here is a full PCA, if you just want to keep 
    // 10 principal components (read Eigenfaces), then call 
    // the factory method like this: 
    // 
    //  cv::createEigenFaceRecognizer(10); 
    // 
    // If you want to create a FaceRecognizer with a 
    // confidence threshold (e.g. 123.0), call it with: 
    // 
    //  cv::createEigenFaceRecognizer(10, 123.0); 
    // 
    // If you want to use _all_ Eigenfaces and have a threshold, 
    // then call the method like this: 
    // 
    //  cv::createEigenFaceRecognizer(0, 123.0); 
    // 
    Ptr<FaceRecognizer> model = createEigenFaceRecognizer(); 
    model->train(images, labels); 
    // The following line predicts the label of a given 
    // test image: 
    int predictedLabel = model->predict(testSample); 
    // 
    // To get the confidence of a prediction call the model with: 
    // 
    //  int predictedLabel = -1; 
    //  double confidence = 0.0; 
    //  model->predict(testSample, predictedLabel, confidence); 
    // 
    string result_message = format("Predicted class = %d/Actual class = %d.", predictedLabel, testLabel); 
    cout << result_message << endl; 
    // Here is how to get the eigenvalues of this Eigenfaces model: 
    Mat eigenvalues = model->getMat("eigenvalues"); 
    // And we can do the same to display the Eigenvectors (read Eigenfaces): 
    Mat W = model->getMat("eigenvectors"); 
    // Get the sample mean from the training data 
    Mat mean = model->getMat("mean"); 
    // Display or save: 
    if(argc == 2) { 
     imshow("mean", norm_0_255(mean.reshape(1, images[0].rows))); 
    } else { 
     imwrite(format("%s/mean.png", output_folder.c_str()), norm_0_255(mean.reshape(1, images[0].rows))); 
    } 
    // Display or save the Eigenfaces: 
    for (int i = 0; i < min(10, W.cols); i++) { 
     string msg = format("Eigenvalue #%d = %.5f", i, eigenvalues.at<double>(i)); 
     cout << msg << endl; 
     // get eigenvector #i 
     Mat ev = W.col(i).clone(); 
     // Reshape to original size & normalize to [0...255] for imshow. 
     Mat grayscale = norm_0_255(ev.reshape(1, height)); 
     // Show the image & apply a Jet colormap for better sensing. 
     Mat cgrayscale; 
     applyColorMap(grayscale, cgrayscale, COLORMAP_JET); 
     // Display or save: 
     if(argc == 2) { 
      imshow(format("eigenface_%d", i), cgrayscale); 
     } else { 
      imwrite(format("%s/eigenface_%d.png", output_folder.c_str(), i), norm_0_255(cgrayscale)); 
     } 
    } 

    // Display or save the image reconstruction at some predefined steps: 
    for(int num_components = min(W.cols, 10); num_components < min(W.cols, 300); num_components+=15) { 
     // slice the eigenvectors from the model 
     Mat evs = Mat(W, Range::all(), Range(0, num_components)); 
     Mat projection = subspaceProject(evs, mean, images[0].reshape(1,1)); 
     Mat reconstruction = subspaceReconstruct(evs, mean, projection); 
     // Normalize the result: 
     reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows)); 
     // Display or save: 
     if(argc == 2) { 
      imshow(format("eigenface_reconstruction_%d", num_components), reconstruction); 
     } else { 
      imwrite(format("%s/eigenface_reconstruction_%d.png", output_folder.c_str(), num_components), reconstruction); 
     } 
    } 
    // Display if we are not writing to an output folder: 
    if(argc == 2) { 
     waitKey(0); 
    } 
    return 0; 
} 

그리고 이런 내 출력의 모양을

http://s15.postimg.org/xq76erurf/image.png

알고리즘도 이미지를 출력합니다. 평균 이미지, 대인면 이미지 및 재구성 이미지입니다. 내가 아는 한 가장 중요한 이미지는 재구성 된 이미지이고 출력에서는 재구성 된 이미지가 거의 없지만 거의 모든 것이 유령처럼 보입니다 마지막 얼굴/그림이 올바르게 재구성 된 것을 제외하고는 ... 알고리즘이 올바르게 작동하고 있습니까? 다른 재구성 된 얼굴도 왜 갖지 못합니까? 예측 클래스 = 7, 실제 클래스 = 9는 무엇을 의미합니까?

+0

안녕하세요 Andrija. 기계 학습에 대해 많은 것을 배워야하는 것 같습니다. 나는 전문가는 아니지만 얼굴 인식은 분류 작업입니다. 이러한 작업에는 '누구의 얼굴이 누구입니까?'라는 질문에 대한 정답이 있습니다. 이 정답은 실제 수업입니다. 컴퓨터의 추측은 예측 된 클래스입니다. 보시다시피, 컴퓨터가 잘못 예측했습니다. ( – AndyG

+0

"모두 유령처럼 보입니다"- 괜찮습니다. 각각의 '유령'을 기본 벡터로 생각하면 재구성은 모든 '고유 벡터'의 조합입니다. 예측이 잘못되었습니다. 이유가 없습니다. – berak

답변

0

알고리즘에 대한 기본적인 이해가 필요합니다. here를 찾을 수 있습니다 터크 & 펜 트랜드에서 고유 얼굴를 사용 얼굴 인식 :

나는 당신이 Wikipedia Article about Eigenfaces과 종이를 읽을 것을 권장합니다.

귀하의 목표가 무엇인지 알려 주시면 도움이됩니다. 어쩌면이 알고리즘을 사용하여 잘못된 방향으로 가고있는 것일 수 있습니다.

+0

네, 사실 저는 그것을 더 배우기 위해 노력하고 있습니다 ... 저는 배운 얼굴을 인식하고 그 얼굴에 주어진 이름을 보여줄 프로그램을 만들고자합니다. –

+0

네가 능동적이다. 고유 표면의 문제는 데이터베이스의 이미지 (훈련 이미지)와 인식하고 싶은 이미지의 차이가 있다면 사람을 인식 할 수 있다는 것이다. 샘플 이미지)는 상당히 작기 때문에 실제로 원하는 부분으로 넘어갑니다.하지만 얼굴 인식에 어려움을 겪기 시작한 경우 OpenCV가 사용하는 Eigenfaces 및 다른 메소드가 좋은 출발점입니다. – Mailerdaimon