File size: 3,183 Bytes
a683413
 
58aac12
 
a683413
 
 
 
 
 
 
 
 
 
8b22856
58aac12
a1abe52
a5234fe
58aac12
 
8b22856
 
58aac12
 
8b22856
58aac12
 
 
 
8b22856
58aac12
8b22856
a683413
 
 
 
 
 
 
 
 
 
 
 
 
a5234fe
 
 
 
 
a683413
 
 
 
 
 
 
 
 
 
 
 
 
 
8b22856
c76aaa3
8b22856
 
a683413
8b22856
a683413
 
8b22856
a683413
 
 
 
 
 
 
 
 
8b22856
a683413
 
 
 
 
 
 
 
8b22856
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
91
92
93
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
import base64
from io import BytesIO
from PIL import Image
import numpy as np
import cv2
import os
import traceback
from keras.models import load_model

# FastAPI app
app = FastAPI()
app.mount("/static", StaticFiles(directory="Frontend"), name="static")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"], allow_credentials=True,
    allow_methods=["*"], allow_headers=["*"]
)

# Load model & face detector
model_path = os.path.join(os.path.dirname(__file__), 'emotion_model.keras')
model = load_model(model_path)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# Mappings
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}
emoji_map = {
    0: os.path.join(BASE_DIR, "emojis", "angry.png"),
    1: os.path.join(BASE_DIR, "emojis", "disgusted.png"),
    2: os.path.join(BASE_DIR, "emojis", "fearful.png"),
    3: os.path.join(BASE_DIR, "emojis", "happy.png"),
    4: os.path.join(BASE_DIR, "emojis", "neutral.png"),
    5: os.path.join(BASE_DIR, "emojis", "sad.png"),
    6: os.path.join(BASE_DIR, "emojis", "surprised.png")
}

class ImageData(BaseModel):
    image: str

@app.get("/")
def serve_homepage():
    return FileResponse("Frontend/index.html")

@app.post("/process_image")
async def process_image(data: ImageData):
    try:
        header, encoded = data.image.split(",")
        img_bytes = base64.b64decode(encoded)
        img = Image.open(BytesIO(img_bytes)).convert('RGB')
        img_np = np.array(img)

        gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)

        if len(faces) == 0:
            raise HTTPException(status_code=400, detail="No face detected")

        for (x, y, w, h) in faces:
            face = img_np[y:y+h, x:x+w]
            face = cv2.resize(face, (192, 192))
            face = face.astype("float32") / 255.0
            face = np.expand_dims(face, axis=0)

            preds = model.predict(face, verbose=0)
            emotion_index = int(np.argmax(preds))
            emotion_label = emotion_dict[emotion_index]
            confidence = float(np.max(preds))

            emoji_path = emoji_map[emotion_index]
            emoji_img = Image.open(emoji_path).convert("RGBA")
            buffer = BytesIO()
            emoji_img.save(buffer, format="PNG")
            encoded_emoji = base64.b64encode(buffer.getvalue()).decode("utf-8")

            return JSONResponse({
                "emotion": emotion_label,
                "confidence": round(confidence * 100, 2),
                "emoji": f"data:image/png;base64,{encoded_emoji}"
            })

        raise HTTPException(status_code=400, detail="Face not processed")

    except Exception as e:
        traceback.print_exc()
        raise HTTPException(status_code=500, detail=str(e))