Face Recognition OpenCV – Training A Face Recognizer

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 Recognizer

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

Updates:

To make sure the trainner doesn’t take any file other that the jpg files we will add an if condition in the method

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:

        # Updates in Code
        # ignore if the file does not have jpg extension :
        if(os.path.split(imagePath)[-1].split(".")[-1]!='jpg'):
            continue

        #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')

Github links:

For this code: you can visit: https://github.com/thecodacus/Face-Recognition

nazmi69 has done a good job converting the code for python 3.x and opencv 3.0
available at https://github.com/nazmi69/Face-Recognition

Copyright 2021 The Codacus