Skip to content

Commit 8e12020

Browse files
authored
Create Face-Emotion-Detection-GUI.py
1 parent 8ec5c6c commit 8e12020

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import tkinter as tk
2+
from tkinter import filedialog, messagebox
3+
from PIL import Image, ImageTk
4+
import cv2
5+
import numpy as np
6+
import ttkbootstrap as tb
7+
from ttkbootstrap.constants import *
8+
from tensorflow.keras.models import load_model
9+
from collections import deque
10+
import matplotlib.pyplot as plt
11+
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
12+
import tensorflow as tf
13+
import datetime
14+
15+
# ---------------- GPU CHECK ----------------
16+
gpus = tf.config.list_physical_devices('GPU')
17+
if gpus:
18+
tf.config.experimental.set_memory_growth(gpus[0], True)
19+
20+
# ---------------- EMOTION MODEL ----------------
21+
emotion_labels = ["Angry", "Disgust", "Fear", "Happy", "Sad", "Surprise", "Neutral"]
22+
model = load_model("fer2013_mini_XCEPTION.102-0.66.hdf5", compile=False)
23+
24+
# ---------------- FACE DETECTOR ----------------
25+
face_cascade = cv2.CascadeClassifier(
26+
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
27+
)
28+
29+
class EmotionApp:
30+
def __init__(self, root):
31+
self.root = root
32+
self.root.title("Advanced Face Emotion Detection")
33+
self.root.geometry("1100x850")
34+
self.root.resizable(False, False)
35+
36+
tb.Style("superhero")
37+
38+
# ---------------- Controls ----------------
39+
control = tb.Frame(root)
40+
control.pack(pady=10)
41+
42+
tb.Button(control, text="Start Webcam", bootstyle=SUCCESS, command=self.start).grid(row=0, column=0, padx=5)
43+
tb.Button(control, text="Stop Webcam", bootstyle=DANGER, command=self.stop).grid(row=0, column=1, padx=5)
44+
tb.Button(control, text="Save Screenshot", bootstyle=WARNING, command=self.save_snapshot).grid(row=0, column=2, padx=5)
45+
46+
# ---------------- Labels ----------------
47+
self.emotion_label = tb.Label(root, text="Emotion: None", font=("Arial", 16))
48+
self.emotion_label.pack()
49+
50+
# ---------------- Confidence Bar ----------------
51+
self.conf_bar = tb.Progressbar(root, length=400, bootstyle=SUCCESS)
52+
self.conf_bar.pack(pady=5)
53+
54+
# ---------------- Video ----------------
55+
self.video_label = tb.Label(root)
56+
self.video_label.pack(pady=10)
57+
58+
# ---------------- Emotion History Graph ----------------
59+
self.fig, self.ax = plt.subplots(figsize=(6, 3))
60+
self.ax.set_ylim(0, 1)
61+
self.ax.set_title("Emotion Confidence History")
62+
self.line, = self.ax.plot([], [])
63+
64+
self.canvas = FigureCanvasTkAgg(self.fig, master=root)
65+
self.canvas.get_tk_widget().pack()
66+
67+
self.history = deque(maxlen=50)
68+
69+
# ---------------- Variables ----------------
70+
self.cap = None
71+
self.running = False
72+
self.last_frame = None
73+
74+
# ---------------- Start ----------------
75+
def start(self):
76+
if self.running:
77+
return
78+
self.cap = cv2.VideoCapture(0)
79+
if not self.cap.isOpened():
80+
messagebox.showerror("Error", "Webcam not accessible")
81+
return
82+
self.running = True
83+
self.update()
84+
85+
# ---------------- Stop ----------------
86+
def stop(self):
87+
self.running = False
88+
if self.cap:
89+
self.cap.release()
90+
self.video_label.config(image="")
91+
self.emotion_label.config(text="Emotion: None")
92+
self.conf_bar["value"] = 0
93+
94+
# ---------------- Update Frame ----------------
95+
def update(self):
96+
if not self.running:
97+
return
98+
99+
ret, frame = self.cap.read()
100+
if not ret:
101+
return
102+
103+
self.last_frame = frame.copy()
104+
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
105+
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
106+
107+
for (x, y, w, h) in faces:
108+
face = gray[y:y+h, x:x+w]
109+
face = cv2.resize(face, (48, 48))
110+
face = face / 255.0
111+
face = np.reshape(face, (1, 48, 48, 1))
112+
113+
preds = model.predict(face, verbose=0)[0]
114+
idx = np.argmax(preds)
115+
emotion = emotion_labels[idx]
116+
confidence = preds[idx]
117+
118+
self.emotion_label.config(text=f"Emotion: {emotion}")
119+
self.conf_bar["value"] = confidence * 100
120+
121+
self.history.append(confidence)
122+
self.line.set_data(range(len(self.history)), list(self.history))
123+
self.ax.set_xlim(0, 50)
124+
self.canvas.draw()
125+
126+
cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 2)
127+
cv2.putText(frame, f"{emotion} ({confidence:.2f})",
128+
(x,y-10), cv2.FONT_HERSHEY_SIMPLEX,
129+
0.8, (0,255,0), 2)
130+
131+
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
132+
img = Image.fromarray(frame)
133+
img = img.resize((800, 500), Image.Resampling.LANCZOS)
134+
imgtk = ImageTk.PhotoImage(img)
135+
self.video_label.imgtk = imgtk
136+
self.video_label.config(image=imgtk)
137+
138+
self.root.after(30, self.update)
139+
140+
# ---------------- Save Snapshot ----------------
141+
def save_snapshot(self):
142+
if self.last_frame is None:
143+
return
144+
path = filedialog.asksaveasfilename(
145+
defaultextension=".jpg",
146+
filetypes=[("JPEG", "*.jpg"), ("PNG", "*.png")]
147+
)
148+
if path:
149+
cv2.imwrite(path, self.last_frame)
150+
messagebox.showinfo("Saved", f"Snapshot saved:\n{path}")
151+
152+
# ---------------- Main ----------------
153+
if __name__ == "__main__":
154+
root = tb.Window(themename="superhero")
155+
EmotionApp(root)
156+
root.mainloop()

0 commit comments

Comments
 (0)