|
import streamlit as st |
|
import cv2 |
|
import numpy as np |
|
import os |
|
import sqlite3 |
|
from PIL import Image |
|
from keras.models import load_model |
|
from huggingface_hub import HfApi |
|
import tempfile |
|
|
|
|
|
KNOWN_FACES_DIR = "known_faces" |
|
DATABASE = "students.db" |
|
EMOTION_MODEL_FILE = "CNN_Model_acc_75.h5" |
|
EMOTION_LABELS = ["Angry", "Disgust", "Fear", "Happy", "Sad", "Surprise", "Neutral"] |
|
REPO_NAME = "face_and_emotion_detection" |
|
REPO_ID = "LovnishVerma/" + REPO_NAME |
|
IMG_SHAPE = 48 |
|
hf_token = os.getenv("upload") |
|
|
|
|
|
if not hf_token: |
|
st.error("Hugging Face token not found. Please set the environment variable.") |
|
st.stop() |
|
|
|
|
|
api = HfApi() |
|
|
|
|
|
def create_hugging_face_repo(): |
|
try: |
|
api.create_repo(repo_id=REPO_ID, repo_type="space", space_sdk="streamlit", token=hf_token, exist_ok=True) |
|
st.success(f"Repository '{REPO_NAME}' is ready on Hugging Face!") |
|
except Exception as e: |
|
st.error(f"Error creating Hugging Face repository: {e}") |
|
|
|
|
|
@st.cache_resource |
|
def load_emotion_model(): |
|
try: |
|
model = load_model(EMOTION_MODEL_FILE) |
|
return model |
|
except Exception as e: |
|
st.error(f"Error loading emotion model: {e}") |
|
st.stop() |
|
|
|
emotion_model = load_emotion_model() |
|
|
|
|
|
face_recognizer = cv2.face.LBPHFaceRecognizer_create() |
|
|
|
|
|
def initialize_database(): |
|
""" |
|
Initializes the SQLite database by creating a table to store student data. |
|
""" |
|
with sqlite3.connect(DATABASE) as conn: |
|
conn.execute(""" |
|
CREATE TABLE IF NOT EXISTS students ( |
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
name TEXT NOT NULL, |
|
roll_no TEXT NOT NULL UNIQUE, |
|
image_path TEXT NOT NULL, |
|
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP |
|
) |
|
""") |
|
conn.commit() |
|
|
|
|
|
initialize_database() |
|
|
|
def save_to_database(name, roll_no, image_path): |
|
""" |
|
Saves student data (name, roll number, image path) to the SQLite database. |
|
Ensures roll number is unique. |
|
""" |
|
with sqlite3.connect(DATABASE) as conn: |
|
try: |
|
conn.execute(""" |
|
INSERT INTO students (name, roll_no, image_path) |
|
VALUES (?, ?, ?) |
|
""", (name, roll_no, image_path)) |
|
conn.commit() |
|
st.success("Data saved successfully!") |
|
except sqlite3.IntegrityError: |
|
st.error("Roll number already exists!") |
|
|
|
def save_image_to_hugging_face(image, name, roll_no): |
|
""" |
|
Saves the captured image locally in the 'known_faces' directory and uploads it to Hugging Face. |
|
""" |
|
if not os.path.exists(KNOWN_FACES_DIR): |
|
os.makedirs(KNOWN_FACES_DIR) |
|
|
|
filename = f"{name}_{roll_no}.jpg" |
|
local_path = os.path.join(KNOWN_FACES_DIR, filename) |
|
|
|
|
|
image.save(local_path) |
|
|
|
try: |
|
api.upload_file( |
|
path_or_fileobj=local_path, |
|
path_in_repo=filename, |
|
repo_id=REPO_ID, |
|
repo_type="space", |
|
token=hf_token |
|
) |
|
st.success(f"Image uploaded to Hugging Face: {filename}") |
|
except Exception as e: |
|
st.error(f"Error uploading image to Hugging Face: {e}") |
|
|
|
return local_path |
|
|
|
|
|
def load_known_faces(): |
|
""" |
|
Loads known faces from the 'known_faces' directory and trains the recognizer. |
|
""" |
|
known_faces = [] |
|
known_names = [] |
|
|
|
for image_name in os.listdir(KNOWN_FACES_DIR): |
|
if image_name.endswith(('.jpg', '.jpeg', '.png')): |
|
image_path = os.path.join(KNOWN_FACES_DIR, image_name) |
|
image = cv2.imread(image_path) |
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
faces = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml').detectMultiScale( |
|
gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30) |
|
) |
|
|
|
for (x, y, w, h) in faces: |
|
roi_gray = gray[y:y+h, x:x+w] |
|
known_faces.append(roi_gray) |
|
known_names.append(image_name.split('.')[0]) |
|
|
|
if known_faces: |
|
face_recognizer.train(known_faces, np.array([i for i in range(len(known_faces))])) |
|
else: |
|
st.warning("No known faces found for training.") |
|
|
|
return known_names |
|
|
|
|
|
known_names = load_known_faces() |
|
|
|
|
|
def process_frame(frame): |
|
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) |
|
faces = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml').detectMultiScale( |
|
gray_frame, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30) |
|
) |
|
|
|
result_text = "" |
|
for (x, y, w, h) in faces: |
|
roi_gray = gray_frame[y:y+h, x:x+w] |
|
roi_color = frame[y:y+h, x:x+w] |
|
face_roi = cv2.resize(roi_color, (IMG_SHAPE, IMG_SHAPE)) |
|
face_roi = cv2.cvtColor(face_roi, cv2.COLOR_BGR2RGB) |
|
face_roi = np.expand_dims(face_roi, axis=0) / 255.0 |
|
|
|
predictions = emotion_model.predict(face_roi) |
|
emotion = EMOTION_LABELS[np.argmax(predictions[0])] |
|
|
|
label, confidence = face_recognizer.predict(roi_gray) |
|
name = "Unknown" |
|
if confidence < 100: |
|
name = known_names[label] |
|
|
|
result_text = f"{name} is feeling {emotion}" |
|
|
|
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) |
|
cv2.putText(frame, result_text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) |
|
|
|
return frame, result_text |
|
|
|
|
|
def video_feed(video_source): |
|
frame_placeholder = st.empty() |
|
text_placeholder = st.empty() |
|
|
|
while True: |
|
ret, frame = video_source.read() |
|
if not ret: |
|
break |
|
|
|
frame, result_text = process_frame(frame) |
|
|
|
frame_placeholder.image(frame, channels="BGR", use_column_width=True) |
|
text_placeholder.markdown(f"<h3 style='text-align: center;'>{result_text}</h3>", unsafe_allow_html=True) |
|
|
|
|
|
def main(): |
|
st.title("Student Registration with Face Recognition and Emotion Detection") |
|
|
|
|
|
registration_mode = st.sidebar.radio("Choose an option", ["Register Student", "Face and Emotion Recognition"]) |
|
|
|
if registration_mode == "Register Student": |
|
name = st.text_input("Enter your name") |
|
roll_no = st.text_input("Enter your roll number") |
|
|
|
capture_mode = st.radio("Choose an option to upload your image", ["Use Webcam", "Upload File"]) |
|
|
|
if capture_mode == "Use Webcam": |
|
picture = st.camera_input("Take a picture") |
|
else: |
|
picture = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"]) |
|
|
|
if st.button("Register"): |
|
if not name or not roll_no: |
|
st.error("Please fill in both name and roll number.") |
|
elif not picture: |
|
st.error("Please upload or capture an image.") |
|
else: |
|
try: |
|
image = Image.open(picture) |
|
image_path = save_image_to_hugging_face(image, name, roll_no) |
|
save_to_database(name, roll_no, image_path) |
|
except Exception as e: |
|
st.error(f"An error occurred: {e}") |
|
|
|
elif registration_mode == "Face and Emotion Recognition": |
|
upload_choice = st.radio("Choose input source", ["Upload Image", "Upload Video", "Camera"]) |
|
|
|
if upload_choice == "Camera": |
|
image = st.camera_input("Take a picture") |
|
if image: |
|
frame = np.array(Image.open(image)) |
|
frame, result_text = process_frame(frame) |
|
st.image(frame, caption='Processed Image', use_column_width=True) |
|
st.markdown(f"<h3 style='text-align: center;'>{result_text}</h3>", unsafe_allow_html=True) |
|
elif upload_choice == "Upload Image": |
|
uploaded_image = st.file_uploader("Upload Image", type=["png", "jpg", "jpeg", "gif"]) |
|
if uploaded_image: |
|
image = Image.open(uploaded_image) |
|
frame = np.array(image) |
|
frame, result_text = process_frame(frame) |
|
st.image(frame, caption='Processed Image', use_column_width=True) |
|
st.markdown(f"<h3 style='text-align: center;'>{result_text}</h3>", unsafe_allow_html=True) |
|
elif upload_choice == "Upload Video": |
|
video_file = st.file_uploader("Upload Video", type=["mp4", "mov", "avi"]) |
|
if video_file: |
|
temp_video_file = tempfile.NamedTemporaryFile(delete=False) |
|
temp_video_file.write(video_file.read()) |
|
temp_video_file.close() |
|
video_source = cv2.VideoCapture(temp_video_file.name) |
|
video_feed(video_source) |
|
|
|
if __name__ == "__main__": |
|
main() |
|
|