Spaces:
Running
Running
File size: 7,959 Bytes
c336617 dede013 8775ba7 dede013 5eaad66 dede013 9ca0a51 dede013 9ca0a51 dede013 b15f8f4 dede013 b15f8f4 81a4855 fd4d6b9 b15f8f4 dede013 789804a dede013 0cf156b fd4d6b9 dede013 4c8602a c5f95fa dede013 9178928 151b2c7 c5f95fa 9178928 ecd4291 9178928 ecd4291 4edd752 9178928 c5f95fa 9178928 dede013 0b20aa4 dede013 f02d1fe dede013 89b1493 bd7dcdf 4567594 bd7dcdf 817b9ca bd7dcdf 15eac66 4edd752 bd7dcdf 4edd752 bd7dcdf ecd4291 bd7dcdf fd4d6b9 0cf156b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
import os
import cv2
import torch
import numpy as np
import streamlit as st
import requests
import sqlite3
from PIL import Image
from glob import glob
from insightface.app import FaceAnalysis
import torch.nn.functional as F
# Set the device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Global Variables
IMAGE_SHAPE = 640
data_path = 'employees'
webcam_path = 'captured_image.jpg'
STUDENT_DB = "students.db"
# Set Streamlit title
st.title("AIML-Student Attendance System")
# Load employee image paths
image_paths = glob(os.path.join(data_path, '*.jpg'))
# Initialize Face Analysis
app = FaceAnalysis(name="buffalo_l") # ArcFace model
app.prepare(ctx_id=0 if torch.cuda.is_available() else -1, det_size=(IMAGE_SHAPE, IMAGE_SHAPE))
# # Check if roll exists
# def roll_exists(rno):
# with sqlite3.connect(STUDENT_DB) as conn:
# cur = conn.execute("SELECT * FROM students WHERE rno=?", (rno,))
# return cur.fetchone()
# # Register new student
# def register_student(rno, sname, sclass, image):
# image_path = os.path.join(data_path, f"{rno}.jpg")
# image.save(image_path)
# with sqlite3.connect(STUDENT_DB) as conn:
# conn.execute("INSERT INTO students (rno, sname, sclass, image_path) VALUES (?, ?, ?, ?)",
# (rno, sname, sclass, image_path))
# # Load all registered images
# def load_registered_images():
# with sqlite3.connect(STUDENT_DB) as conn:
# return [row[3] for row in conn.execute("SELECT * FROM students")]
# Define function to match face embeddings
def prod_function(app, prod_path, webcam_img_pil):
np_webcam = np.array(webcam_img_pil)
cv2_webcam = cv2.cvtColor(np_webcam, cv2.COLOR_RGB2BGR)
webcam_faces = app.get(cv2_webcam)
if not webcam_faces:
return [], cv2_webcam
results = []
for webcam_face in webcam_faces:
webcam_emb = torch.tensor(webcam_face.embedding, dtype=torch.float32)
similarity_scores = []
for path in prod_path:
img = cv2.imread(path)
faces = app.get(img, max_num=1)
if not faces:
similarity_scores.append(torch.tensor(-1.0))
continue
face_emb = torch.tensor(faces[0].embedding, dtype=torch.float32)
score = F.cosine_similarity(face_emb, webcam_emb, dim=0)
similarity_scores.append(score)
similarity_scores = torch.stack(similarity_scores)
best_match_idx = torch.argmax(similarity_scores)
best_score = similarity_scores[best_match_idx].item()
# Get coordinates
x1, y1, x2, y2 = [int(i) for i in webcam_face.bbox]
if best_score >= 0.6:
matched_name = os.path.basename(prod_path[best_match_idx]).split('.')[0]
else:
matched_name = "Unknown"
results.append({'bbox': (x1, y1, x2, y2), 'name': matched_name})
return results, cv2_webcam
# Streamlit tabs
about_tab, app_tab, register_tab = st.tabs(["About the app", "Face Recognition", "Register new Student"])
with about_tab:
st.markdown("""
# ποΈβπ¨οΈ AI-Powered Face Recognition Attendance System
Secure and Accurate Attendance using Vision Transformer + ArcFace Embeddings.
- **Automated, contactless attendance logging**
- **Uses InsightFace ArcFace embeddings for recognition**
- **Real-time logging with confidence scoring**
- **Future Scope: Mask-aware recognition, Group detection, and more**
""")
with app_tab:
enable = st.checkbox("Enable camera")
picture = st.camera_input("Take a picture", disabled=not enable)
if picture is not None:
with st.spinner("Analyzing face..."):
image_pil = Image.open(picture)
matches, image_bgr = prod_function(app, image_paths, image_pil)
if not matches:
st.warning("No face detected in the captured image.")
else:
# st.write("Similarity Scores:", prediction_scores)
for match in matches:
x1, y1, x2, y2 = match['bbox']
matched_name = match['name']
color = (0, 255, 0) if matched_name != "Unknown" else (0, 0, 255)
cv2.rectangle(image_bgr, (x1, y1), (x2, y2), color, 2)
cv2.putText(image_bgr, matched_name, (x1, y2 + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)
if matched_name != "Unknown":
# recognized = False
# for score, idx in matches:
# if matched_score >= 0.6:
# matched_name = os.path.basename(image_paths[match_idx]).split('.')[0]
# st.success(f"β
Welcome: {matched_name}")
# recognizes=True
# Send attendance via POST
url = "https://nielit-attendance.glitch.me/adds"
data = {'rno': 15, 'sname': matched_name, 'sclass': 7}
try:
response = requests.post(url, data=data)
if response.status_code == 200:
st.success(f"Attendance marked successfully for {matched_name}.")
else:
st.warning(f"Failed to update attendance for {matched_name}.")
except Exception as e:
st.error(f"Request failed: {e}")
else:
st.warning("β Face match not found or too low confidence.")
# Convert back to RGB for display
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
st.image(image_rgb, caption="Detected Faces", use_container_width=True)
with register_tab:
upload_mode = st.radio("Choose Method", ["π€ Upload Image", "π· Take Photo"])
if upload_mode == "π€ Upload Image":
upload = st.file_uploader("Upload Student Image with plain background(.jpg)", type="jpg")
if upload:
image_pil = Image.open(upload)
else:
camera_capture = st.camera_input("Capture Image")
if camera_capture:
image_pil = Image.open(camera_capture)
if 'image_pil' in locals():
st.image(image_pil, caption="Student Image", use_container_width=True)
rno = st.text_input("Roll Number")
sname = st.text_input("Student Name")
sclass = st.text_input("Class")
if st.button("Register"):
if not (rno and sname and sclass):
st.warning("Fill all details.")
# # Save locally in employees folder
# local_path = os.path.join("employees", f"{sname}.jpg")
# image_pil.save(local_path)
# # Convert image to base64 for sending to Glitch
# buffered = BytesIO()
# image_pil.save(buffered, format="JPEG")
# img_str = base64.b64encode(buffered.getvalue()).decode()
# # Prepare data for POST request
# glitch_url = "https://your-glitch-app.glitch.me/register" # Replace this
# data = {
# "rno": rno,
# "sname": sname,
# "sclass": sclass,
# "image_base64": img_str,
# }
# response = requests.post(glitch_url, json=data)
# result = response.json()
# if result["status"] == "success":
# st.success(result["message"])
# else:
# st.error(result["message"]) |