# Real-Time Face Verification Login System for Website

#### From scratch till deployment

In this section, we’ll learn how to build a facial verification login system for websites.

***Here I kept the web design simple enough for two reasons:***

*1\. I haven’t explored web development a lot till now.*

*2\. Secondly, To keep the deployment stuff relatively easier for the audience to understand the procedure and mainly utilise their time in building the project instead of resolving version-related issues for different environment the audience are working on during their practical implementation.*

<iframe src="https://www.youtube.com/embed/1WisGZCGv9k?feature=oembed" width="700" height="393"></iframe>

**Tasks to perform:**

1. **Build Facial Verification model:  
    \-** MTCNN  
    \- VGG faceNet using ResNet50  
    \- Euclidean distance / Cosine similarity
    
2. **Model deployment.**  
    \- Firebase Database  
    \- Flask
    

Now getting started with the implementation:

1. **Building a Facial Verification Model:  
    \*Stage-01:   
    *Face Detection*** - \*A very first task for the model is to detect a face in the given frame/image. For this, we have multiple approaches:  
    \- MTCNN  
    \- Haar Cascade  
    \- CNN  
    \- DeepFace  
    \***For this project, we’ll be using MTCNN because of its better performance in face detection.**
    

Create a Python file and name it **Extract\_face\_Mtcnn\_stage01.py**

""" Goal: """  
\# Extract Face using MTCNN from Images

""" Libraries """  
from PIL import Image  
import numpy as np  
from mtcnn.mtcnn import MTCNN

x1, y1, x2, y2 =0, 0, 0, 0

\# detected face from image  
def extract\_face\_n\_labels(mImage, imageIsArray=True):

\# using MTCNN for face detector in an image  
detector = MTCNN()

cropped\_face = \[\]

global x1, y1, x2, y2

if imageIsArray == True:

pixels = mImage

\# MTCNN for face detection  
face\_detected = detector.detect\_faces(pixels)  
print('face\_detected, proccessed values: ', face\_detected)

if face\_detected: # if face\_detected list not empty

\# getting the bounding box of detected face  
x1, y1, w, h = face\_detected\[0\]\['box'\]

x1, y1 = abs(x1), abs(y1)  
x2 = abs(x1 + w)  
y2 = abs(y1 + h)

\# get face from the image by slicing out using coordinates & store it  
store\_face = pixels\[y1:y2, x1:x2\] # y -&gt; rows, x -&gt; columns

\# for verification plotting the face  
\# plt.imshow(store\_face)

image1 = Image.fromarray(store\_face, 'RGB') # convert the numpy array to object  
image1 = image1.resize((224, 224)) # resize the image  
face\_array = np.array(image1) # image1 to numpy array

\# increase the dim as VGGnet needs 4d  
face\_array = np.expand\_dims(face\_array, axis=0)

\# get list of all numpy face arrays  
cropped\_face.append(face\_array)

zipped\_coord = \[x1,y1,x2,y2\]

\# return cropped\_face, array\_img\_labels  
return cropped\_face, zipped\_coord

Don’t go towards the length of the code here we are performing 3 things:  
1\. **imageIsArray** - Checking if the passed image to the function is an array. (Well this if statement is optional if you are sure you are going to call this function by passing Image converted into an array then no need to use this parameter and this if statement either)

2\. **Face detecting -** Using MTCNN

3\. **Cropping Image -** With the help of the coordinates of the detected face we are going to crop the image, So now the new image consists of only the detected face so that further facial feature processing could occur only over the face, not over the unwanted background.

**\*Stage-02:   
*Create Face Embeddings -*** *Now that we have cropped the image, it’s time to dive deeper Into the facial verification model. Now we want our model to tell the difference between the faces. Whether the two faces are similar or not.  
One way to do this is by passing an image to the model and allowing it to learn the features based on its pixel values and bringing the output accordingly.  
But, this approach takes time and is inefficient for this situation.  
So, instead, we’ll be calculating the distances of some major facial features instead of the whole face.*

> **This approach also helps in avoiding errors while processing images in different lighting conditions, because now the model is not learning over the pixel values instead it has calculated the distances of the facial features which is not affected by any lighting conditions.**

