Skip to main content

Face Recognition Based Attendance System with Python

In our previous Python project tutorial, we have explained How To Use Pandas Library in Python. In this tutorial, we will explain how to develop a Face Recognition Based Attendance System using Python, Flask and MySQL.

The face recognition attendance management system provide a quick way to take attendance of students, teachers, employees etc. The system recog the faces and mark attendance of the recognized faces into an excel sheet.

We will develop the system using face_recognition package from Python. During user register process, we will store the user image in database and upload image to a directory. Then we will capture image through webcam and recognize to complete attendance.

So let’s proceed with tutorial to develop system.

Prerequisites

  • Python
  • Flask package
  • Flask_mysqldb package
  • Numpy package
  • face_recognition package
  • Knowledge of Python, HTML.

Application Setup

First, we will create our application directory face-recognition-attendance-system-python-flask-mysql using below command.

$ mkdir face-recognition-attendance-system-python-flask-mysql

we moved to the project direcotry

$ cd face-recognition-attendance-system-python-flask-mysql

Install Required Python Moudles

We will install flask, flask_mysqldb, Numpy and face_recognition package from Python.

  • Flask: It is a micro framework from Python to create web application. So we will install this package to create web applications. We will install it using the below command:
  • pip install Flask
    
  • flask_mysqldb: This is Python package that can be used to connect to MySQL database. We will install it using the below command:
  • pip install flask_mysqldb
    
  • Numpy: This is Python package that can be used for working with arrays.:
  • pip install numpy
    
  • face_recognition: This is Python package that can be used for recognize and manipulate faces:
  • pip install face_recognition
    

Create MySQL Database Table

As we will store use information in user table in MySQL database, so we will create table using below query:

CREATE TABLE `user` (
  `id` int(11) UNSIGNED NOT NULL,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `password` varchar(64) NOT NULL,
  `picture` varchar(250) NOT NULL,
  `role` enum('admin','user') DEFAULT 'admin'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Import Python Packages

We will create app.py Python file and import installed packages.

from flask import Flask, flash, render_template, request, redirect, url_for, session, Response
from werkzeug.utils import secure_filename
from flask_mysqldb import MySQL
import MySQLdb.cursors
import cv2
import numpy as np
import face_recognition
from datetime import datetime
import re
import os
import sys

We will define user image path and also create function to validate allowed image files.

UPLOAD_FOLDER = r'C:\python_program\face-recognition-attendance-system-python-flask-mysql\faces'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}


def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

Loading Attendance Page

We will check for route attendance and load attendance.html template file.

@app.route("/attendance", methods =['GET', 'POST'])
def attendance():
    if 'loggedin' in session:
        userId = request.args.get('userid')
        return render_template("attendance.html", userid = userId)
    return redirect(url_for('login'))

In attendance.html template file, we will call take_attendance route to call take_attendance() function to load webcap to complete attendance.

<div class="container-fluid" id="main">
	{% include 'top_menus.html' %}  	
	<div class="row row-offcanvas row-offcanvas-left">   
		{% include 'left_menus.html' %}	
		<div class="col-md-9 col-lg-10 main"> 
			<br>
			<h3>Attendance</h3>
			<br><br>				
			<div class="mx-auto" style="width: 700px;">
			  <img src="{{ url_for('take_attendance', userid=userid) }}">
			</div>
			<br><br>

		</div>
	</div>
</div>

Implement Face Recognition and Update Attendance

We will define take_attendance() function and call generate() function to recognise user face.

@app.route('/take_attendance')
def take_attendance():    
    userId = request.args.get('userid')
    cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)    
    cursor.execute('SELECT * FROM user WHERE id = % s', (userId, ))
    user = cursor.fetchone()   
    if(user['picture']):
        return Response(generate(user['picture']),
                        mimetype='multipart/x-mixed-replace; boundary=frame')

we will implement generate() function. We will get user’s saved image and then compare with webcam captured image using face_recognition module functions. We will write attendance to attendence.csv file.

def generate(userImage):
    IMAGE_FILES = []
    filename = []
    imageDir = r'C:\python_program\face-recognition-attendance-system-python-flask-mysql\faces'        
    
    if userImage:                 
        img_path = os.path.join(imageDir, userImage)    
        print(img_path)
        img_path = face_recognition.load_image_file(img_path) 
        IMAGE_FILES.append(img_path)
        filename.append(userImage.split(".", 1)[0])    
            

    def encoding_img(IMAGE_FILES):
        encodeList = []
        for img in IMAGE_FILES:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)           
            encode = face_recognition.face_encodings(img)[0]
            encodeList.append(encode)
            return encodeList
            

    def addAttendence(name):        
       with open('attendence.csv', 'r+') as f:
            mypeople_list = f.readlines()
            dateList = []
            now = datetime.now()
            datestring = now.strftime('%m/%d/%Y')      
            for line in mypeople_list:
                entry = line.split(',')
                dateList.append(entry[1])
            if datestring not in dateList:    
                timestring = now.strftime('%H:%M:%S')              
                f.writelines(f'\n{name},{datestring}')

    encodeListknown = encoding_img(IMAGE_FILES)    

    cap = cv2.VideoCapture(0)

    while True:
        success, img = cap.read()
        imgc = cv2.resize(img, (0, 0), None, 0.25, 0.25)
        # converting image to RGB from BGR
        imgc = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        fasescurrent = face_recognition.face_locations(imgc)
        encode_fasescurrent = face_recognition.face_encodings(imgc, fasescurrent)

        # faceloc- one by one it grab one face location from fasescurrent
        # than encodeFace grab encoding from encode_fasescurrent
        # we want them all in same loop so we are using zip
        for encodeFace, faceloc in zip(encode_fasescurrent, fasescurrent):
            matches_face = face_recognition.compare_faces(encodeListknown, encodeFace)
            face_distence = face_recognition.face_distance(encodeListknown, encodeFace)
            # print(face_distence)
            # finding minimum distence index that will return best match
            matchindex = np.argmin(face_distence)

            if matches_face[matchindex]:
                name = filename[matchindex].upper()
                putText = 'Captured'                
                y1, x2, y2, x1 = faceloc
                # multiply locations by 4 because we above we reduced our webcam input image by 0.25
                # y1,x2,y2,x1 = y1*4,x2*4,y2*4,x1*4
                cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)
                cv2.rectangle(img, (x1, y2 - 35), (x2, y2), (255, 0, 0), 2, cv2.FILLED)
                cv2.putText(img, putText, (x1 + 6, y2 - 6), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
                addAttendence(name)  # taking name for attendence function above
        
        frame = cv2.imencode('.jpg', img)[1].tobytes()
        yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')        
        key = cv2.waitKey(20)        
        if key == 27:
           cap.release()   
           cv2.destroyAllWindows()             
           break 

You can download the complete source code of project from the Download link below.

Download