Face Recognition System is one of the most popular Python, Machine Learning, and Deep Learning projects.

What will you learn?

  1. Watch the demo video to get an idea of a project
  2. Part 1: Generate dataset
  3. Part 2: Train the classifier and save it
  4. Part 3: Face detection/recognition
  5. Part 4 (Converting the project into GUI)
  6. Part 5: (Connecting project to the database)
  7. (Extra )Part 6. GUI Face Recognition system using Tkinter-canvas
  8. Converting the project into a setup (Application) file

Demo:

View Complete Documentation

Part 1: Generate dataset

In Part 1, I must create the dataset. That implies I'll have to gather pictures. The Open-CV package can be used for this. To install this package, open any terminal and type:

pip install opencv-python

I am using the haarcascade_frontalface_default xml file to get the coordinates of my face so that I can crop it and use it to make a dataset and for future prediction.

I need to convert my RGB (Red, Green, Blue) images to grayscale. An RGB image has three channels, whereas a grayscale image has only one. It minimizes a lot of complexity when an image is converted to grayscale. The coordinates can then be obtained by utilizing the face classifier and the detectMultiScale technique. We must pass the scaling factor as well as the minimal neighbors. The scale factor is the factor that determines how much to modify from the original image. The number of minimum neighbors indicates how many faces to detect. A greater value yields less detection but of higher quality. We must experiment with this value. We can alter these parameters depending on our results. Then we simply collect the image and terminate the execution when it reaches 200 images or when we press the Enter key on the keyboard.

## pip install opencv-python
import cv2

def generate_dataset():
    face_classifier = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    def face_cropped(img):
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        faces = face_classifier.detectMultiScale(gray, 1.3, 5)
        # scaling factor = 1.3
        # minimum neighbor = 5
        
        if faces is ():
            return None
        for (x,y,w,h) in faces:
            cropped_face = img[y:y+h,x:x+w]
        return cropped_face
    
    cap = cv2.VideoCapture(1)
    id =1
    img_id = 0
    
    while True:
        ret, frame = cap.read()
        if face_cropped(frame) is not None:
            img_id+=1
            face = cv2.resize(face_cropped(frame), (200,200))
            face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
            file_name_path = "data/user."+str(id)+"."+str(img_id)+".jpg"
            cv2.imwrite(file_name_path, face)
            cv2.putText(face, str(img_id), (50,50), cv2.FONT_HERSHEY_COMPLEX, 1, (0,255,0), 2)
            
            cv2.imshow("Cropped face", face)
            
        if cv2.waitKey(1)==13 or int(img_id)==200: #13 is the ASCII character of Enter
            break
            
    cap.release()
    cv2.destroyAllWindows()
    print("Collecting samples is completed....")
generate_dataset()
 

Part 2: Train the classifier and save it

The next step is to train the classifier. Our system doesn't understand images, right? It needs to be converted into a Numpy array format so that it can make certain decisions based on this data. This part generates the classifier.xml file, which contains specific data (information) about our faces.
import os
import cv2
from PIL import Image #pip install pillow
import numpy as np    # pip install numpy

def train_classifier(data_dir):
    path = [os.path.join(data_dir, f) for f in os.listdir(data_dir)]
    
    faces = []
    ids = []
    
    for image in path:
        img = Image.open(image).convert('L')
        imageNp = np.array(img, 'uint8')
        id = int(os.path.split(image)[1].split(".")[1])
        
        faces.append(imageNp)
        ids.append(id)
        
    ids = np.array(ids)
    
    # Train and save classifier
    clf = cv2.face.LBPHFaceRecognizer_create()
    clf.train(faces,ids)
    clf.write("classifier.xml")
train_classifier("data")
 

Part 3: Face detection/recognition

In this part, I am going to make a prediction. I have defined one function name draw_boundary, which draws a boundary around my face and also displays my name at the top of my face. There are two identity persons 'Ishwar' and 'Manish'. Other than these two authorized persons, it will display 'UNKNOWN'.
import cv2
import numpy as np
from PIL import Image
import os

