File size: 3,351 Bytes
f9e4904
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import base64
import numpy as np
import cv2
from flask import Flask, render_template, request, jsonify
import tensorflow as tf
from PIL import Image
import io
from mtcnn import MTCNN
import os

app = Flask(__name__, static_folder='static', template_folder='templates')
app.secret_key = 'shamstabrez'

# Load Model
model_path = os.path.join("model", "RAFDB_Custom.h5")
if not os.path.exists(model_path):
    raise FileNotFoundError(f"Model file not found: {model_path}")

model = tf.keras.models.load_model(model_path)
class_labels = ['Angry', 'Disgust', 'Fear', 'Happy', 'Neutral', 'Sad', 'Surprise']
IMG_SIZE = (48, 48)
detector = MTCNN()

streaming = False

def detect_and_classify(frame):
    faces = detector.detect_faces(frame)
    detected_faces = []
    if faces:
        for face in faces:
            x, y, w, h = face['box']
            x, y = max(0, x), max(0, y)
            cropped_face = frame[y:y+h, x:x+w]

            if cropped_face.shape[0] > 0 and cropped_face.shape[1] > 0:
                face_rgb = cv2.resize(cropped_face, IMG_SIZE)
                face_array = tf.keras.preprocessing.image.img_to_array(face_rgb) / 255.0
                face_array = np.expand_dims(face_array, axis=0)

                predictions = model.predict(face_array)[0]
                top_indices = np.argsort(predictions)[-3:][::-1]  # Get top 3 emotions
                top_emotions = [(class_labels[i], round(predictions[i] * 100, 2)) for i in top_indices]

                cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 1)  # Thin border
                for i, (emotion, percentage) in enumerate(top_emotions):
                    text = f"{emotion} ({percentage}%)"
                    cv2.putText(frame, text, (x, y - (i * 20) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
                detected_faces.extend(top_emotions)
    return frame, detected_faces

@app.route('/')
def index():
    return render_template('index.html', top_emotions=None, img_base64=None, show_upload=True, show_camera=False, initial_image=True)

@app.route('/classify', methods=['POST'])
def classify_image():
    image = request.files['image']
    img = Image.open(image)
    img = np.array(img)
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    processed_frame, top_emotions = detect_and_classify(img)

    _, buffer = cv2.imencode('.png', processed_frame)
    img_base64 = base64.b64encode(buffer).decode('utf-8')

    return render_template('index.html', top_emotions=top_emotions, img_base64=img_base64, show_upload=True, show_camera=False, initial_image=False)

@app.route('/predict_video', methods=['POST'])
def predict_video():
    data = request.json
    image_data = data.get("image")

    if not image_data:
        return jsonify({"error": "No image data received"}), 400

    image_data = image_data.split(",")[1]
    image_bytes = base64.b64decode(image_data)
    image = Image.open(io.BytesIO(image_bytes))
    frame = np.array(image)
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

    processed_frame, detected_faces = detect_and_classify(frame)
    _, buffer = cv2.imencode(".jpg", processed_frame)
    processed_image_base64 = base64.b64encode(buffer).decode("utf-8")

    return jsonify({"processed_frame": processed_image_base64, "emotions": detected_faces})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7860)