PrashanthB461 commited on
Commit
c8ae942
Β·
verified Β·
1 Parent(s): 70c6634

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +458 -0
app.py ADDED
@@ -0,0 +1,458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cv2
3
+ import numpy as np
4
+ import pandas as pd
5
+ from datetime import datetime, date
6
+ import os
7
+ import sqlite3
8
+ import face_recognition
9
+ import io
10
+ from PIL import Image
11
+ import json
12
+
13
+ # Initialize database
14
+ def init_database():
15
+ conn = sqlite3.connect('attendance.db')
16
+ cursor = conn.cursor()
17
+
18
+ # Create users table
19
+ cursor.execute('''
20
+ CREATE TABLE IF NOT EXISTS users (
21
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ name TEXT NOT NULL,
23
+ employee_id TEXT UNIQUE NOT NULL,
24
+ face_encoding TEXT NOT NULL,
25
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
26
+ )
27
+ ''')
28
+
29
+ # Create attendance table
30
+ cursor.execute('''
31
+ CREATE TABLE IF NOT EXISTS attendance (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ employee_id TEXT NOT NULL,
34
+ name TEXT NOT NULL,
35
+ date DATE NOT NULL,
36
+ time_in TIME,
37
+ time_out TIME,
38
+ status TEXT DEFAULT 'Present',
39
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
40
+ FOREIGN KEY (employee_id) REFERENCES users (employee_id)
41
+ )
42
+ ''')
43
+
44
+ conn.commit()
45
+ conn.close()
46
+
47
+ # Load known faces from database
48
+ def load_known_faces():
49
+ conn = sqlite3.connect('attendance.db')
50
+ cursor = conn.cursor()
51
+ cursor.execute("SELECT name, employee_id, face_encoding FROM users")
52
+ users = cursor.fetchall()
53
+ conn.close()
54
+
55
+ known_faces = []
56
+ known_names = []
57
+ known_ids = []
58
+
59
+ for user in users:
60
+ name, emp_id, encoding_str = user
61
+ encoding = json.loads(encoding_str)
62
+ known_faces.append(np.array(encoding))
63
+ known_names.append(name)
64
+ known_ids.append(emp_id)
65
+
66
+ return known_faces, known_names, known_ids
67
+
68
+ # Register new face
69
+ def register_face(image, name, employee_id):
70
+ if image is None:
71
+ return "Please upload an image", None
72
+
73
+ if not name or not employee_id:
74
+ return "Please provide both name and employee ID", None
75
+
76
+ try:
77
+ # Convert PIL image to RGB array
78
+ img_array = np.array(image)
79
+
80
+ # Find face encodings
81
+ face_locations = face_recognition.face_locations(img_array)
82
+
83
+ if len(face_locations) == 0:
84
+ return "No face detected in the image. Please upload a clear image with a visible face.", None
85
+
86
+ if len(face_locations) > 1:
87
+ return "Multiple faces detected. Please upload an image with only one face.", None
88
+
89
+ face_encodings = face_recognition.face_encodings(img_array, face_locations)
90
+ face_encoding = face_encodings[0]
91
+
92
+ # Check if employee ID already exists
93
+ conn = sqlite3.connect('attendance.db')
94
+ cursor = conn.cursor()
95
+ cursor.execute("SELECT * FROM users WHERE employee_id = ?", (employee_id,))
96
+ existing_user = cursor.fetchone()
97
+
98
+ if existing_user:
99
+ conn.close()
100
+ return f"Employee ID {employee_id} already exists!", None
101
+
102
+ # Save to database
103
+ encoding_str = json.dumps(face_encoding.tolist())
104
+ cursor.execute(
105
+ "INSERT INTO users (name, employee_id, face_encoding) VALUES (?, ?, ?)",
106
+ (name, employee_id, encoding_str)
107
+ )
108
+ conn.commit()
109
+ conn.close()
110
+
111
+ return f"Successfully registered {name} with Employee ID: {employee_id}", get_registered_users()
112
+
113
+ except Exception as e:
114
+ return f"Error during registration: {str(e)}", None
115
+
116
+ # Mark attendance
117
+ def mark_attendance(image):
118
+ if image is None:
119
+ return "Please upload an image", None, None
120
+
121
+ try:
122
+ # Convert PIL image to RGB array
123
+ img_array = np.array(image)
124
+
125
+ # Load known faces
126
+ known_faces, known_names, known_ids = load_known_faces()
127
+
128
+ if len(known_faces) == 0:
129
+ return "No registered users found. Please register users first.", None, None
130
+
131
+ # Find faces in the uploaded image
132
+ face_locations = face_recognition.face_locations(img_array)
133
+ face_encodings = face_recognition.face_encodings(img_array, face_locations)
134
+
135
+ if len(face_encodings) == 0:
136
+ return "No face detected in the image.", None, None
137
+
138
+ results = []
139
+ annotated_image = img_array.copy()
140
+
141
+ for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
142
+ # Compare with known faces
143
+ matches = face_recognition.compare_faces(known_faces, face_encoding, tolerance=0.6)
144
+ face_distances = face_recognition.face_distance(known_faces, face_encoding)
145
+
146
+ if len(face_distances) > 0:
147
+ best_match_index = np.argmin(face_distances)
148
+
149
+ if matches[best_match_index]:
150
+ name = known_names[best_match_index]
151
+ emp_id = known_ids[best_match_index]
152
+ confidence = 1 - face_distances[best_match_index]
153
+
154
+ # Mark attendance in database
155
+ conn = sqlite3.connect('attendance.db')
156
+ cursor = conn.cursor()
157
+
158
+ today = date.today()
159
+ current_time = datetime.now().strftime("%H:%M:%S")
160
+
161
+ # Check if already marked for today
162
+ cursor.execute(
163
+ "SELECT * FROM attendance WHERE employee_id = ? AND date = ?",
164
+ (emp_id, today)
165
+ )
166
+ existing_record = cursor.fetchone()
167
+
168
+ if existing_record:
169
+ # Update time_out if time_in exists
170
+ if existing_record[4]: # time_in exists
171
+ cursor.execute(
172
+ "UPDATE attendance SET time_out = ? WHERE employee_id = ? AND date = ?",
173
+ (current_time, emp_id, today)
174
+ )
175
+ status = "Time Out Updated"
176
+ else:
177
+ status = "Already marked for today"
178
+ else:
179
+ # Create new attendance record
180
+ cursor.execute(
181
+ "INSERT INTO attendance (employee_id, name, date, time_in) VALUES (?, ?, ?, ?)",
182
+ (emp_id, name, today, current_time)
183
+ )
184
+ status = "Attendance Marked"
185
+
186
+ conn.commit()
187
+ conn.close()
188
+
189
+ results.append(f"{name} ({emp_id}) - {status} - Confidence: {confidence:.2f}")
190
+
191
+ # Draw rectangle and label on image
192
+ cv2.rectangle(annotated_image, (left, top), (right, bottom), (0, 255, 0), 2)
193
+ cv2.putText(annotated_image, f"{name} ({confidence:.2f})",
194
+ (left, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
195
+ else:
196
+ results.append("Unknown person detected")
197
+ cv2.rectangle(annotated_image, (left, top), (right, bottom), (0, 0, 255), 2)
198
+ cv2.putText(annotated_image, "Unknown",
199
+ (left, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
200
+ else:
201
+ results.append("Unknown person detected")
202
+
203
+ result_text = "\n".join(results)
204
+ return result_text, Image.fromarray(annotated_image), get_attendance_records()
205
+
206
+ except Exception as e:
207
+ return f"Error during attendance marking: {str(e)}", None, None
208
+
209
+ # Get registered users
210
+ def get_registered_users():
211
+ try:
212
+ conn = sqlite3.connect('attendance.db')
213
+ df = pd.read_sql_query("SELECT name, employee_id, created_at FROM users ORDER BY created_at DESC", conn)
214
+ conn.close()
215
+ return df
216
+ except:
217
+ return pd.DataFrame(columns=['name', 'employee_id', 'created_at'])
218
+
219
+ # Get attendance records
220
+ def get_attendance_records():
221
+ try:
222
+ conn = sqlite3.connect('attendance.db')
223
+ df = pd.read_sql_query("""
224
+ SELECT name, employee_id, date, time_in, time_out, status
225
+ FROM attendance
226
+ ORDER BY date DESC, time_in DESC
227
+ """, conn)
228
+ conn.close()
229
+ return df
230
+ except:
231
+ return pd.DataFrame(columns=['name', 'employee_id', 'date', 'time_in', 'time_out', 'status'])
232
+
233
+ # Get today's attendance
234
+ def get_todays_attendance():
235
+ try:
236
+ conn = sqlite3.connect('attendance.db')
237
+ today = date.today()
238
+ df = pd.read_sql_query("""
239
+ SELECT name, employee_id, time_in, time_out, status
240
+ FROM attendance
241
+ WHERE date = ?
242
+ ORDER BY time_in DESC
243
+ """, conn, params=(today,))
244
+ conn.close()
245
+ return df
246
+ except:
247
+ return pd.DataFrame(columns=['name', 'employee_id', 'time_in', 'time_out', 'status'])
248
+
249
+ # Delete user
250
+ def delete_user(employee_id):
251
+ if not employee_id:
252
+ return "Please enter an employee ID", get_registered_users()
253
+
254
+ try:
255
+ conn = sqlite3.connect('attendance.db')
256
+ cursor = conn.cursor()
257
+
258
+ # Check if user exists
259
+ cursor.execute("SELECT name FROM users WHERE employee_id = ?", (employee_id,))
260
+ user = cursor.fetchone()
261
+
262
+ if not user:
263
+ conn.close()
264
+ return f"Employee ID {employee_id} not found", get_registered_users()
265
+
266
+ # Delete user and their attendance records
267
+ cursor.execute("DELETE FROM attendance WHERE employee_id = ?", (employee_id,))
268
+ cursor.execute("DELETE FROM users WHERE employee_id = ?", (employee_id,))
269
+
270
+ conn.commit()
271
+ conn.close()
272
+
273
+ return f"Successfully deleted user {user[0]} ({employee_id})", get_registered_users()
274
+
275
+ except Exception as e:
276
+ return f"Error deleting user: {str(e)}", get_registered_users()
277
+
278
+ # Initialize database on startup
279
+ init_database()
280
+
281
+ # Custom CSS
282
+ css = """
283
+ .gradio-container {
284
+ max-width: 1200px !important;
285
+ }
286
+ .tab-nav {
287
+ background: linear-gradient(90deg, #667eea 0%, #764ba2 100%) !important;
288
+ }
289
+ .tab-nav button {
290
+ color: white !important;
291
+ font-weight: bold !important;
292
+ }
293
+ .tab-nav button.selected {
294
+ background: rgba(255,255,255,0.2) !important;
295
+ }
296
+ """
297
+
298
+ # Create Gradio interface
299
+ with gr.Blocks(css=css, title="Attendance Analyzer - Face Detection", theme=gr.themes.Soft()) as app:
300
+ gr.Markdown(
301
+ """
302
+ # 🎯 Attendance Analyzer Using Face Detection
303
+
304
+ **Advanced AI-powered attendance management system with real-time face recognition**
305
+
306
+ ---
307
+ """,
308
+ elem_classes="header"
309
+ )
310
+
311
+ with gr.Tabs():
312
+ # Tab 1: Mark Attendance
313
+ with gr.Tab("πŸ“Έ Mark Attendance"):
314
+ gr.Markdown("### Mark attendance by uploading an image or using webcam")
315
+
316
+ with gr.Row():
317
+ with gr.Column(scale=1):
318
+ attendance_image = gr.Image(
319
+ type="pil",
320
+ label="Upload Image for Attendance",
321
+ height=400
322
+ )
323
+ mark_btn = gr.Button("Mark Attendance", variant="primary", size="lg")
324
+
325
+ with gr.Column(scale=1):
326
+ attendance_result = gr.Textbox(
327
+ label="Attendance Result",
328
+ lines=5,
329
+ placeholder="Results will appear here..."
330
+ )
331
+ annotated_output = gr.Image(
332
+ label="Detected Faces",
333
+ height=400
334
+ )
335
+
336
+ with gr.Row():
337
+ attendance_df = gr.Dataframe(
338
+ label="πŸ“Š Today's Attendance Records",
339
+ headers=["Name", "Employee ID", "Time In", "Time Out", "Status"],
340
+ datatype=["str", "str", "str", "str", "str"],
341
+ value=get_todays_attendance()
342
+ )
343
+
344
+ # Tab 2: Register New User
345
+ with gr.Tab("πŸ‘€ Register User"):
346
+ gr.Markdown("### Register a new user for face recognition")
347
+
348
+ with gr.Row():
349
+ with gr.Column(scale=1):
350
+ register_image = gr.Image(
351
+ type="pil",
352
+ label="Upload User Photo",
353
+ height=400
354
+ )
355
+
356
+ with gr.Column(scale=1):
357
+ user_name = gr.Textbox(
358
+ label="Full Name",
359
+ placeholder="Enter full name..."
360
+ )
361
+ emp_id = gr.Textbox(
362
+ label="Employee ID",
363
+ placeholder="Enter unique employee ID..."
364
+ )
365
+ register_btn = gr.Button("Register User", variant="primary", size="lg")
366
+
367
+ register_result = gr.Textbox(
368
+ label="Registration Result",
369
+ lines=3,
370
+ placeholder="Registration status will appear here..."
371
+ )
372
+
373
+ with gr.Row():
374
+ users_df = gr.Dataframe(
375
+ label="πŸ‘₯ Registered Users",
376
+ headers=["Name", "Employee ID", "Registration Date"],
377
+ datatype=["str", "str", "str"],
378
+ value=get_registered_users()
379
+ )
380
+
381
+ # Tab 3: Manage Users
382
+ with gr.Tab("βš™οΈ Manage Users"):
383
+ gr.Markdown("### Manage registered users")
384
+
385
+ with gr.Row():
386
+ with gr.Column(scale=1):
387
+ delete_emp_id = gr.Textbox(
388
+ label="Employee ID to Delete",
389
+ placeholder="Enter employee ID to delete..."
390
+ )
391
+ delete_btn = gr.Button("Delete User", variant="stop", size="lg")
392
+ delete_result = gr.Textbox(
393
+ label="Delete Result",
394
+ lines=2,
395
+ placeholder="Delete status will appear here..."
396
+ )
397
+
398
+ with gr.Column(scale=2):
399
+ manage_users_df = gr.Dataframe(
400
+ label="πŸ‘₯ All Registered Users",
401
+ headers=["Name", "Employee ID", "Registration Date"],
402
+ datatype=["str", "str", "str"],
403
+ value=get_registered_users()
404
+ )
405
+
406
+ # Tab 4: Attendance Reports
407
+ with gr.Tab("πŸ“ˆ Reports"):
408
+ gr.Markdown("### View attendance reports and analytics")
409
+
410
+ with gr.Row():
411
+ refresh_btn = gr.Button("Refresh Reports", variant="secondary")
412
+
413
+ with gr.Row():
414
+ all_attendance_df = gr.Dataframe(
415
+ label="πŸ“‹ All Attendance Records",
416
+ headers=["Name", "Employee ID", "Date", "Time In", "Time Out", "Status"],
417
+ datatype=["str", "str", "str", "str", "str", "str"],
418
+ value=get_attendance_records(),
419
+ height=500
420
+ )
421
+
422
+ # Event handlers
423
+ mark_btn.click(
424
+ fn=mark_attendance,
425
+ inputs=[attendance_image],
426
+ outputs=[attendance_result, annotated_output, attendance_df]
427
+ )
428
+
429
+ register_btn.click(
430
+ fn=register_face,
431
+ inputs=[register_image, user_name, emp_id],
432
+ outputs=[register_result, users_df]
433
+ )
434
+
435
+ delete_btn.click(
436
+ fn=delete_user,
437
+ inputs=[delete_emp_id],
438
+ outputs=[delete_result, manage_users_df]
439
+ )
440
+
441
+ refresh_btn.click(
442
+ fn=lambda: get_attendance_records(),
443
+ outputs=[all_attendance_df]
444
+ )
445
+
446
+ # Auto-refresh today's attendance
447
+ mark_btn.click(
448
+ fn=lambda: get_todays_attendance(),
449
+ outputs=[attendance_df]
450
+ )
451
+
452
+ if __name__ == "__main__":
453
+ app.launch(
454
+ share=True,
455
+ server_name="0.0.0.0",
456
+ server_port=7860,
457
+ show_api=False
458
+ )