So these distances are nothing but embedded features(1D vector). In order to calculate embedded features we again have a lot of approaches available here:  
\- FaceNet  
\- DeepFace  
\- OpenFace  
\- VGG-Face  
\*\*[Accuracy of these models](http://accuracy%20of%20these%20models)\*\*

We’ll be using VGG-Face for our model building. VGG-model produces random facial measurements called embedded features. Well, you don’t have to worry about which random facial features are they.

Create a Python file and name it **Embedded\_Features\_VggNet\_stage02.py**

""" Goal: """  
\# Getting Embedded Features using VggNet from Images

""" Libraries """  
from keras\_vggface.vggface import VGGFace #model.py change to tensorflow.keras.utils  
from keras.layers import MaxPooling2D, ZeroPadding2D, Convolution2D, Dropout, Flatten, Activation  
from keras.models import Model, Sequential

def vgg\_model\_building():

"""Method-01: Build Vgg model (BASED ON RESNET50)"""  
vgg\_model = VGGFace(model='resnet50', weights='vggface', include\_top=False,  
input\_shape=(224, 224, 3), pooling='avg')

########################################################################

"""Method-02: Vgg model (BASED ON VGG16)"""  
model = Sequential()  
model.add(ZeroPadding2D((1, 1), input\_shape=(224, 224, 3)))  
model.add(Convolution2D(64, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(64, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(128, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(128, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(256, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(256, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(256, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(512, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(512, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(512, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(512, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(512, (3, 3), activation='relu'))  
model.add(ZeroPadding2D((1, 1)))  
model.add(Convolution2D(512, (3, 3), activation='relu'))  
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(Convolution2D(4096, (7, 7), activation='relu'))  
model.add(Dropout(0.5))  
model.add(Convolution2D(4096, (1, 1), activation='relu'))  
model.add(Dropout(0.5))  
model.add(Convolution2D(2622, (1, 1)))  
model.add(Flatten())  
model.add(Activation('softmax'))

\# link to download these weights is given below  
model.load\_weights('vgg\_face\_weights.h5')

vgg\_model = Model(inputs=model.layers\[0\].input,  
outputs=model.layers\[-2\].output)

return vgg\_model

def embedded\_feature(model, img):

return model.predict(img)

**Download weights for vgg-face:** [https://www.kaggle.com/datasets/acharyarupak391/vggfaceweights](https://www.kaggle.com/datasets/acharyarupak391/vggfaceweights)

> ***Please Note:*** As you will run the code it might raise an error at the line **‘from keras\_vggface.vggface import VGGFace’** as No module named ‘**keras.engine.topology**’ .  
> for this just open **models.py** you will get the link of the models.py file at error terminal itself, open it and replace ‘**from keras.engine.topology import get\_source\_inputs’** with **‘from tensorflow.keras.utils import get\_source\_inputs’**

In the **vgg\_model\_building**() function I have shown two methods for building the vgg model. One is simply importing vgg-face and specifying state-of-the-art architecture(RestNet50) and the second one is building the layers of the architecture(VGG16). Both architectures are different so it's up to you whichever you find compatible with your system follow it accordingly and ***comment out*** the one you don’t follow.

Also please notice in the implementation of VGG16 architecture at the end we have flattened the CNN layers which produce 1D vectors consisting of 2622 elements, well these vectors are nothing but the embedded vectors only consisting of the facial features. Whereas, if we use the prebuilt model of ResNet50 as vgg\_model then we get 2048 facial features.

**\*Stage-03:  
Face Verification -** If you followed till now congrats we are now at the last stage of the model building, at this stage we’ll be calculating the distances of embedded features of the **stored database users(*db\_user\_embedding*)** and the **current login user(*current\_user\_embedding*)**  
For the time being, if you don’t understand what’s the meaning of database user here. So, hold down your horses, I’ll be explaining it in the deployment stage you will get to know the whole picture behind using these terms.  
For now, just think of it as if we are going to compare both faces by calculating the distance of embedded features(facial measurements).  
If the distance is large that means both images are different and if the distance is close to 0 then the face is similar which means the user is similar to the one stored in a database.  
To calculate the similarity of the face we can use:  
1\. Euclidean distance  
2\. Cosine Similarity  
We’ll be seeing both of them in the code, in order to understand how to implement them, but for the final stage Euclidean distance we’ll going to be the major deciding factor as it performs really well in this situation compared to cosine similarity.

Create a Python file and name it **Face\_Verification\_stage03.py**

""" Goal: """  
\# Finally Face Verifiction step using Euclidean distance

""" Libraries """  
import numpy as np

\# Euclidean distance  
def euclid\_dist(db\_user\_embeddings, current\_user\_embeddings):

euclidean\_dist = np.linalg.norm(db\_user\_embeddings - current\_user\_embeddings)

return euclidean\_dist

\# Cosine similarity calculation  
def cosine\_sim(db\_user\_embeddings, current\_user\_embeddings):

a = np.matmul(np.transpose(db\_user\_embeddings), current\_user\_embeddings)

b = np.sum(np.multiply(db\_user\_embeddings, current\_user\_embeddings))

c = np.sum(np.multiply(db\_user\_embeddings, current\_user\_embeddings))

cosine\_similarity = 1 - (a / (np.sqrt(b) \* np.sqrt(c)))

return cosine\_similarity

\# face verification calculation  
def verify\_face(db\_user\_embeddings, current\_user\_embeddings):

\# setting a threshold value  
threshold\_cosine = 0.45 # cosine  
threshold\_euclid = 120 # Euclid

\# Euclidean Distance  
euclid\_distance = euclid\_dist(db\_user\_embeddings, current\_user\_embeddings)

"""to verify"""  
\# if euclid\_distance &lt; threshold\_euclid:  
\# print('By Euclidean - Face verified!!')  
#  
\# else:  
\# print("By Euclidean - Face isn't verified!!")

\# Cosine Similarity  
cosine\_similarity = cosine\_sim(db\_user\_embeddings, current\_user\_embeddings)

"""to verify"""  
\# if cosine\_similarity &lt; threshold\_cosine:  
\# print('By Cosine similarity - Face verified!!')  
#  
\# else:  
\# print("By Cosine similarity - Face isn't verified!!")

return euclid\_distance, cosine\_similarity, threshold\_cosine, threshold\_euclid

Finally Congrats!!! we are done with the model-building part.

2\. **Deployment:**

Building up the model is never enough until the model is deployed so that model can be utilized by the community too.

### **Deployment Thoughts:**

1. We’ll create a **signup page** that consists of email and password as input fields as well as the live streaming window. It captures the image and sends it to the model which returns the embedded feature of the input image.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727510738386/7605244e-6e81-4930-a7ee-2f5257a55977.png align="left")

Signup Page

2. Store the email ID, password and embedded feature of the new user in the Firebase database.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727510740410/04091f6d-5591-48cd-b640-c4d264ef29a2.png align="left")

3. Now we’ll create a **login page** that takes the email ID **and password** from the user and in the backend, we’ll search for the current user in the database using its email ID as a unique identifier in this project. If the user didn’t remember his password can able to switch to **Forget Password Page.**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727510741791/0bc2fcdf-dd72-4142-827f-1e75edcb028d.png align="left")

Login Page

4. The idea behind this project is generally if the user forgets their password they get an OTP via email for the verification process. But we’ll optimize this process by replacing OTP verification with the Facial Verification process.
    
5. So finally **Forget Password page** consists of a Live streaming window that takes the current user image and sends it to the model, the model returns the embedded feature calling it **current\_user\_embedding.** Now before switching to Forget Password page user needs to enter the email ID so as to find the current user email-ID existence in the database and then retrieve the respective embedded feature from the database calling it **db\_user\_embedding.**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727510743474/e3ba89b9-6098-40dc-aade-d96209f58377.png align="left")

Forget Password Page for Facial Verification

6. Now the final goal is to do the verification of the user by calculating the Euclidean distance/Cosine similarity of both the embeddings (**db\_user\_embedding** & **current\_user\_embedding**). If the verification is successful send the user to the **home page.**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727510745548/802f0609-ac99-4c22-9300-1d8874c7c680.png align="left")

Home Page

> \*\*Connecting the Firebase database with the project:  
> \*\*1. Please follow the below link for complete guide for firebase python connectivity:  
> [https://medium.com/theleanprogrammer/connecting-firebase-6102ef4eca08](https://medium.com/theleanprogrammer/connecting-firebase-6102ef4eca08)

> **Hustling in this step will make you explore more about firebase, if your are new to firebase database.**

We performed various operations in all the 3 stages, hence in order to keep the code easy to understand we’ll going to merge all of them in an optimized manner in one Python file. So, if we want to perform any model operation we can simply import this Python file.

Create a Python file and name it **ForgetPassword\_page.py**

""" Goal: Gathering all the stages in one file for the clean implementation """

"""Process:  
1\. Prepare MTCNN function  
2\. Prepare Embeddings function  
3\. Merge them all and reshape the embedded feature  
"""

""" Libraries """  
import Extract\_Face\_Mtcnn\_stage01  
import Embedded\_Features\_VggNet\_stage02

\# Prepare cropped image using MTCNN  
def prepare\_mtcnn(image\_path, bool\_val):

x\_cropped\_face, zipped\_coord = Extract\_Face\_Mtcnn\_stage01.extract\_face(image\_path, bool\_val)

return x\_cropped\_face, zipped\_coord

\# Prepare facial embeddings using vgg\_model  
def prepare\_Embeddings(cropped\_face):

Cropped\_img = cropped\_face\[0\]

\# VGG model based on ResNet50  
model = Embedded\_Features\_VggNet\_stage02.vgg\_model\_building()

\# emebedded feature of the cropped\_face  
embedded\_face = Embedded\_Features\_VggNet\_stage02.embedded\_feature(model, Cropped\_img)

return embedded\_face

\# get the current user data opted for forget password  
def currentUser\_ImageProcess(ImageArray):

\# Sends the image array for MTCNN -&gt; Embedded  
\# 1. MTCNN  
cropped\_face, zipped\_corrd = prepare\_mtcnn(ImageArray, bool\_val=True)

\# 2, Embeddings  
embedded\_face = prepare\_Embeddings(cropped\_face)

currentUser\_embedded\_face = embedded\_face\[0, :\] # \[0,:\] -&gt; to bring the shape from (1,2048) to (2048,)

return currentUser\_embedded\_face

**Starting with the deployment implementation part:**

Well, if you are a beginner in Python this section will going to be quite lengthy and a bit difficult to understand, hence I have commented on each line of the code for a better understanding.

Create a new Python file and name it **Signup\_page\_addNewuser.py**

""" Goal: Run Flask to:

1. Add new User into our database (Signup Page)
    
2. Build Login Page (verify current user email\_id + if password not remember switch to forget passwprd page)
    
3. Build Forget Password Page (Use Facial verification in forget password)
    

\## Need to save 3 things into the database:

* Email\_ID
    
* Password
    
* Facial Embedded feature of the new user."""
    

"""Process:

1\. Database connectivity

2\. Signup Page:  
\# Takes input  
\- Email ID  
\- Password  
\- Image (Live stream using webcam)  
\*\* Finally Saves all the 3 thing into the database.

3\. Login Page:  
\# Takes input  
\- Email  
\- Password (If not remember switch to forget pass page)  
\- Before switching verify whether email\_id is existing in Db, if not then  
current user goes back to the Signup Page.  
\- If current user email id verified then fetch its appropriate Face embedding from database using its email id as unique identifiers for searching.

4\. Forget Password page:  
\# Takes input:  
\- Image(From live streaming Face Detection \[used Haar Cascade\])  
\- Calculate Current User Face Embedding.  
\- Match the Db Embedding and Current User Embedding  
If, matches then go to Home page.  
else, back to login page

"""

""" Libraries """  
import cv2  
import numpy as np  
import ForgetPassword\_page\_FaceVerification  
import firebase\_admin  
from firebase\_admin import credentials,db  
import yaml  
import json  
from json import JSONEncoder  
from flask import Flask, render\_template, request, Response, redirect, url\_for, flash  
from PIL import Image  
import Face\_Verifiction\_stage03  
import threading  
import time

"""Getting Config file"""  
with open('config.yml', 'r') as file:  
config\_data = yaml.safe\_load(file)

app = Flask(\_\_name\_\_)  
app.secret\_key = "super secret key"  
\# for displaying msg for custom duration after successful signup  
app.config\['MESSAGE\_FLASHING\_OPTIONS'\] = {'duration': 100}

"""Global Variables"""  
capture = 0  
mcapture = 0  
error = None  
successfulMsg = None

ImageArray = np.array(\[\])  
imgArray = np.array(\[\])

dbUser\_embedding = np.array(\[\])  
currentUser\_embedding = np.array(\[\])

euclid\_distance=0  
cosine\_similarity=0  
threshold\_cosine=0  
threshold\_euclid=0

\# declaring lock  
forgetPage\_lock = threading.Lock()  
mainThread\_lock = threading.Lock()

cam = cv2.VideoCapture(2)

\# Step-1  
\# connect with database  
def connect\_database():

cred = credentials.Certificate('fb\_credentials.json')

\# Initialize the app with a service account, granting admin privileges  
firebase\_admin.initialize\_app(cred, {  
'databaseURL': config\_data\['databaseURL'\]}) # getting url stored in config file

return db

database = connect\_database()

#################  
"""SignUp Page"""  
#################

\# Step 2  
@app.route("/", methods=\['GET', 'POST'\])  
def signup():

global capture, error, successfulMsg

if request.method == 'POST':

\# if Capture Image & SignUp button pressed, save the data into database  
if request.form.get('Signup\_action') == 'Capture Image & SignUp':

email = request.form\['email'\]  
password = request.form\['password'\]  
print(email, password) # to verify

\# check whether the entered value is empty  
if request.form\['email'\] == '' or request.form\['password'\] == '':  
error = 'Please enter values in the input field'

else:  
capture = 1 #if signup button pressed then set capture=1

\# sending email,password for database operation(saving these values)  
push\_data2Database(email, password)

\# Throw msg if user data successfully saved  
successfulMsg = "Data Saved"  
flash(successfulMsg, 'success') # flash a msg after task is successfully done

return redirect(url\_for('login'))

\# otherwise if login button pressed then switch to login page  
elif request.form.get('login\_action') == 'Login':

return redirect(url\_for('login'))

else:  
pass # unknown

return render\_template('Signup\_page.html', error=error, msg = successfulMsg)

\# Generate frames for Live streaming on Signup page  
def SignupVideoGen():

""" Opencv cam """  
\# cam = cv2.VideoCapture(2)

global capture, ImageArray

\# Take user image: \[OpenCV\]  
while True:

ret, frame = cam.read()

\# Convert the image into array and store into global np array variable  
ImageArray = np.array(frame)

if ret:

if (capture): # if capture button clicked then capture has set 1 and click img

capture = 0  
cv2.imwrite('img.jpg',frame)

\# process the image and produce facial embeddings  
convert2FacialEmbeddings()

\# encode the frame so that flask can return it as a response  
ret, buffer = cv2.imencode('.jpg',frame)

\# convert each frame to a byte object  
frame = buffer.tobytes()

\# concat frame one by one and show result  
yield (b'--frame\\r\\n'  
b'Content-Type: image/jpeg\\r\\n\\r\\n' + frame + b'\\r\\n')

\# return Frames to the flask signup template  
@app.route('/video\_feed')  
def video\_feed():  
return Response(SignupVideoGen(), mimetype='multipart/x-mixed-replace; boundary=frame')

#################  
"""Login Page"""  
#################

\# Step 3  
\# Task:  
\# 1. check if current user email exist in db.  
\# 2. If yes then fetch the appropriate embedded feature for facial verification  
@app.route('/login', methods=\['POST', 'GET'\])  
def login():

global currentUser\_embedded\_face, dbUser\_embedding, error, database

\# refrencing the database  
ref = database.reference('/Users')

if request.method == 'POST':

\# pressed forget password key  
if request.form.get('forget\_action') == 'Forget Password':

if request.form\['email'\] == '':  
error = 'Please enter your Email Address'

\# 1.check if email exist in db

else:

\# get the email id from current user  
email = request.form\['email'\]  
print(email)

\# creating list of child node of db  
child\_id = \[\]  
for i in range(1, 5): # lets us assume we have only 5 users in db  
child\_id.append(str(i))

\# search for child node  
for i in child\_id:  
user = ref.child(i).get()

if user != None:

if user\['email'\] == email: # searching current user in db via email  
print('found email at child node:', i)

\# 2. Fetched appropriate Face embidding using emailID as unique identifier  
encodded\_embedding = user\['embeddings'\]  
print(type(encodded\_embedding))

\# Deserailize the embeddings  
print("Decode JSON serialized NumPy array")  
decodded\_embedding = json.loads(encodded\_embedding)  
dbUser\_embedding = np.array(decodded\_embedding\["embeddings"\])

return redirect(url\_for('forget\_password'))

else:  
error = "Please enter valid email, Signup if new?"

return render\_template('Login\_page.html', error=error)

##########################  
"""Forget Password Page"""  
##########################

\# Step 4  
\# If current User is the existing User in the DB...Then for auth forget password page  
"""  
Forget Password Page:  
1\. Consist of Live streaming Face detection.  
2\. Button to click the photo for verification  
"""  
@app.route('/forget\_password', methods=\['GET', 'POST'\])  
def forget\_password():

global mcapture  
global euclid\_distance, cosine\_similarity, threshold\_cosine, threshold\_euclid

if request.method == 'POST':

\# if Verify button pressed Start verfication process(MTCNN, Emebedd, Euclid)  
if request.form.get('verify\_action') == 'Verify Image':

print("Verify button clicked")  
mcapture = 1

\# use try except block to release lock because if release function run done twice then error arises.  
try:  
forgetPage\_lock.release()

except:  
print("Click verify button only once, lock already released'")  
return render\_template('ForgetPassword\_page.html')

\# for getting the face verification results sleep down this function for 4.5sec  
time.sleep(4.5)

\# recieved verification results, updated by ForgetPass\_videoGen function  
print('recieved verification results:')  
print(euclid\_distance, cosine\_similarity, threshold\_cosine, threshold\_euclid)

\# If Face verified, give access to the user  
if euclid\_distance &lt; threshold\_euclid:

print('Face Verified!!')  
return redirect(url\_for('home'))

else:  
print('Face Not Verified')  
return redirect(url\_for('login'))

return render\_template('ForgetPassword\_page.html')

mainThread\_lock.acquire() #blocking main thread to avoid ForgetPassVideo run at first call

\# Generate frames for streaming on ForgetPassword page  
"""  
It performs:  
1\. Live streaming with Face detection.  
2\. Facial Verification  
"""  
def ForgetPassVideoGen():

global ImageArray, mcapture, x, y, w, h, currentUser\_embedding, imgArray  
global euclid\_distance, cosine\_similarity, threshold\_cosine, threshold\_euclid

\# after generator run once lock the thread  
forgetPage\_lock.acquire()

\# Using Haar cascade for realtime face detection  
\# \[Motive\] -&gt; To display user its detected face which guide them  
\# to click image at correct timing.

face\_detector = cv2.CascadeClassifier('haarcascade\_frontalface\_alt.xml')

\# Take user image: \[OpenCV\]  
while True:

ret, frame = cam.read()

if ret:

"""Displaying Live Face detected bbox for users"""  
\# NOTE: cann't use MTCNN for face bbox creation  
\# bcz it is very slow as compared to Haar caascade

gray = cv2.cvtColor(frame, cv2.COLOR\_BGR2GRAY)  
faces = face\_detector.detectMultiScale(gray, 1.1, 4)

for (x, y, w, h) in faces:  
cv2.rectangle(frame, pt1=(x, y), pt2=(x + w, y + h),  
color=(255, 0, 0), thickness=3)

"""When verify button is pressed"""  
if (mcapture): # verification button pressed & mcapture becomes 1

mcapture = 0

"""Preparing Image for verification Process"""  
\# Convert the image into array and store into global numpy array variable  
ImageArray = np.array(frame)

img = Image.fromarray(ImageArray) # convert from array to image onject

img = img.convert(colors='RGB') # convert image object to RGB

imgArray = np.array(img) # converting image RGB back to np array

"""  
Performing Image verification process  
1\. Getting CurrentUser emebeddings.  
2\. Finall Facial Verification stage(Match the database & currentUser embedding)  
"""

\# 1. Current user embedding  
currentUser\_embedding = ForgetPassword\_page\_FaceVerification.currentUser\_ImageProcess(imgArray)

\# 2. Facial Verification stage  
euclid\_distance, cosine\_similarity, threshold\_cosine, threshold\_euclid = Face\_Verifiction\_stage03.verify\_face(dbUser\_embedding,currentUser\_embedding)

"""to verify code results"""  
\# print('Verification Results:....')  
\# print('euclid\_distance: ',euclid\_distance)  
\# print('cosine\_similarity: ',cosine\_similarity)  
\# print('threshold\_cosine: ',threshold\_cosine)  
\# print('threshold\_euclid: ',threshold\_euclid)

\# encode the frame so that flask can return it as a response in  
ret, buffer = cv2.imencode('.jpg', frame)

\# convert each frame to a byte object  
frame = buffer.tobytes()

\# concat frame one by one and show result  
yield (b'--frame\\r\\n'  
b'Content-Type: image/jpeg\\r\\n\\r\\n' + frame + b'\\r\\n')

\# Returns video feed to the Forget Password page  
@app.route('/ForgetPassVideo\_feed')  
def ForgetPassVideo\_feed():  
return Response( ForgetPassVideoGen(), mimetype='multipart/x-mixed-replace; boundary=frame' )

\# Home  
@app.route('/home')  
def home():

return render\_template('Home\_page.html')

##################################################################################

\# For Step-1  
\# Convert Image to Embedded form \[Only for Sigup Clicked Image\]  
def convert2FacialEmbeddings():

global ImageArray

img = Image.fromarray(ImageArray) #convert from array to image onject

img = img.convert(colors='RGB') # convert image object to RGB

imgArray = np.array(img) # converting image RGB back to np array

\# Sends the image array for MTCNN -&gt; Embedded  
\# 1. MTCNN  
cropped\_face, zipped\_coord = ForgetPassword\_page\_FaceVerification.prepare\_mtcnn(imgArray, bool\_val=True)

\# 2, Embedded  
embedded\_face = ForgetPassword\_page\_FaceVerification.prepare\_Embeddings(cropped\_face)

embedded\_face = embedded\_face\[0, :\] # \[0,:\] -&gt; to bring the shape from (1,2048) to (2048,)

return embedded\_face

#####################################  
\# converting np.array in json format  
#####################################

\# used for converting numpy array emmbedded feature json for pushing in db  
class NumpyArrayEncoder(JSONEncoder):  
def default(self, obj):  
if isinstance(obj, np.ndarray):  
return obj.tolist()  
return JSONEncoder.default(self, obj)

\# Push user data into database  
def push\_data2Database(user\_email, user\_password):

""" Connecting to database """  
global database

""" get user data for storing """  
embedded\_face = convert2FacialEmbeddings()  
email, password = user\_email, user\_password

""" Store values into database """

"""  
We Have three value to store:  
1\. Email as string  
2\. Password as String  
3\. Embedded face as array, so convert into json and then save to firebase.  
"""

\### Before pushing np.array embedded\_face to db convert it to json ##

\# Serialization embedded\_face  
numpyData\_embedding = {"embeddings": embedded\_face}  
encoded\_EmbeddedData = json.dumps(numpyData\_embedding, cls=NumpyArrayEncoder) # use dump() to write array into file

\# prepare data to insert  
data = {'email': email, 'password': password, 'embeddings':encoded\_EmbeddedData}

\# created reference of database  
ref = database.reference('/Users')

\# Save data into database  
ref.child('1').set(data)

def runFlask():  
app.run()

if \_\_name\_\_ == '\_\_main\_\_':

thread1 = threading.Thread(target=runFlask, name='thread-1')  
thread2 = threading.Thread(target=ForgetPassVideoGen, name='thread-2')

thread1.start()  
thread2.start()

"""Small Note"""  
\# activate thread2 when we are at ForgetPassword\_page  
\# else, keep it lock  
\# lock.acquire() -&gt; lock thread  
\# lock.release() -&gt; unlock thread

* The threading concept was used in this project in order to make the two tasks run separately that is **forget\_password**() function and **ForgetPassVideoGen**().
    
* Earlier without threading, **forget\_password**() runs only once because of which global variable **euclid\_distance, cosine\_similarity, threshold\_cosine,** and **threshold\_euclid** gets updated in **ForgetPassVideoGen().** This does not make the **forget\_password**() function aware of these variable changes.
    
* Now the question arises why do we want **forget\_password**() to get aware of these changes? because after all, the **forget\_password**() runs over the server and can perform a page switching to the **home page** after successful verification. whereas **ForgetPassVideoGen()** is a generator function whose task is to generate multiple frames for live streaming.
    
* So to avoid this problem we have to use the threading concept to run both of these tasks parallelly over 2 independent threads.
    
* At the same time, we used the lock and release concept of multi-threading to have control over their activities during the program.
    

> With the threading concept if you would have noticed in **forget\_password()** we made the function sleep for 4.5 sec, by that time the **ForgetPassVideoGen()** updates the global variables **euclid\_distance, cosine\_similarity, threshold\_cosine,** and **threshold\_euclid** on a different thread and then these updated variables can be utilized back in **forget\_password**() function for the verification process after sleep duration is over.

### Templates:

1. **SignUp Page:**
    

Signup

&lt;div class="container"&gt;  
&lt;h1&gt;Signup&lt;/h1&gt;  
&lt;br&gt;  
&lt;form action="" method="post"&gt;

&lt;input type="text" placeholder="Email" name="email" value="{{  
request.form.email }}"&gt;

&lt;input type="password" placeholder="Password" name="password" value="{{  
request.form.password }}"&gt;

&lt;input type="submit" value="Capture Image & SignUp" name="Signup\_action"/&gt;

&lt;/form&gt;

{% if error %}  
&lt;p class="error"&gt;&lt;strong&gt;Error:&lt;/strong&gt; {{ error }}  
{% endif %}

&lt;div class="container"&gt;

&lt;div class="row"&gt;  
&lt;div class="col-lg-8 offset-lg-2"&gt;  
&lt;h3 class="mt-5"&gt; Click an Image &lt;/h3&gt;  
&lt;img src="{{ url\_for('video\_feed') }}"  
width="50%"  
border="5px solid #100"&gt;

{% for message in get\_flashed\_messages() %}  
&lt;h1&gt;&lt;p style="color:red"&gt;{{ message }}&lt;/p&gt;&lt;/h1&gt;  
{% endfor %}

&lt;/div&gt;  
&lt;/div&gt;

&lt;/div&gt;

&lt;/div&gt;  
&lt;/body&gt;  
&lt;/html&gt;

**2\. Login Page:**

&lt;head&gt;  
&lt;meta charset="UTF-8"&gt;  
&lt;title&gt;Login Page&lt;/title&gt;  
&lt;/head&gt;

&lt;body&gt;  
&lt;div class="container"&gt;  
&lt;h1&gt;Login&lt;/h1&gt;  
&lt;br&gt;

&lt;form action="" method="post"&gt;

&lt;input type="text" placeholder="Email" name="email" value="{{  
request.form.email }}"&gt;

&lt;br&gt;  
&lt;br&gt;  
&lt;input type="password" placeholder="Password" name="password" value="{{  
request.form.password }}"&gt;

&lt;br&gt;  
&lt;br&gt;  
&lt;input type="submit" value="Forget Password" name="forget\_action"/&gt;

&lt;input type="submit" value="Login" name="login\_action"/&gt;

&lt;br&gt;  
&lt;br&gt;  
&lt;p style="color:red"&gt; {{error}} &lt;/p&gt;

&lt;/form&gt;  
&lt;/div&gt;  
&lt;/body&gt;  
&lt;/html&gt;

**3\. Forget Password Page:**

Forget Password Page

&lt;div class="row"&gt;  
&lt;div class="col-lg-8 offset-lg-2"&gt;

&lt;form action="" method="post"&gt;

&lt;h1 &lt;p style="color:red"&gt; Face Verification &lt;/h1&gt;  
&lt;br&gt;  
&lt;input type="submit" value="Verify Image" name="verify\_action"/&gt;  
&lt;br&gt;  
&lt;img src="{{ url\_for('ForgetPassVideo\_feed') }}"  
width="55%"  
align="middle"  
border="5px solid #100"&gt;  
&lt;br&gt;  
{% for message in get\_flashed\_messages() %}  
&lt;h1&gt;&lt;p style="color:red"&gt;{{ message }}&lt;/p&gt;&lt;/h1&gt;  
{% endfor %}

&lt;/form&gt;

&lt;/div&gt;  
&lt;/div&gt;

&lt;/body&gt;  
&lt;/html&gt;

**4\. Home Page:**

Home Page

&lt;h1&gt; Home Page &lt;/h1&gt;  
&lt;br&gt;  
&lt;form action="" method="post"&gt;

&lt;h2&gt;&lt;p &lt;b style="color:green"&gt; Face Recognised :) &lt;/b&gt; &lt;/p&gt;&lt;/h2&gt;

&lt;/form&gt;

&lt;/div&gt;

&lt;/body&gt;  
&lt;/html&gt;

#### **Complete source code:**

[https://github.com/sk3786/ComputerVision-FaceVerification-LoginSystem](https://github.com/sk3786/ComputerVision-FaceVerification-LoginSystem)
