Face Recognition OpenCV – Training A Face Recognizer

To perform face recognition we need to train a face recognizer, using a pre labeled dataset, In my previous post we created a labeled dataset for our face recognition system, now its time to use that dataset to train a face recognizer using opencv python,

Lets Train A Face RecognizerTwitter

First create a python “trainner.py” file in the same folder where we saved out dataset generator script in the previous post, and then create a folder in the same directory name it “trainner”, this is the folder where we are going to save our recognizer after training.

So the folder structure till now should be something like this

Those who don’t know how we got the dataset folder and script , it was created in my previous post you should check that first.

Before we start actual coding we need a new library called pillow,
open your cmd (run as administrator )and type following command to navigate to your python pip directory:
“cd c:/python27/scripts/”
now type the following to install pillow:
pip install pillow
this will install the latest version of pillow in your python library

Lets Start Coding

So now we rare ready to code the trainner,
Just like all the other opencv script we need:

import the opencv / cv2 library,
we will need the os to accress the file list in out dataset folder,
we also need to import the numpy library,
and we need to import the pillow / PIL library we installed before,

It will look something like this:

import cv2,os
import numpy as np
from PIL import Image

Now we need to initialize the recognizer and the face detector

recognizer = cv2.createLBPHFaceRecognizer()
detector= cv2.CascadeClassifier("haarcascade_frontalface_default.xml");

Load The Training Data

Ok, now we will are going to create a function which will grab the training images from the dataset folder, and will also get the corresponding Ids from its file name, (remember we formatted the filename to be like User.id.samplenumber in our previous script)

So I am going to name this function “getImagesAndLabels”  we need the path of the dataset folder so we will provide the folder path as argument. So the function will be like this

def getImagesAndLabels(path):

So now inside this function we are going to do the following

  • Load the training images from dataset folder
  • capture the faces and Id from the training images
  • Put them In a List of Ids and FaceSamples  and return it

To load the image we need to create the paths of the image

    imagePaths=[os.path.join(path,f) for f in os.listdir(path)] 

this will get the path of each images in the folder.
now we need to create two lists for faces and Ids to store the faces and Ids

    faceSamples=[]
    Ids=[]

Now we will loop the images using the image path and will load those images and Ids, we will add that in your lists

    for imagePath in imagePaths:
        pilImage=Image.open(imagePath).convert('L')
        imageNp=np.array(pilImage,'uint8')
        Id=int(os.path.split(imagePath)[-1].split(".")[1])
        faces=detector.detectMultiScale(imageNp)
        for (x,y,w,h) in faces:
            faceSamples.append(imageNp[y:y+h,x:x+w])
            Ids.append(Id)

In the above code we used used “Image.open(imagePath).convert(‘L’)” is loading the image and converting it to gray scale, but now its a PIL image we need to convert it to numpy array.
for that we are converting it to numpy array “imageNP=np.array(pilImage,’uint8′)”.
To get the Id we split the image path and took the first from the last part (which is “-1” in python) and that is the name of the imagefile. now here is the trick, we saved the file name in our previous program like this “User.Id.SampleNumber” so if we split this using “.” the we will get 3 token in a list “User”, “Id”, “SampleNumber”
so to get the Id we will choone 1st index (index starts from 0)

So we get:

        Id=int(os.path.split(imagePath)[-1].split(".")[1])

Now we are using the detector to extract the faces and append them in the faceSamples list with the Id

which looks like:

        for (x,y,w,h) in faces:
            faceSamples.append(imageNp[y:y+h,x:x+w])
            Ids.append(Id)

So we are done now we just have to return that value

return faceSamples,Ids

Now the entire function will look like this

def getImagesAndLabels(path):
    #get the path of all the files in the folder
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)] 
    #create empth face list
    faceSamples=[]
    #create empty ID list
    Ids=[]
    #now looping through all the image paths and loading the Ids and the images
    for imagePath in imagePaths:
        #loading the image and converting it to gray scale
        pilImage=Image.open(imagePath).convert('L')
        #Now we are converting the PIL image into numpy array
        imageNp=np.array(pilImage,'uint8')
        #getting the Id from the image
        Id=int(os.path.split(imagePath)[-1].split(".")[1])
        # extract the face from the training image sample
        faces=detector.detectMultiScale(imageNp)
        #If a face is there then append that in the list as well as Id of it
        for (x,y,w,h) in faces:
            faceSamples.append(imageNp[y:y+h,x:x+w])
            Ids.append(Id)
    return faceSamples,Ids

