Smile / app.py
ktejeshnaidu's picture
Update app.py
31cd5f1 verified
import gradio as gr
import cv2
import numpy as np
from model import EmotionPredictor
# Initialize the predictor
predictor = EmotionPredictor()
# Load Haar Cascade for face detection
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
if face_cascade.empty():
raise RuntimeError("Failed to load Haar Cascade")
def predict_emotion(image):
"""
Predict emotion from an image.
Args:
image: PIL Image or numpy array
Returns:
annotated image and emotion prediction
"""
if image is None:
return None, "No image provided"
# Convert PIL Image to numpy array if needed
if isinstance(image, np.ndarray):
frame = image
else:
frame = np.array(image)
# Convert RGB to BGR for OpenCV
if len(frame.shape) == 3 and frame.shape[2] == 3:
frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
else:
frame_bgr = frame
# Convert to grayscale for face detection
gray = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2GRAY)
# Detect faces
detected = face_cascade.detectMultiScale(
gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)
)
if len(detected) == 0:
return frame, "No face detected"
# Get the largest face
faces = [max(detected, key=lambda r: r[2]*r[3])]
# Process the face
output_frame = frame_bgr.copy()
emotions = []
for (x, y, w, h) in faces:
# Extract face region
face_rgb = cv2.cvtColor(frame_bgr[y:y+h, x:x+w], cv2.COLOR_BGR2RGB)
# Predict emotion
emotion = predictor.predict(face_rgb)
emotions.append(emotion)
# Draw rectangle and label
cv2.rectangle(output_frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.putText(
output_frame, emotion, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2
)
# Convert back to RGB for display
output_frame_rgb = cv2.cvtColor(output_frame, cv2.COLOR_BGR2RGB)
# Return annotated image and detected emotion
emotion_text = ", ".join(emotions) if emotions else "No emotion detected"
return output_frame_rgb, f"Detected emotion(s): {emotion_text}"
# Create Gradio interface
with gr.Blocks(title="Smilo😃 - Real-Time Emotion Detection") as demo:
gr.HTML("""
<div style="background: linear-gradient(90deg, #FF9933 0%, #D0B264 50%, #469F93 100%);
padding: 40px;
border-radius: 12px;
text-align: center;
color: white;
font-family: 'Helvetica Neue', Arial, sans-serif;
margin-bottom: 20px;">
<h1 style="color: white; margin: 0; margin-bottom: 10px; font-weight: 900; font-size: 3.5em; display: flex; align-items: center; justify-content: center; gap: 10px;">
Smilo <span style="font-size: 0.9em;">😃</span>
</h1>
<p style="color: #f0f0f0; font-size: 1.2em; margin: 0; font-weight: 400; letter-spacing: 0.5px;">Real-Time Emotion Detection powered by PyTorch & OpenCV <a href='https://github.com/TejeshNaiduKona/Smilo' target='_blank'>GitHub</a></p>
</div>
""")
with gr.Row():
with gr.Column():
image_input = gr.Image(
label="Input Image",
type="pil",
sources=["upload", "webcam"]
)
submit_btn = gr.Button("Predict Emotion", variant="primary")
with gr.Column():
image_output = gr.Image(label="Annotated Image")
emotion_output = gr.Textbox(label="Prediction Result", interactive=False)
# Connect the function to the button
submit_btn.click(
fn=predict_emotion,
inputs=[image_input],
outputs=[image_output, emotion_output]
)
# Also run prediction when image is uploaded
image_input.change(
fn=predict_emotion,
inputs=[image_input],
outputs=[image_output, emotion_output]
)
if __name__ == "__main__":
demo.launch()