├── 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 | 
6 |
--------------------------------------------------------------------------------
/templates/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
40 |
41 |
42 |
43 |
44 |
67 |
68 |
70 |
Today's
71 | Attendance assignment
72 |
73 |
77 |
78 |
79 |
80 | | S No |
81 | Name |
82 | ID |
83 | Time |
84 |
85 | {% if l %}
86 |
87 | {% for i in range(l) %}
88 |
89 | | {{ i+1 }} |
90 | {{ names[i] }} |
91 | {{ rolls[i] }} |
92 | {{ times[i] }} |
93 |
94 | {% endfor %}
95 | {% endif %}
96 |
97 |
98 |
99 |
100 |
102 |
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 |
--------------------------------------------------------------------------------