├── ss.png ├── README.md ├── templates └── home.html └── app.py /ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharmaji27/face-recognition-based-attendance-system/HEAD/ss.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # face-recognition-based-attendance-system 2 | 3 | Do visit my blog for better explanations: https://machinelearningprojects.net/face-recognition-based-attendance-system/ 4 | 5 | ![Face Recognition Based Attendance System](ss.png) 6 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | Face Recognition Based Attendance System 53 | 54 | 55 | 56 | 57 |
58 |

Face Recognition Based 59 | Attendance System

60 |
61 | 62 | {% if mess%} 63 |

{{ mess }}

64 | {% endif %} 65 | 66 |
67 | 68 |
70 |

Today's 71 | Attendance assignment

72 | 73 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | {% if l %} 86 | 87 | {% for i in range(l) %} 88 | 89 | 90 | 91 | 92 | 93 | 94 | {% endfor %} 95 | {% endif %} 96 |
S NoNameIDTime
{{ i+1 }}{{ names[i] }}{{ rolls[i] }}{{ times[i] }}
97 | 98 |
99 | 100 |
102 |
103 |

Add 104 | New User control_point_duplicate

105 | 106 |
107 | 109 |
110 | 111 |
112 | 114 |
115 | 118 |
119 |
Total Users in Database: {{totalreg}}
120 |
121 |
122 | 123 |
124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | from flask import Flask, request, render_template 4 | from datetime import date 5 | from datetime import datetime 6 | import numpy as np 7 | from sklearn.neighbors import KNeighborsClassifier 8 | import pandas as pd 9 | import joblib 10 | 11 | # Defining Flask App 12 | app = Flask(__name__) 13 | 14 | nimgs = 10 15 | 16 | # Saving Date today in 2 different formats 17 | datetoday = date.today().strftime("%m_%d_%y") 18 | datetoday2 = date.today().strftime("%d-%B-%Y") 19 | 20 | 21 | # Initializing VideoCapture object to access WebCam 22 | face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 23 | 24 | 25 | # If these directories don't exist, create them 26 | if not os.path.isdir('Attendance'): 27 | os.makedirs('Attendance') 28 | if not os.path.isdir('static'): 29 | os.makedirs('static') 30 | if not os.path.isdir('static/faces'): 31 | os.makedirs('static/faces') 32 | if f'Attendance-{datetoday}.csv' not in os.listdir('Attendance'): 33 | with open(f'Attendance/Attendance-{datetoday}.csv', 'w') as f: 34 | f.write('Name,Roll,Time') 35 | 36 | 37 | # get a number of total registered users 38 | def totalreg(): 39 | return len(os.listdir('static/faces')) 40 | 41 | 42 | # extract the face from an image 43 | def extract_faces(img): 44 | try: 45 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 46 | face_points = face_detector.detectMultiScale(gray, 1.2, 5, minSize=(20, 20)) 47 | return face_points 48 | except: 49 | return [] 50 | 51 | 52 | # Identify face using ML model 53 | def identify_face(facearray): 54 | model = joblib.load('static/face_recognition_model.pkl') 55 | return model.predict(facearray) 56 | 57 | 58 | # A function which trains the model on all the faces available in faces folder 59 | def train_model(): 60 | faces = [] 61 | labels = [] 62 | userlist = os.listdir('static/faces') 63 | for user in userlist: 64 | for imgname in os.listdir(f'static/faces/{user}'): 65 | img = cv2.imread(f'static/faces/{user}/{imgname}') 66 | resized_face = cv2.resize(img, (50, 50)) 67 | faces.append(resized_face.ravel()) 68 | labels.append(user) 69 | faces = np.array(faces) 70 | knn = KNeighborsClassifier(n_neighbors=5) 71 | knn.fit(faces, labels) 72 | joblib.dump(knn, 'static/face_recognition_model.pkl') 73 | 74 | 75 | # Extract info from today's attendance file in attendance folder 76 | def extract_attendance(): 77 | df = pd.read_csv(f'Attendance/Attendance-{datetoday}.csv') 78 | names = df['Name'] 79 | rolls = df['Roll'] 80 | times = df['Time'] 81 | l = len(df) 82 | return names, rolls, times, l 83 | 84 | 85 | # Add Attendance of a specific user 86 | def add_attendance(name): 87 | username = name.split('_')[0] 88 | userid = name.split('_')[1] 89 | current_time = datetime.now().strftime("%H:%M:%S") 90 | 91 | df = pd.read_csv(f'Attendance/Attendance-{datetoday}.csv') 92 | if int(userid) not in list(df['Roll']): 93 | with open(f'Attendance/Attendance-{datetoday}.csv', 'a') as f: 94 | f.write(f'\n{username},{userid},{current_time}') 95 | 96 | 97 | ## A function to get names and rol numbers of all users 98 | def getallusers(): 99 | userlist = os.listdir('static/faces') 100 | names = [] 101 | rolls = [] 102 | l = len(userlist) 103 | 104 | for i in userlist: 105 | name, roll = i.split('_') 106 | names.append(name) 107 | rolls.append(roll) 108 | 109 | return userlist, names, rolls, l 110 | 111 | 112 | ## A function to delete a user folder 113 | def deletefolder(duser): 114 | pics = os.listdir(duser) 115 | for i in pics: 116 | os.remove(duser+'/'+i) 117 | os.rmdir(duser) 118 | 119 | 120 | 121 | 122 | ################## ROUTING FUNCTIONS ######################### 123 | 124 | # Our main page 125 | @app.route('/') 126 | def home(): 127 | names, rolls, times, l = extract_attendance() 128 | return render_template('home.html', names=names, rolls=rolls, times=times, l=l, totalreg=totalreg(), datetoday2=datetoday2) 129 | 130 | 131 | ## List users page 132 | @app.route('/listusers') 133 | def listusers(): 134 | userlist, names, rolls, l = getallusers() 135 | return render_template('listusers.html', userlist=userlist, names=names, rolls=rolls, l=l, totalreg=totalreg(), datetoday2=datetoday2) 136 | 137 | 138 | ## Delete functionality 139 | @app.route('/deleteuser', methods=['GET']) 140 | def deleteuser(): 141 | duser = request.args.get('user') 142 | deletefolder('static/faces/'+duser) 143 | 144 | ## if all the face are deleted, delete the trained file... 145 | if os.listdir('static/faces/')==[]: 146 | os.remove('static/face_recognition_model.pkl') 147 | 148 | try: 149 | train_model() 150 | except: 151 | pass 152 | 153 | userlist, names, rolls, l = getallusers() 154 | return render_template('listusers.html', userlist=userlist, names=names, rolls=rolls, l=l, totalreg=totalreg(), datetoday2=datetoday2) 155 | 156 | 157 | # Our main Face Recognition functionality. 158 | # This function will run when we click on Take Attendance Button. 159 | @app.route('/start', methods=['GET']) 160 | def start(): 161 | names, rolls, times, l = extract_attendance() 162 | 163 | if 'face_recognition_model.pkl' not in os.listdir('static'): 164 | return render_template('home.html', names=names, rolls=rolls, times=times, l=l, totalreg=totalreg(), datetoday2=datetoday2, mess='There is no trained model in the static folder. Please add a new face to continue.') 165 | 166 | ret = True 167 | cap = cv2.VideoCapture(0) 168 | while ret: 169 | ret, frame = cap.read() 170 | if len(extract_faces(frame)) > 0: 171 | (x, y, w, h) = extract_faces(frame)[0] 172 | cv2.rectangle(frame, (x, y), (x+w, y+h), (86, 32, 251), 1) 173 | cv2.rectangle(frame, (x, y), (x+w, y-40), (86, 32, 251), -1) 174 | face = cv2.resize(frame[y:y+h, x:x+w], (50, 50)) 175 | identified_person = identify_face(face.reshape(1, -1))[0] 176 | add_attendance(identified_person) 177 | cv2.putText(frame, f'{identified_person}', (x+5, y-5), 178 | cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) 179 | cv2.imshow('Attendance', frame) 180 | if cv2.waitKey(1) == 27: 181 | break 182 | cap.release() 183 | cv2.destroyAllWindows() 184 | names, rolls, times, l = extract_attendance() 185 | return render_template('home.html', names=names, rolls=rolls, times=times, l=l, totalreg=totalreg(), datetoday2=datetoday2) 186 | 187 | 188 | # A function to add a new user. 189 | # This function will run when we add a new user. 190 | @app.route('/add', methods=['GET', 'POST']) 191 | def add(): 192 | newusername = request.form['newusername'] 193 | newuserid = request.form['newuserid'] 194 | userimagefolder = 'static/faces/'+newusername+'_'+str(newuserid) 195 | if not os.path.isdir(userimagefolder): 196 | os.makedirs(userimagefolder) 197 | i, j = 0, 0 198 | cap = cv2.VideoCapture(0) 199 | while 1: 200 | _, frame = cap.read() 201 | faces = extract_faces(frame) 202 | for (x, y, w, h) in faces: 203 | cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 20), 2) 204 | cv2.putText(frame, f'Images Captured: {i}/{nimgs}', (30, 30), 205 | cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 20), 2, cv2.LINE_AA) 206 | if j % 5 == 0: 207 | name = newusername+'_'+str(i)+'.jpg' 208 | cv2.imwrite(userimagefolder+'/'+name, frame[y:y+h, x:x+w]) 209 | i += 1 210 | j += 1 211 | if j == nimgs*5: 212 | break 213 | cv2.imshow('Adding new User', frame) 214 | if cv2.waitKey(1) == 27: 215 | break 216 | cap.release() 217 | cv2.destroyAllWindows() 218 | print('Training Model') 219 | train_model() 220 | names, rolls, times, l = extract_attendance() 221 | return render_template('home.html', names=names, rolls=rolls, times=times, l=l, totalreg=totalreg(), datetoday2=datetoday2) 222 | 223 | 224 | # Our main function which runs the Flask App 225 | if __name__ == '__main__': 226 | app.run(debug=True) 227 | --------------------------------------------------------------------------------