Almost Done!!

We are almost finished, now we just have to call that function and feed the data to the recognizer to train

faces,Ids = getImagesAndLabels('dataSet')
recognizer.train(faces, np.array(Ids))
recognizer.save('trainner/trainner.yml')

Thats it!!

Now if we run this code it will create a “trainner.yml” file inside the trainner folder,
We will use this file in our next post to actually recognize the faces that we trained the face recognizer to recognize,

The Complete Code

import cv2,os
import numpy as np
from PIL import Image

recognizer = cv2.createLBPHFaceRecognizer()
detector= cv2.CascadeClassifier("haarcascade_frontalface_default.xml");

def getImagesAndLabels(path):
    #get the path of all the files in the folder
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)] 
    #create empth face list
    faceSamples=[]
    #create empty ID list
    Ids=[]
    #now looping through all the image paths and loading the Ids and the images
    for imagePath in imagePaths:
        #loading the image and converting it to gray scale
        pilImage=Image.open(imagePath).convert('L')
        #Now we are converting the PIL image into numpy array
        imageNp=np.array(pilImage,'uint8')
        #getting the Id from the image
        Id=int(os.path.split(imagePath)[-1].split(".")[1])
        # extract the face from the training image sample
        faces=detector.detectMultiScale(imageNp)
        #If a face is there then append that in the list as well as Id of it
        for (x,y,w,h) in faces:
            faceSamples.append(imageNp[y:y+h,x:x+w])
            Ids.append(Id)
    return faceSamples,Ids

faces,Ids = getImagesAndLabels('dataSet')
recognizer.train(faces, np.array(Ids))
recognizer.save('trainner/trainner.yml')

 

Now The Complete Video Tutorial

 

You May also like

Comments

comments

