Face recognition using OpenCV and Python

in #machinelearning7 years ago

Hello World!
Hope everything is well at your end.. If not! and you are stuck with something like making your own face recognition system or just you want to implement few algorithms to do some task like face recognition this post will definitely help you out in just three steps.

So, let's get started with the things required to complete this project:

  • OpenCV 2.4.9
  • Python 2.7.10
  • AT&T face dataset here's the link
  • 30 minutes of time

Steps:

  • Make/Create data
  • Train the model and Save it to disk
  • Load the saved model and test it in real time

01. Create your own data

Here's the folder hierarchy of our face data
| --database
| |—- s0
| | |—- 1.pgm
| | |—- 2.pgm
| | |—- ...
| |—- s1
| | |—- 1.pgm
| | |—- 2.pgm
| | |—- ...
| |—- aquib(your face folder name)
| | |—- 1.pgm
| | |—- 2.pgm
| | |—- ...

Because we are going to make it real time, we need to have our own face data so that we can test it.
The code below will take 45 images of the face and saves it in the folder. What is happening here’s is, the camera will open and detect the face from the frames and it take face and resize it to 112×92 pixels with the extension of the file name with .pgm. To detect face in a frame we use haarcascade frontalface default.xml and OpenCV function to detect face.

 # create_database.py
 import cv2, sys, numpy, os, time
 count = 0
 size = 4
 fn_haar = 'haarcascade_frontalface_default.xml'
 fn_dir = 'database'
 fn_name = sys.argv[1]   #name of the person  
 path = os.path.join(fn_dir, fn_name)
 if not os.path.isdir(path):
     os.mkdir(path)
 (im_width, im_height) = (112, 92) 
 haar_cascade = cv2.CascadeClassifier(fn_haar)
 webcam = cv2.VideoCapture(0)
 print "-----------------------Taking pictures----------------------"
 print "--------------------Give some expressions---------------------"
 # The program loops until it has 20 images of the face.
while count < 45:
       (rval, im) = webcam.read()
im = cv2.flip(im, 1, 0)
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
mini = cv2.resize(gray, (gray.shape[1] / size, gray.shape[0] / size))
faces = haar_cascade.detectMultiScale(mini)
faces = sorted(faces, key=lambda x: x[3])
if faces:
    face_i = faces[0]
    (x, y, w, h) = [v * size for v in face_i]
    face = gray[y:y + h, x:x + w]
    face_resize = cv2.resize(face, (im_width, im_height))
    pin=sorted([int(n[:n.find('.')]) for n in os.listdir(path)
           if n[0]!='.' ]+[0])[-1] + 1
    cv2.imwrite('%s/%s.png' % (path, pin), face_resize)
    cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 3)
    cv2.putText(im, fn_name, (x - 10, y - 10), cv2.FONT_HERSHEY_PLAIN,
        1,(0, 255, 0))
time.sleep(0.38)        
count += 1   
cv2.imshow('OpenCV', im)
key = cv2.waitKey(10)
if key == 27:
    break
print str(count) + " images taken and saved to " + fn_name +" folder in database "

run python create_data.py name_of_the_person

02. Train the model and saving it to disk

we need to train the Images present in the face_data for training. The currently available algorithms(in opencv 2.4.9) are:

  • Eigenfaces ( createEigenFaceRecognizer())
  • Fisherfaces ( createFisherFaceRecognizer())
  • Local Binary Patterns Histograms ( createLBPHFaceRecognizer())