def draw_boundary(img, classifier, scaleFactor, minNeighbors, color, text, clf):
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    features = classifier.detectMultiScale(gray_img, scaleFactor, minNeighbors)
    
    for (x,y,w,h) in features:
        cv2.rectangle(img, (x,y), (x+w,y+h), color, 2 )
        
        id, pred = clf.predict(gray_img[y:y+h,x:x+w])
        confidence = int(100*(1-pred/300))
        
        if confidence>70:
            if id==1:
                cv2.putText(img, "Ishwar", (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 1, cv2.LINE_AA)
            if id==2:
                cv2.putText(img, "Manish", (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 1, cv2.LINE_AA)
        else:
            cv2.putText(img, "UNKNOWN", (x,y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 1, cv2.LINE_AA)
    
    return img

# loading classifier
faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

clf = cv2.face.LBPHFaceRecognizer_create()
clf.read("classifier.xml")

video_capture = cv2.VideoCapture(1)

while True:
    ret, img = video_capture.read()
    img = draw_boundary(img, faceCascade, 1.3, 6, (255,255,255), "Face", clf)
    cv2.imshow("face Detection", img)
    
    if cv2.waitKey(1)==13:
        break
video_capture.release()
cv2.destroyAllWindows()
 

Part 4 (Converting the above project into GUI):

(If you don't know about GUI, you must have to watch this video first: GUI using Tkinter)

Now let's convert the above project into a GUI application.

Why should we change our project to a graphical user interface? It is essential to transform any of our Python projects into a graphical user interface (GUI) if we intend to submit our code to our college or any place else. It's because we can do anything within the same window, right? We don't need to run each cell of code repeatedly.
import tkinter as tk
from tkinter import messagebox

window = tk.Tk()
window.title("Face Recognition system")

l1 = tk.Label(window, text="Name", font=("Algerian",20))
l1.grid(column=0, row=0)
t1 = tk.Entry(window, width=50, bd=5)
t1.grid(column=1, row=0)

l2 = tk.Label(window, text="Age", font=("Algerian",20))
l2.grid(column=0, row=1)
t2 = tk.Entry(window, width=50, bd=5)
t2.grid(column=1, row=1)

l3 = tk.Label(window, text="Address", font=("Algerian",20))
l3.grid(column=0, row=2)
t3 = tk.Entry(window, width=50, bd=5)
t3.grid(column=1, row=2)


b1 = tk.Button(window, text="Training", font=("Algerian",20),bg="orange",fg="red")
b1.grid(column=0, row=4)

b2 = tk.Button(window, text="Detect the faces", font=("Algerian",20), bg="green", fg="orange")
b2.grid(column=1, row=4)

b3 = tk.Button(window, text="Generate dataset", font=("Algerian",20), bg="pink", fg="black")
b3.grid(column=2, row=4)

window.geometry("800x200")
window.mainloop()

#other just copy code from previous part same like as I have done in this video
 

Part 5: (Connecting this project to the database)

(If you don't know how to connect any Python project to the database, you must have to watch this video first: Connect Python to the database)

Let's now link our project to the database:

In the preceding section, we just printed the authorized user's name. But this is not a good practice. We must save the user's information in the database. So, you must understand how to connect Python to a database. The user's information is now derived from the database rather than the code.

import tkinter as tk
from tkinter import messagebox
import cv2
import os
from PIL import Image
import numpy as np
import mysql.connector
window=tk.Tk()
window.title("Face recognition system")
#window.config(background="lime")
l1=tk.Label(window,text="Name",font=("Algerian",20))
l1.grid(column=0, row=0)
t1=tk.Entry(window,width=50,bd=5)
t1.grid(column=1, row=0)

l2=tk.Label(window,text="Age",font=("Algerian",20))
l2.grid(column=0, row=1)
t2=tk.Entry(window,width=50,bd=5)
t2.grid(column=1, row=1)

l3=tk.Label(window,text="Address",font=("Algerian",20))
l3.grid(column=0, row=2)
t3=tk.Entry(window,width=50,bd=5)
t3.grid(column=1, row=2)

def train_classifier():
    data_dir="C:/Users/Ishwar Gautam/Desktop/Face recognizer/data"
    path = [os.path.join(data_dir,f) for f in os.listdir(data_dir)]
    faces  = []
    ids   = []
    
    for image in path:
        img = Image.open(image).convert('L');
        imageNp= np.array(img, 'uint8')
        id = int(os.path.split(image)[1].split(".")[1])
        
        faces.append(imageNp)
        ids.append(id)
    ids = np.array(ids)
    
    #Train the classifier and save
    clf = cv2.face.LBPHFaceRecognizer_create()
    clf.train(faces,ids)
    clf.write("classifier.xml")
    messagebox.showinfo('Result','Training dataset completed!!!')
    
b1=tk.Button(window,text="Training",font=("Algerian",20),bg='orange',fg='red',command=train_classifier)
b1.grid(column=0, row=4)

def detect_face():
    def draw_boundary(img,classifier,scaleFactor,minNeighbors,color,text,clf):
        gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        features = classifier.detectMultiScale(gray_image,scaleFactor,minNeighbors)

        coords = []

        for(x,y,w,h) in features:
            cv2.rectangle(img,(x,y),(x+w,y+h),color,2)
            id,pred = clf.predict(gray_image[y:y+h,x:x+w])
            confidence = int(100*(1-pred/300))
            
            mydb=mysql.connector.connect(
            host="localhost",
            user="root",
            passwd="",
            database="Authorized_user"
            )
            mycursor=mydb.cursor()
            mycursor.execute("select name from my_table where id="+str(id))
            s = mycursor.fetchone()
            s = ''+''.join(s)
            
            if confidence>74:
                cv2.putText(img,s,(x,y-5),cv2.FONT_HERSHEY_SIMPLEX,0.8,color,1,cv2.LINE_AA)   
            else:
                cv2.putText(img,"UNKNOWN",(x,y-5),cv2.FONT_HERSHEY_SIMPLEX,0.8,(0,0,255),1,cv2.LINE_AA)

            coords=[x,y,w,h]
        return coords
            
    def recognize(img,clf,faceCascade):
        coords = draw_boundary(img,faceCascade,1.1,10,(255,255,255),"Face",clf)
        return img

    faceCascade=cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    clf = cv2.face.LBPHFaceRecognizer_create()
    clf.read("classifier.xml")

    video_capture =  cv2.VideoCapture(0)

    while True:
        ret,img = video_capture.read()
        img=  recognize(img,clf,faceCascade)
        cv2.imshow("face detection",img)

        if cv2.waitKey(1)==13:
            break

    video_capture.release()
    cv2.destroyAllWindows()

b2=tk.Button(window,text="Detect the face",font=("Algerian",20),bg='green',fg='white',command=detect_face)
b2.grid(column=1, row=4)

def generate_dataset():
    if(t1.get()=="" or t2.get()=="" or t3.get()==""):
        messagebox.showinfo('Result','Please provide complete details of the user')
    else:
        mydb=mysql.connector.connect(
        host="localhost",
        user="root",
        passwd="",
        database="Authorized_user"
        )
        mycursor=mydb.cursor()
        mycursor.execute("SELECT * from my_table")
        myresult=mycursor.fetchall()
        id=1
        for x in myresult:
            id+=1
        sql="insert into my_table(id,Name,Age,Address) values(%s,%s,%s,%s)"
        val=(id,t1.get(),t2.get(),t3.get())
        mycursor.execute(sql,val)
        mydb.commit()
        
        face_classifier = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
        def face_cropped(img):
            gray  = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            faces = face_classifier.detectMultiScale(gray,1.3,5)
            #scaling factor=1.3
            #Minimum neighbor = 5

            if faces is ():
                return None
            for(x,y,w,h) in faces:
                cropped_face=img[y:y+h,x:x+w]
            return cropped_face

        cap = cv2.VideoCapture(0)
        img_id=0

        while True:
            ret,frame = cap.read()
            if face_cropped(frame) is not None:
                img_id+=1
                face = cv2.resize(face_cropped(frame),(200,200))
                face  = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
                file_name_path = "data/user."+str(id)+"."+str(img_id)+".jpg"
                cv2.imwrite(file_name_path,face)
                cv2.putText(face,str(img_id),(50,50),cv2.FONT_HERSHEY_COMPLEX,1, (0,255,0),2)
                # (50,50) is the origin point from where text is to be written
                # font scale=1
                #thickness=2

                cv2.imshow("Cropped face",face)
                if cv2.waitKey(1)==13 or int(img_id)==200:
                    break
        cap.release()
        cv2.destroyAllWindows()
        messagebox.showinfo('Result','Generating dataset completed!!!')

b3=tk.Button(window,text="Generate dataset",font=("Algerian",20),bg='pink',fg='black',command=generate_dataset)
b3.grid(column=2, row=4)

window.geometry("800x200")
window.mainloop()

Part 6. GUI Face Recognition system using Tkinter-canvas

This is an extra step to make an awesome GUI application.

(Note: This part is clearly explained in the Nepali language Face Recognition Video.)

import tkinter as tk
from tkinter import *
import cv2
import os
from PIL import Image, ImageTk
import numpy as np
import mysql.connector
from tkinter import messagebox

Divide window

window = tk.Tk()
window.title("Project")
window.resizable(0,0)

load1 = Image.open("header.png")
photo1 = ImageTk.PhotoImage(load1)


header = tk.Button(window, image=photo1)
header.place(x=5, y=0)

canvas1 = Canvas(window, width = 500, height=250, bg='ivory')
canvas1.place(x=5, y=120)

l1 = tk.Button(canvas1, text="Name", font=("Algerian",15))
l1.place(x=5, y=5)
t1 = tk.Entry(canvas1, width=50, bd=5)
t1.place(x=150, y=10)

l2 = tk.Button(canvas1, text="Age", font=("Algerian",15))
l2.place(x=5, y=50)
t2 = tk.Entry(canvas1, width=50, bd=5)
t2.place(x=150, y=55)

l3 = tk.Button(canvas1, text="Address", font=("Algerian",15))
l3.place(x=5, y=100)
t3 = tk.Entry(canvas1, width=50, bd=5)
t3.place(x=150, y=105)


b1= tk.Button(canvas1, text="Training", font=("Algerian",20), bg='orange', fg='red')
b1.place(x=10, y=180)

b2= tk.Button(canvas1, text="Generate dataset", font=("Algerian",20), bg='pink', fg='black')
b2.place(x=175, y=180)

load2= Image.open("canvas2.png")
photo2 = ImageTk.PhotoImage(load2)

canvas2 =  Canvas(window, width=500, height=250)
canvas2.place(x=5, y=400)
canvas2.create_image(250,125,image=photo2)

b3 = tk.Button(canvas2, text="Capture the image", font=("Algerian",20), bg="gray", fg="black")
b3.place(x=5, y=50)

b4 = tk.Button(canvas2, text="Predict face from live video", font=("Algerian", 20), bg="cyan", fg="black")
b4.place(x=5, y=150)

load3= Image.open('canvas3.png')
photo3 = ImageTk.PhotoImage(load3)

canvas3 = Canvas(window, width=280, height=530)
canvas3.place(x=515, y=120)
canvas3.create_image(140, 265, image=photo3)

window.geometry("800x680")
window.mainloop()

 

Converting the above project into a setup (Application) file:

To run the code, you must launch your Python IDE, right? After this section, you won't need it anymore. Transform your entire project into an application or setup file. You can open this project just like any other application, such as a game.

Conclusion:

In this way, you can make a complete Face Recognition System project. Make sure to watch each video step by step to prevent any errors. This post illustrates how you can make a Face recognition project with the OpenCV library. If you are searching for making this project using deep learning, you can click here.

I hope this project is very helpful to you. If you have any questions, you can comment below. I will reply as soon as possible. Thanks.