Spaces:
Sleeping
Sleeping
| from flask import Flask, render_template, request, jsonify | |
| import os | |
| import cv2 | |
| import numpy as np | |
| import pandas as pd | |
| from datetime import datetime | |
| import base64 | |
| app = Flask(__name__) | |
| # Setup | |
| face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml") | |
| dataset_path = "./face_dataset/" | |
| attendance_path = "./attendance_data/" | |
| os.makedirs(dataset_path, exist_ok=True) | |
| os.makedirs(attendance_path, exist_ok=True) | |
| # KNN distance utility | |
| def distance(v1, v2): | |
| return np.sqrt(((v1 - v2) ** 2).sum()) | |
| def knn(train, test, k=5): | |
| dist = [] | |
| for i in range(train.shape[0]): | |
| ix = train[i, :-1] | |
| iy = train[i, -1] | |
| d = distance(test, ix) | |
| dist.append([d, iy]) | |
| dk = sorted(dist, key=lambda x: x[0])[:k] | |
| labels = np.array(dk)[:, -1] | |
| return np.unique(labels, return_counts=True)[0][0] | |
| # Attendance management per class | |
| class AttendanceSystem: | |
| def __init__(self, class_name): | |
| self.class_name = class_name | |
| self.file = os.path.join(attendance_path, f"{class_name}.xlsx") | |
| self.columns = ["Enrollment", "Name", "Date", "CheckIn", "CheckOut"] | |
| if not os.path.exists(self.file): | |
| df = pd.DataFrame(columns=self.columns) | |
| df.to_excel(self.file, index=False) | |
| def checkin(self, enrollment, name): | |
| today = datetime.now().strftime("%Y-%m-%d") | |
| now = datetime.now().strftime("%H:%M:%S") | |
| df = pd.read_excel(self.file) | |
| existing = df[(df["Enrollment"] == enrollment) & (df["Date"] == today)] | |
| if existing.empty: | |
| new_entry = pd.DataFrame([[enrollment, name, today, now, ""]], columns=self.columns) | |
| df = pd.concat([df, new_entry], ignore_index=True) | |
| df.to_excel(self.file, index=False) | |
| return True, "Check-in successful" | |
| return False, "Already checked in" | |
| def checkout(self, enrollment): | |
| today = datetime.now().strftime("%Y-%m-%d") | |
| now = datetime.now().strftime("%H:%M:%S") | |
| df = pd.read_excel(self.file) | |
| idx = df[(df["Enrollment"] == enrollment) & (df["Date"] == today)].index | |
| if idx.empty: | |
| return False, "Please check-in first" | |
| row = df.loc[idx[0]] | |
| if pd.isna(row["CheckOut"]) or row["CheckOut"] == "": | |
| df.at[idx[0], "CheckOut"] = now | |
| df.to_excel(self.file, index=False) | |
| return True, "Check-out successful" | |
| return False, "Already checked out" | |
| # Routes | |
| def index(): | |
| return render_template('index.html') | |
| def register(): | |
| return render_template('register.html') | |
| def mark(): | |
| return render_template('mark.html') | |
| # API to save face during registration | |
| def register_face(): | |
| data = request.json | |
| class_name = data['class_name'] | |
| name = data['name'] | |
| enrollment = data['enrollment'] | |
| images = data['images'] # List of base64 images | |
| class_folder = os.path.join(dataset_path, class_name) | |
| os.makedirs(class_folder, exist_ok=True) | |
| face_data = [] | |
| for img_data in images: | |
| img_bytes = base64.b64decode(img_data.split(",")[1]) | |
| np_arr = np.frombuffer(img_bytes, np.uint8) | |
| img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| gray = cv2.equalizeHist(gray) | |
| faces = face_cascade.detectMultiScale(gray, 1.3, 5) | |
| for (x, y, w, h) in faces[:1]: | |
| face = img[y:y+h, x:x+w] | |
| face = cv2.resize(face, (100, 100)) | |
| face_data.append(face.flatten()) | |
| flipped = cv2.flip(face, 1) | |
| face_data.append(flipped.flatten()) | |
| if face_data: | |
| face_data = np.array(face_data) | |
| filename = f"{enrollment}_{name}.npy" | |
| np.save(os.path.join(class_folder, filename), face_data) | |
| return jsonify({"status": "success", "message": f"{len(face_data)} faces saved"}) | |
| return jsonify({"status": "fail", "message": "No faces detected"}) | |
| # API to identify face without marking | |
| def identify_face(): | |
| data = request.json | |
| class_name = data['class_name'] | |
| img_data = data['image'] | |
| img_bytes = base64.b64decode(img_data.split(",")[1]) | |
| np_arr = np.frombuffer(img_bytes, np.uint8) | |
| img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| faces = face_cascade.detectMultiScale(gray, 1.3, 5) | |
| class_folder = os.path.join(dataset_path, class_name) | |
| if not os.path.exists(class_folder): | |
| return jsonify({"status": "fail", "message": "No data for this class"}) | |
| # Load training data for this class | |
| face_data = [] | |
| labels = [] | |
| names = {} | |
| class_id = 0 | |
| for file in os.listdir(class_folder): | |
| if file.endswith('.npy'): | |
| data_arr = np.load(os.path.join(class_folder, file)) | |
| face_data.append(data_arr) | |
| parts = file[:-4].split('_', 1) | |
| labels.extend([class_id] * data_arr.shape[0]) | |
| names[class_id] = {'enrollment': parts[0], 'name': parts[1]} | |
| class_id += 1 | |
| if not face_data: | |
| return jsonify({"status": "fail", "message": "No trained data found"}) | |
| X_train = np.concatenate(face_data, axis=0) | |
| y_train = np.array(labels).reshape(-1, 1) | |
| trainset = np.hstack((X_train, y_train)) | |
| for (x, y, w, h) in faces[:1]: | |
| face = img[y:y+h, x:x+w] | |
| face = cv2.resize(face, (100, 100)).flatten() | |
| pred_id = knn(trainset, face) | |
| info = names.get(pred_id) | |
| if info: | |
| return jsonify({ | |
| "status": "success", | |
| "name": info['name'], | |
| "enrollment": info['enrollment'] | |
| }) | |
| return jsonify({"status": "fail", "message": "Face not recognized"}) | |
| # API to check-in | |
| def api_checkin(): | |
| data = request.json | |
| class_name = data['class_name'] | |
| enrollment = data['enrollment'] | |
| name = data['name'] | |
| attendance = AttendanceSystem(class_name) | |
| ok, msg = attendance.checkin(enrollment, name) | |
| status = "success" if ok else "fail" | |
| return jsonify({"status": status, "message": msg}) | |
| # API to check-out | |
| def api_checkout(): | |
| data = request.json | |
| class_name = data['class_name'] | |
| enrollment = data['enrollment'] | |
| attendance = AttendanceSystem(class_name) | |
| ok, msg = attendance.checkout(enrollment) | |
| status = "success" if ok else "fail" | |
| return jsonify({"status": status, "message": msg}) | |
| if __name__ == '__main__': | |
| app.run(host='0.0.0.0', port=7860, debug=True) |