56 thoughts on “Face Recognition OpenCV – Training A Face Recognizer”

  1. Hi, I’m new in the openCV programming. I’ve openCV 3.2 (+ openCV contrib) installed on my PC with python 2.7 and when I compile the code appears this error:
    recognizer = cv2.createEigenFaceRecognizer()
    AttributeError: ‘module’ object has no attribute ‘face’

    I’ve searched in forums and they suggest to put ‘face.’ before ‘createEigenFaceRecognizer()’ or to substitute ‘cv2.createEigenFaceRecognizer()’ with ‘cv2.createFisherFaceRecognizer()’ etc… I haven’t solved my problem… What can I do?
    Thanks in advance and sorry for my bad English.

  2. Hello Anirban;
    When i use
    recognizer = cv2.createEigenFaceRecognizer()
    an error occur that say “In Eigenfaces method all input samples (training images) must be of equal size! “.All images must be in same height and width (in pixel).
    How can i create a dataset with this condition?
    Thanks in advance.

    1. you can use
      face=cv2.resize(imageNp[y:y+h,x:x+w],(100,100))
      faceSamples.append(face)

      now all the samples will be same size always

  3. Getting following error,

    File “two_train.py”, line 35, in
    faces,Ids = getImagesAndLabels(‘dataSet’)
    File “two_train.py”, line 19, in getImagesAndLabels
    pilImage=Image.open(imagePath).convert(‘L’)
    File “/home/pi/.virtualenvs/cv/lib/python3.4/site-packages/PIL/Image.py”, line 2349, in open
    % (filename if filename else fp))
    OSError: cannot identify image file ‘dataSet/.DS_Store’

    P.S: it takes 50% of data set and then it shows this error.

    1. Actually there is a hidden file “dataSet/.DS_Store” -> “.DS_Store” and the script is taking that as input but not able to convert it as image, try to remove that file from the folder and it will work

        1. hey gaurav sorry for not replying sooner,
          try this split the image path in by “.” so the 2nd part will be jpeg after “.” if its not then its not an image

          token=imagePath.split(“.”)
          if(token[1]==’jpeg’):
          # put the rest of the code inside

          1. Hello Anirban, I am having a similar issue, I am trying to filter out the hidden .DS_Store file, but I don’t quite understand your solution

            Where should this occur?
            token=imagePath.split(“.”)
            if(token[1]==’jpeg’):
            # put the rest of the code inside

            As a component of this?
            Id= int(os.path.split(imagePath)[-1].split(“.”)[1])

            Thank you so much! Your tutorial has been great so far

  4. HI, I am Shyam I using ubuntu 16.04 how could I have to do and save trainer/trainer .yml file can you help me for that. And you had changed the code in a video but you not mentioned in website.Did you face any problem in it?

    anticipating for yor answer ,,,,

    1. Hi Shyam, If you have saved your python script in the same folder as the “trainner” folder like in the image that is shown in the post then.

      recognizer.save(‘trainner/trainner.yml’)

      this above line will save the yml file inside the “trainner” folder. even if you are using ubuntu its not a problem and if your script is in a different location then

      recognizer.save(‘[Fullpath]/trainner/trainner.yml’)

      you have to enter the full path of the “trainner” folder then it will work

      and about the difference in the blog and the video, its actually i didn’t wrote the both code same time so there is some difference in code but both logic is same you can follow any of them both will work. while writing the blog i broken down the code so that it becomes easier to explain in the blog that’s it

  5. Hey That I am have been another doubt.This tutorial is for save yml file or we can check the face of our ID. It is confusing me can you explain to me.

    This is only for face checking or Id checking

    1. its just for training the recognizer with the dataset that we created in the previous post and save the recognizer in a file, in the next post we are using that file to recognize the faces

  6. Getting this error how to resolve it please help

    Traceback (most recent call last):
    File “F:\New folder (6)\face reco\trainner.py”, line 21, in
    Ids,faces=getImagesWithID(path)
    File “F:\New folder (6)\face reco\trainner.py”, line 12, in getImagesWithID
    faceImg=Image.open(imagePath).convert(‘L’);
    File “C:\Python27\lib\site-packages\PIL\Image.py”, line 2349, in open
    % (filename if filename else fp))
    IOError: cannot identify image file ‘dataSet\\Thumbs.db’

    1. This is fixed after doing this :

      import cv2,os
      import numpy as np
      from PIL import Image

      recognizer = cv2.createLBPHFaceRecognizer()
      detector= cv2.CascadeClassifier(“haarcascade_frontalface_default.xml”);

      def getImagesAndLabels(path):
      #get the path of all the files in the folder
      imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
      #create empth face list
      faceSamples=[]
      #create empty ID list
      Ids=[]
      #now looping through all the image paths and loading the Ids and the images
      for imagePath in imagePaths:
      token = imagePath.split(“.”)
      if(token[1] ==’jpeg’):
      #loading the image and converting it to gray scale
      pilImage=Image.open(imagePath).convert(‘L’)
      #Now we are converting the PIL image into numpy array
      imageNp=np.array(pilImage,’uint8′)
      #getting the Id from the image
      Id=int(os.path.split(imagePath)[-1].split(“.”)[1])
      # extract the face from the training image sample
      faces=detector.detectMultiScale(imageNp)
      #If a face is there then append that in the list as well as Id of it
      for (x,y,w,h) in faces:
      faceSamples.append(imageNp[y:y+h,x:x+w])
      Ids.append(Id)
      return faceSamples,Ids

      faces,Ids = getImagesAndLabels(‘dataSet’)
      recognizer.train(faces, np.array(Ids))
      recognizer.save(‘trainner/trainner.yml’)

      But having a new error :

      Traceback (most recent call last):
      File “C:\Users\User\Desktop\python opencv\Face Recog\trainner.py”, line 34, in
      recognizer.train(faces, np.array(Ids))
      error: ..\..\..\..\opencv\modules\contrib\src\facerec.cpp:917: error: (-210) Empty training data was given. You’ll need more than one sample to learn a model. in function cv::LBPH::train

  7. Getting this error. unable to solve. ( I followed your code from youTube)
    Traceback (most recent call last):
    File “K:/python project/face recognition/trainer.py”, line 25, in
    recognizer.train(faces,Ids)
    TypeError: labels data type = 18 is not supported.

    when i pasted the code from this blog it works fine.

  8. Hello,
    How could I apply the same detection and recognition techniques but with a browse button instead of capturing it through the cam?

  9. hey Anirban,
    Thanks for the tutorial. But i am getting this error.
    Traceback (most recent call last):
    File “C:/Python27/prog/facerecog/trainner.py”, line 33, in
    recognizer.train(faces, np.array(Ids))
    TypeError: labels data type = 17 is not supported

  10. i am facing ….”””AttributeError: ‘module’ object has no attribute ‘createLBPHFaceRecognizer “”‘
    error …. what should i do….

  11. hello sir

    am developing your code on Anaconda navigator (Spyder) and python 3

    all the previous codes works fine but only in this code I get this error

    recognizer= cv2.createLBPHFaceRecognizer()

    AttributeError: module ‘cv2’ has no attribute ‘createLBPHFaceRecognizer’

    1. did you check your opencv version ?? is it 2/3? cuz in opencv 3 you dont have “createLBPHFaceRecognizer” out of the box

  12. hi Sir
    I copy your code and run it but it error
    Traceback (most recent call last):

    File “trainner.py”, line 31, in
    faces,Ids = getImagesAndLabels(‘dataSet’)
    File “trainner.py”, line 22, in getImagesAndLabels
    Id=int(os.path.split(imagePath)[-1].split(“.”)[1])
    ValueError: invalid literal for int() with base 10: ‘cam’
    Can you help me ? Thanks

  13. Getting this error how to resolve it please help

    Traceback (most recent call last):
    File “F:\New folder (6)\face reco\trainner.py”, line 21, in
    Ids,faces=getImagesWithID(path)
    File “F:\New folder (6)\face reco\trainner.py”, line 12, in getImagesWithID
    faceImg=Image.open(imagePath).convert(‘L’);
    File “C:\Python27\lib\site-packages\PIL\Image.py”, line 2349, in open
    % (filename if filename else fp))
    IOError: cannot identify image file ‘dataSet\\Thumbs.db’

    1. hey gaurav sorry for not replying sooner,
      try this split the image path in by “.” so the 2nd part will be jpeg after “.” if its not then its not an image

      token=imagePath.split(“.”)
      if(token[1]==’jpeg’):
      # put the rest of the code inside

  14. Hi there Anirban,
    When I tried running the code you have given here, I get the error
    Traceback (most recent call last):
    File “”, line 1, in
    exec file(“D:/Pjjjjjj/pythonsamp/trainner.py”)
    File “D:/Pjjjjjj/pythonsamp/trainner.py”, line 33, in
    recognizer.save(‘trainner/trainner.yml’)
    error: ..\..\..\..\opencv\modules\contrib\src\facerec.cpp:390: error: (-2) File can’t be opened for writing! in function cv::FaceRecognizer::save

    What should I do?

  15. #Here is my code…..

    import os
    import cv2
    import numpy as np
    cv2.imread(“filepath”)

    recognizer=cv2.createLBPHFaceRecognizer()
    path=’dataSet’

    def getImagesWithID(path):
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    faces=[]
    IDs=[]
    for imagePath in imagePaths:
    faceNp=cv2.imread(imagepath,0)
    ID=int(os.path.split(imagePath)[-1].split(“.”)[1])
    faces.append(faceNp)
    print ID
    IDs.append(ID)
    cv2.imshow(“training”,faceNp)
    cv2.waitKey(10)
    return IDs,faces

    IDs,faces = getImagesWithID(path)
    recognizer.train(faces, np.array(Ids))
    recognizer.save(‘recognizer/trainningData.yml’)
    cv2.destroyAllWindow()

    #And this error occurs…..

    Traceback (most recent call last):
    File “E:/Project & thesis/Face Recognition/trainner.py”, line 23, in
    IDs,faces = getImagesWithID(path)
    File “E:/Project & thesis/Face Recognition/trainner.py”, line 14, in getImagesWithID
    faceNp=cv2.imread(imagepath,0)
    NameError: global name ‘imagepath’ is not defined

    # What should I do? Please help.

      1. Thanks a lot. Now it works fine.
        Now I am facing a problem in Sqlite Database.

        Here is my code…..
        import cv2
        import sqlite3
        cam = cv2.VideoCapture(0)
        detector=cv2.CascadeClassifier(‘Classifiers/face.xml’)

        def insertOrUpdate(Id,Name):
        conn=sqlite3.connect(“FaceBase.db”)
        cmd=”SELECT * FROM People WHERE ID=”+str(Id)
        cursor=conn.execute(cmd)
        isRecordExist=0
        for row in cursor:
        isRecordExist=1
        if(isRecordExist==1):
        cmd=”UPDATE People SET Name=”+str(Name)+” WHERE ID=”+str(Id)
        else:
        cmd=”INSERT INTO People(ID,Name) Values(“+str(Id)+”,”+str(Name)+”)”
        conn.execute(cmd)
        conn.commit()
        conn.close()

        id=raw_input(‘enter your id’)
        name=raw_input(‘enter your name’)
        insertOrUpdate(id,name)
        sampleNum=0
        while(True):
        ret, img =cam.read()
        gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces=detector.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(100, 100), flags=cv2.CASCADE_SCALE_IMAGE)
        for (x,y,w,h) in faces:
        sampleNum=sampleNum+1
        cv2.imwrite(“dataSet/user.”+id +’.’+ str(sampleNum) + “.jpg”, gray[y:y+h,x:x+w])
        cv2.rectangle(img,(x-50,y-50),(x+w+50,y+h+50),(225,0,0),2)
        cv2.imshow(‘img’,img)
        cv2.waitKey(100)
        if sampleNum>20:
        cam.release()
        cv2.destroyAllWindows()
        break

        # My problem is this code runs well but doesn’t detect my face and doesn’t create the dataSet of my face. Now what should I do?

  16. CODE :
    import cv2
    import os
    import numpy as np
    from PIL import Image

    recognizer = cv2.createLBPHFaceRecognizer()
    detector = cv2.CascadeClassifier(“haarcascade_frontalface_default.xml”);

    def getImagesAndLabels(path):
    #get the path of all the files in the folder
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    #create empth face list
    faceSamples=[]
    #create empty ID list
    Ids=[]
    #now looping through all the image paths and loading the Ids and the images
    for imagePath in imagePaths:
    token = imagePath.split(“.”)
    if(token[1] ==’jpeg’):
    #loading the image and converting it to gray scale
    pilImage=Image.open(imagePath).convert(‘L’)
    #Now we are converting the PIL image into numpy array
    imageNp=np.array(pilImage,’uint8′)
    #getting the Id from the image
    Id=int(os.path.split(imagePath)[-1].split(“.”)[1])
    # extract the face from the training image sample
    faces=detector.detectMultiScale(imageNp)
    #If a face is there then append that in the list as well as Id of it
    for (x,y,w,h) in faces:
    faceSamples.append(imageNp[y:y+h,x:x+w])
    Ids.append(Id)
    cv2.imshow(“Adding faces to trainning set. . . “,imageNp[y:y+h,x:x+w])
    cv2.waitKey(50)
    return faceSamples,Ids

    faces,Ids = getImagesAndLabels(‘dataSet’)
    recognizer.train(faces, np.array(Ids))
    recognizer.save(‘trainner/trainner.yml’)

    ERROR :
    Traceback (most recent call last):
    File “C:\Users\User\Desktop\python opencv\Face Recog\trainner.py”, line 37, in
    recognizer.train(faces, np.array(Ids))
    error: ..\..\..\..\opencv\modules\contrib\src\facerec.cpp:917: error: (-210) Empty training data was given. You’ll need more than one sample to learn a model. in function cv::LBPH::train

    Please fix the error….

  17. How to solve this error
    recognizer=cv2.createLBPHFaceRecognizer()
    AttributeError: ‘module’ object has no attribute ‘createLBPHFaceRecognizer’

  18. I am getting this error:
    Image.register_decoder(‘MSP’, MspDecoder)

    AttributeError: ‘module’ object has no attribute ‘register_decoder’

    1. I was able to fix the first problem by installing PIL; now I get this error:
      the first image.

      IOError: cannot identify image file ‘dataSet/.DS_Store’

Leave a Reply

Your email address will not be published. Required fields are marked *