Setup
Here is our layout
├── faceDataSet
├── haarcascade
│ ├── haarcascade_frontalface.xml
├── trainers
│ ├── savedTrainer.yml
├── clearData.py
├── faceDataCreator.py
├── trainer.py
├── faceDetector.py
First get the haarcascade data from here.
Requirements
OpenCv
Numpy
Pillow
Lets start with creating our data. We will create a program to take pictures of faces, then store them in faceDataSet. I will name my file faceDataCreator.py. The index is used to only take 20 pictures of one subject. Create an input in order to save a label to your image. Write the images to faceDataSet. You can show the frame but it is not necessary.
from cv2 import cv2
import os
currentPath = os.path.dirname(os.path.abspath(__file__))
detector=cv2.CascadeClassifier(currentPath+r'\haarcascade\haarcascade_frontalface.xml')
index = 0
camera = cv2.VideoCapture(0)
id=input('enter your id: ')
while True:
ret, frame = camera.read()
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
faces = detector.detectMultiScale(gray,
scaleFactor=1.2,
minNeighbors=3,
minSize=(100, 100)
)
# print(faces)
for (x,y,w,h) in faces:
index=index+1
cv2.imwrite("faceDataSet/personface-"+ id +'.'+ str(index) + ".jpg", gray[y:y+h,x:x+w])
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,250,0),2)
cv2.imshow('current',frame[y:y+h,x:x+w])
cv2.waitKey(1)
#change to higher number if needed
if index>19:
camera.release()
cv2.destroyAllWindows()
exit()
You can run this file multiple times, create a new id for each new face you want to add to the folder. Running it with the same id will overwrite the current picture. If you need to delete the files in the folder use the code below.
import os
import glob
files = glob.glob('faceDataSet/*')
for f in files:
print(f)
os.remove(f)
Next, we will create our trainer. This trainer will take in data from the pictures taken from faceDataCreator.py. The trainer is what will be learning in order to recognize faces. Create a file called trainer.py. Classify the cascade and create your recognizer. I will use a function to create a list of images and labels. Next train and save the recognizer. Include cv2.imshow() in the for loop if you want to see which picture the program is currently on.
import os
from cv2 import cv2
import numpy as np
from PIL import Image
currentPath = os.path.dirname(os.path.abspath(__file__))
print(currentPath)
faceCascade = cv2.CascadeClassifier(currentPath+r"\haarcascade\haarcascade_frontalface.xml")
recognizer = cv2.face.LBPHFaceRecognizer_create()
faceDataPath = currentPath+r'\faceDataSet'
def returnImageLabel(path):
images = list()
labels = list()
image_paths = [os.path.join(path, i) for i in os.listdir(path)]
for image_path in image_paths:
# convert to grayscale (L converts to gray scale), then convert image format to numpy
image = Image.open(image_path).convert('L')
image = np.array(image, 'uint8')
currentLabel = int(os.path.split(image_path)[1].split(".")[0].replace("personface-", ""))
print(currentLabel)
# detect the current faces
faces = faceCascade.detectMultiScale(image)
# append detected faces
for (x, y, w, h) in faces:
images.append(image[y: y + h, x: x + w])
labels.append(currentLabel)
return images, labels
images, labels = returnImageLabel(faceDataPath)
recognizer.train(images, np.array(labels))
recognizer.save(currentPath+r'\trainers\savedTrainer.yml')
The final file will be faceDetector.py. In this file we will launch the camera, recognize and predict who it is, draw a rectangle around the face and name who it is.
import os
from cv2 import cv2
import numpy as np
currentPath = os.path.dirname(os.path.abspath(__file__))
print(currentPath)
faceRecog = cv2.face.LBPHFaceRecognizer_create()
faceRecog.read(currentPath+r'\trainers\savedTrainer.yml')
faceCascade = cv2.CascadeClassifier(currentPath+r'\haarcascade\haarcascade_frontalface.xml')
cam = cv2.VideoCapture(0)
font = cv2.FONT_HERSHEY_SIMPLEX
while True:
ret, frame =cam.read()
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.2,
minNeighbors=3,
minSize=(100, 100)
)
for(x,y,w,h) in faces:
#create prediction
predictedPerson, conf = faceRecog.predict(gray[y:y+h,x:x+w])
##create rectangle
cv2.rectangle(frame,(x,y),(x+w,y+h),(225,0,0),2)
#change this to your id and name. Create a new if statement for new faces.
if(predictedPerson==1):
predictedPerson='Abhilash'
cv2.putText(frame,str(predictedPerson), (x,y+h),font, 1.0, (255,0,0))
cv2.imshow('Video',frame)
cv2.waitKey(10)