1
votes

I am pretty new to EMGUCV . I want to make a face recognition system , I had implemented it but the results are not acceptable. Here is my code for the recognition :

public List<Person> RecognizeFaces(List<Image<Bgr, byte>> faces)
{
        List<Person> RecognizedPersons = new List<Person>();
        MCvTermCriteria termCrit = new MCvTermCriteria(TrainDB.Count, 0.001);

        EigenObjectRecognizer recognizer = new EigenObjectRecognizer(
         this.ToGrayList(this.TrainDB),
         labels.ToArray(),
         7000,  // I changed this argument many times but nothing has changed (1000, 2000, ...
         ref termCrit);

        string label = "";
        for (int i = 0; i < faces.Count; i++)
        {
            label = recognizer.Recognize(faces[i].Convert<Gray, byte>());
            RecognizedPersons.Add(new Person(faces[i],!label.Equals("") ? label : "unknown"));
        }

        return RecognizedPersons;
}

This function takes a list of previously detected faces from an input image and returns a list of Type Person where each person contains an image and a label to the recognized person . My Question is why the results are not good ? is there is something wrong with my code ? Or there is something wrong with the training set TrainDB , if so , what is the best guidelines to follow when creating the training set ?

I had collected the training set according to this : 1- Applying face detection (using EMGU) on an image that's contain a single person 2- Then I resize the detected face to 200 : W, 200 : H

Some images from my training set :

enter image description here

enter image description here

Some Examples of test images :

enter image description here

  • List item

enter image description here

enter image description here

My last question .. do Emgu/OpenCv are powerful tools to be used in face recognition ? or there is something else that could be more accurate in results ?

2
What is the size of the training set? How many subject are in the training set and how many images are there from each subject? Are the test images in the same pose/lightning conditions/facial expression as the training images? - GilLevi
@GilLevi The size of the training set is 15 .. I have 3 persons 5 images for each person .. Not all test images are in the same pose/lightning condition but the facial expressions are the same - Ibrahim Amer
Thanks for uploading the test images. For each test image, are you first detecting the face and them apply face recognition or are you running face recognition on the entire input image? - GilLevi
@GilLevi no sir, first I apply face detection on the input image, then applying face recognition on the returned result - Ibrahim Amer
5 per person are definitely not enough. 20, maybe. - berak

2 Answers

1
votes

your training set should have the same size (dimensions) and gray images

List<Image<Gray, byte>>
0
votes

Can you tell us the capture method for faces that you are trying to detect? Are you simply giving it bitmaps and asking it to recognise? What you need to do is first do facial detection, you can use the same libary e.g.:

I have put 5 unique faces into my training data (one of each face and label) and it is pretty good at detecting. So you dont need 20+ images per person, but I guess it will help vastly...

   face = new HaarCascade("haarcascade_frontalface_default.xml"); //You will need an XML training file 
   gray = MyImage.Convert<Gray, Byte>();
   MCvAvgComp[][] facesDetected = gray.DetectHaarCascade(face,1.2, 10,
      Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
      new Size(20, 20));

where MyImage is your actual file (as an image object of the same class). You can read about Haar cascade object detection here: https://docs.opencv.org/3.4/d7/d8b/tutorial_py_face_detection.html

so lets say you only have one face now in your facesDetected array (the second dimension indexes the total number of faces found, when there are mutliple faces in the MyImage):

face = MyImage.Copy(facesDetected[0][0].rect).Convert<Gray, byte>().Resize(100, 100, 
Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);

Now you have a resized, and converted face, you can use. So, once you have captured a normalized face of all of your training data, save them to an image array, save the labels in a string array and use the following command to recognise the face:

    MCvTermCriteria termCrit = new MCvTermCriteria(TrainingImages.Length, 0.001);
    EigenObjectRecognizer recognizer = new EigenObjectRecognizer(
                       TrainingImages, //as Image<Gray, byte>[] array
                       TrainingImageLabels, //as string[] array
                       3000,
                       ref termCrit);
                    name = recognizer.Recognize(result);
                    // Name will contain the recognised label

This works reasonably well, when you have pre-trained images, in my case, I am trying to detect for unique faces. This method works like statistics, and I am trying to figure out if the Recognizer is able to return some % level of confidence that I can use to reject the suggested name. But, I hope this help you!