|
import streamlit as st |
|
import cv2 |
|
import numpy as np |
|
import time |
|
import os |
|
from keras.models import load_model |
|
from PIL import Image |
|
import pymongo |
|
from datetime import datetime |
|
import tempfile |
|
from facenet_pytorch import MTCNN |
|
|
|
|
|
MONGO_URI = "mongodb+srv://test:[email protected]/?retryWrites=true&w=majority" |
|
|
|
|
|
client = pymongo.MongoClient(MONGO_URI) |
|
db = client.get_database("emotion_detection") |
|
collection = db.get_collection("face_data") |
|
|
|
|
|
st.markdown("<h1 style='text-align: center;'>Emotion Detection with Face Recognition</h1>", unsafe_allow_html=True) |
|
|
|
|
|
st.markdown("<h3 style='text-align: center;'>angry, fear, happy, neutral, sad, surprise</h3>", unsafe_allow_html=True) |
|
|
|
|
|
start = time.time() |
|
|
|
|
|
@st.cache_resource |
|
def load_emotion_model(): |
|
model = load_model('CNN_Model_acc_75.h5') |
|
return model |
|
|
|
model = load_emotion_model() |
|
print("Time taken to load model: ", time.time() - start) |
|
|
|
|
|
emotion_labels = ['angry', 'fear', 'happy', 'neutral', 'sad', 'surprise'] |
|
|
|
|
|
mtcnn = MTCNN() |
|
|
|
|
|
known_faces = [] |
|
known_names = [] |
|
face_recognizer = cv2.face.LBPHFaceRecognizer_create() |
|
|
|
def load_known_faces(): |
|
folder_path = "known_faces" |
|
for image_name in os.listdir(folder_path): |
|
if image_name.endswith(('.jpg', '.jpeg', '.png')): |
|
image_path = os.path.join(folder_path, image_name) |
|
image = cv2.imread(image_path) |
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
|
|
faces, _ = mtcnn.detect(image) |
|
|
|
if faces is not None: |
|
for face in faces: |
|
x, y, w, h = face[0], face[1], face[2], face[3] |
|
roi_gray = gray[y:y+h, x:x+w] |
|
known_faces.append(roi_gray) |
|
known_names.append(image_name.split('.')[0]) |
|
|
|
|
|
face_recognizer.train(known_faces, np.array([i for i in range(len(known_faces))])) |
|
|
|
load_known_faces() |
|
|
|
|
|
def process_frame(frame): |
|
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) |
|
faces, _ = mtcnn.detect(frame) |
|
|
|
result_text = "" |
|
|
|
if faces is not None and len(faces) > 0: |
|
for face in faces: |
|
x, y, w, h = face[0], face[1], face[2], face[3] |
|
roi_color = frame[y:y+h, x:x+w] |
|
roi_gray = gray[y:y+h, x:x+w] |
|
|
|
|
|
roi_gray = cv2.equalizeHist(roi_gray) |
|
|
|
face_roi = cv2.resize(roi_color, (48, 48)) |
|
face_roi = cv2.cvtColor(face_roi, cv2.COLOR_BGR2RGB) |
|
face_roi = np.expand_dims(face_roi, axis=0) / 255.0 |
|
|
|
|
|
predictions = model.predict(face_roi) |
|
emotion = emotion_labels[np.argmax(predictions[0])] |
|
|
|
|
|
name = "Unknown" |
|
label, confidence = face_recognizer.predict(roi_gray) |
|
if confidence < 100: |
|
name = known_names[label] |
|
|
|
|
|
result_text = f"{name} is feeling {emotion}" |
|
|
|
|
|
if name != "Unknown": |
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
document = { |
|
"name": name, |
|
"emotion": emotion, |
|
"timestamp": timestamp |
|
} |
|
|
|
collection.insert_one(document) |
|
print(f"Data inserted into MongoDB: {document}") |
|
|
|
|
|
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, 0.9, (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) |
|
|
|
|
|
upload_choice = st.sidebar.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": |
|
uploaded_video = st.file_uploader("Upload Video", type=["mp4", "mov", "avi", "mkv", "webm"]) |
|
|
|
if uploaded_video: |
|
with tempfile.NamedTemporaryFile(delete=False) as tfile: |
|
tfile.write(uploaded_video.read()) |
|
video_source = cv2.VideoCapture(tfile.name) |
|
video_feed(video_source) |
|
|
|
|
|
st.markdown("### MongoDB Records") |
|
records = collection.find().sort("timestamp", -1) |
|
|
|
for record in records: |
|
col1, col2, col3 = st.columns([3, 3, 1]) |
|
with col1: |
|
st.write(f"**Name**: {record['name']}") |
|
with col2: |
|
st.write(f"**Emotion**: {record['emotion']}") |
|
with col3: |
|
st.write(f"**Timestamp**: {record['timestamp']}") |
|
|
|
|
|
delete_button = st.button(f"Delete {record['_id']}", key=record['_id']) |
|
if delete_button: |
|
collection.delete_one({"_id": record["_id"]}) |
|
st.success(f"Record with ID {record['_id']} has been deleted.") |
|
|