We are going to use createLBPHFaceRecognizer(), Now open another new python file named it as trainer.py,

 # trainer.py
 import cv2, sys, numpy, os,pyttsx,time
 size = 4
 fn_haar = 'haarcascade_frontalface_default.xml'
 fn_dir = 'database'
 recognizer = cv2.createLBPHFaceRecognizer()
 # Part 1: Create fisherRecognizer
 print('Training...')
 # Create a list of images and a list of corresponding names
 (images, lables, names, id) = ([], [], {}, 0)
 for (subdirs, dirs, files) in os.walk(fn_dir):
      for subdir in dirs:
          names[id] = subdir
          subjectpath = os.path.join(fn_dir, subdir)
          for filename in os.listdir(subjectpath):
                path = subjectpath + '/' + filename
                lable = id
            images.append(cv2.imread(path, 0))
                lables.append(int(lable))
          id += 1
 (im_width, im_height) = (112, 92)
 # Create a Numpy array from the two lists above
 (images, lables) = [numpy.array(lis) for lis in [images, lables]]
 recognizer.train(images, lables)
 recognizer.save('trainer.yml')

run python trainer.py

03. Load the saved model and test it on real-time video feed

Now, we have saved model to the disk, we have to load it in memory and start making prediction. How we are going to do this is just we need to detect face from the current frame as we have done earlier in step 1, then pass it to the classfier model which we have got from step 2. But before passing it directly we need to resize it as we have done for training data. Open new python file and name it real_time.py

 import cv2,os
 # Import numpy for matrices calculations
 import numpy as np
 # Create Local Binary Patterns Histograms for face recognization
 recognizer = cv2.createLBPHFaceRecognizer()
 # Load the trained mode
 recognizer.load('trainer.yml')
 fn_dir = 'database'

 # Load prebuilt model for Frontal Face
 cascadePath = "haarcascade_frontalface_default.xml"
 (im_width, im_height) = (112, 92)
 # Part 2: Use fisherRecognizer on camera stream
 (images, lables, names, id) = ([], [], {}, 0)
 for (subdirs, dirs, files) in os.walk(fn_dir):
     for subdir in dirs:
            names[id] = subdir
            subjectpath = os.path.join(fn_dir, subdir)
            for filename in os.listdir(subjectpath):
                  path = subjectpath + '/' + filename
                  lable = id
              images.append(cv2.imread(path, 0))
                  lables.append(int(lable)) 
              id += 1

 face_cascade = cv2.CascadeClassifier(cascadePath)
 webcam = cv2.VideoCapture(0)
 while True:
     (_, im) = webcam.read()
     gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
     faces = face_cascade.detectMultiScale(gray, 1.3, 5)
     for (x,y,w,h) in faces:
         cv2.rectangle(im,(x,y),(x+w,y+h),(255,0,0),2)
         face = gray[y:y + h, x:x + w]
         face_resize = cv2.resize(face, (im_width, im_height))
         # Try to recognize the face
         prediction = recognizer.predict(face_resize)
         cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 3)
         if prediction[1]<500:
                cv2.putText(im,'%s - %.0f' % (names[prediction[0]],prediction[1]),(x-10, y-10), cv2.FONT_HERSHEY_PLAIN,1,(0, 255, 0))
         else:
                cv2.putText(im,'not recognized',(x-10, y-10), cv2.FONT_HERSHEY_PLAIN,1,(0, 255, 0))
     cv2.imshow('OpenCV', im)
     key = cv2.waitKey(10)
     if key == 27:
         break

run real_time.py

Completed :)

This is very basics but still you can see some good results, I would like to point out few things are as follows:

  • Light conditions really matters a lot, So your accuracy will vary accordingly
  • Maximum accuracy I got is between 70-75%
  • you can implement it on Raspberry Pi

Most of the things, I tried my best to explain in this post, But still if you face any issue just put it in the comment, You can download the code from my github repo
Here's the demo:


Thanks a lot !

Sort:  

This type of thing may be an added feature of web browsers soon.

yeah, there are a lot of JavaScript libraries are there, Where we can run the deep-learning model in web browser.

Congratulations @aquib! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received
Award for the number of comments
You got a First Reply

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Coin Marketplace

STEEM 0.28
TRX 0.12
JST 0.032
BTC 66407.66
ETH 3025.92
USDT 1.00
SBD 3.69