如何提高 EigenFaceRecognizer 的准确率,将两个人识别为一个人?

How to increase the accuracy of EigenFaceRecognizer, it recognizes two people as one?

我正在尝试使用 C++ 中的 EigenFaceRecognizer 识别正面。

问题是:

1) 在高阈值下,两个人被识别为同一个人,一张"NEW"脸也被识别,而不是说是一张新脸

2) 在低阈值下,已经在训练集中的人脸被识别为新人脸

3) 也遇到了误报。虽然不是问题,但如果建议一种简单的方法来减少它们,我们将不胜感激>

有什么方法可以改进识别器以准确识别人脸吗?

以下是我正在做的事情。

 #include<opencv2\opencv.hpp>                //For opencv functions
#include<opencv2\highgui\highgui.hpp>       //For window based functions
#include<fstream>                           //For dealing with I/O operations on file

using namespace std;
using namespace cv;


// Function to read the File containing paths and labels of the training images and push them into images and     labels vector
static void read_data(vector <Mat> & images,vector <int>& labels, char separator=' ')
{
ifstream file("images.txt");   //images.txt contains paths and labels separated by a space
string line;
string a[2];

 while(getline(file,line))  // read images.txt line by line 
 {
     int i=0;
stringstream iss(line);
while (iss.good() && i < 2)
{
    iss>>a[i]; 
    ++i;
}
images.push_back(imread(a[0],CV_LOAD_IMAGE_GRAYSCALE)); // a[0] = "path of images"
labels.push_back(atoi(a[1].c_str()));  //a[1] = "labels"
}

file.close();
  }


  // Function to take input from webcam and recognize faces 
   int face_recognition::face_rec(int time_flag, int trigger_flag)
  {

 vector<Mat> images;    //stores the paths of all images
vector<int> labels;    //stores the corresponding labels

//function call to function read_data
read_data(images,labels);    

//take the size of the sample images
int im_width = images[0].cols;           
int im_height = images[0].rows;

//threshold is the minimum value of magnitude of vector of EigenFaces
double threshold=10.0;    

//create instance of EigenFaceRecognizer
Ptr<FaceRecognizer> model = createEigenFaceRecognizer(10,threshold);  
double current_threshold =model->getDouble("threshold");

// set a threshold value, for face prediction
model->set("threshold",5000.0);      

// train the face recognizer using the sample images
model->train(images,labels);         

// Create face_cascade to detect people
CascadeClassifier face_cascade;
if(!face_cascade.load("haarcascade_frontalface_default.xml"))   // load     haarcascade_frontaface_default.xml
{ 
cout<<"ERROR Loading cascade file";
return 1;
}

// capture the video input from webcam
VideoCapture capture(CV_CAP_ANY);    

capture.set(CV_CAP_PROP_FRAME_WIDTH, 320);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, 240); 

Size frameSize(static_cast<int>(320), static_cast<int>(240));

//initialize the VideoWriter object
VideoWriter oVideoWriter ("MyVideo.avi", CV_FOURCC('P','I','M','1'), 20, frameSize, true);  // video is save in the  VS  project

if(!capture.isOpened())
{
    cout<<"Error in camera";
return 1;
}

Mat cap_img, gray_img;

//store the detected faces
vector<Rect> faces;   
while(1)
{
//capture frame by frame in cap_img
capture>>cap_img;   
waitKey(10);


// Image conversion: Color to Gray
cvtColor(cap_img,gray_img,CV_BGR2GRAY);   

//Histogram Equilization to increase contrast by stretching intensity ranges
equalizeHist(gray_img,gray_img);      




// detects faces in the frame
//CV_HAAR_SCALE_IMAGE to scale the size of the detect face 
//CV_HAAR_DO_CANNY_PRUNING to increase speed as it skips image regions that are unlikely to contain a face
face_cascade.detectMultiScale(gray_img,faces,1.1,10,CV_HAAR_SCALE_IMAGE | CV_HAAR_DO_CANNY_PRUNING, Size(20,20),Size(300,300));  

Mat Normalized;

//Loop over the detected faces
for(int i=0;i<faces.size();i++)
{
    Rect face_i = faces[i];
    Mat face = gray_img(face_i);

    Mat face_resized;

    //resize the detected face to the size of sample images
    resize(face,face_resized, Size(im_width,im_height),1.0,1.0,INTER_CUBIC);  


    // predict the person the face belongs to, returns label
    int predicted_label = -1;
    predicted_label=model->predict(face_resized); 

    // Draws a rectangle around the faces
    rectangle(cap_img,face_i, CV_RGB(0,255,0),1);   

    //text to be put with the face, by default "new" for new faces
    string box_text=format("new");  

    // Change the text based on label
    if(predicted_label>-1)
        switch(predicted_label)
        {
            case 0:box_text = format("keanu");
                   break;
            case 1:box_text = format("selena");
                   break;
            case 2:box_text = format("shubham");
                   break;
        }


    // calculate the coordinates to put the text based on the postion of the face 
    int pos_x = max(face_i.tl().x - 10, 0);
    int pos_y = max(face_i.tl().y - 10, 0);

    // put text on the output screen
    putText(cap_img, box_text , Point(pos_x,pos_y), FONT_HERSHEY_PLAIN,0.8, CV_RGB(0,255,0), 1,CV_AA);  

    if (box_text=="new")
    {
       oVideoWriter.write(cap_img); //writer the frame into the file
    }
}

// show the frame on the result window
imshow("Press Esc to exit",cap_img); 

if(waitKey(30)==27)         
    break; 
}

return 0; }

我遇到了同样的问题。答案(and code) is in Chapter 8 of the Mastering OpenCV book by the awesome Shervin Emami. Here's his blog post 关于这个问题。

主要是对人脸做一些预处理,包括以下几个步骤

  1. 训练时,在连续帧之间进行差异处理,并且仅在帧与前一帧明显不同时才对其进行预处理
  2. 将图像和镜像版本都添加到训练集中,以便您拥有更多的训练数据,还可以处理向左或向右看的人脸
  3. 直方图均衡化以提高面部的对比度和亮度
  4. 面部经过缩放、旋转、平移,以便眼睛对齐。
  5. 从面部图像中去除额头、下巴、耳朵和背景
  6. 分别对左右脸进行直方图均衡
  7. 使用双边滤波器平滑或去除噪声
  8. 用于去除剩余头发和背景的椭圆蒙版

干杯。