from flask import Flask, render_template, Response
import cv2
import pygame
import numpy as np
from keras.models import load_model
from statistics import mode
from utils.datasets import get_labels
from utils.inference import detect_faces
from utils.inference import draw_text
from utils.inference import draw_bounding_box
from utils.inference import apply_offsets
from utils.inference import load_detection_model
from utils.preprocessor import preprocess_input

# Create Flask Entity Instant
app = Flask(__name__)

# parameters for loading data and images
emotion_model_path = './models/emotion_model.hdf5'
emotion_labels = get_labels('fer2013')

# hyper-parameters for bounding boxes shape
frame_window = 10
emotion_offsets = (20, 40)

# loading models
face_cascade = cv2.CascadeClassifier('./models/haarcascade_frontalface_default.xml')
emotion_classifier = load_model(emotion_model_path)

# getting input model shapes for inference
emotion_target_size = emotion_classifier.input_shape[1:3]

# starting lists for calculating modes
emotion_window = []

cap = cv2.VideoCapture(0)

pygame.mixer.init(16000, -16, 1, 2048)

music_sad = "music/sad.mp3"   # mp3 or mid file
music_angry = "music/angry.mp3"
music_happy = "music/happy.mp3"


def playmusic(soundfile):
    if not pygame.mixer.music.get_busy():
        pygame.mixer.music.stop()
        pygame.mixer.music.load(soundfile)
        pygame.mixer.music.play()
        pygame.mixer.music.fadeout(10000)

def gen(video):
    while True:
        success, bgr_image = cap.read()

        gray_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY)
        rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)

        faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5,
                minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)

        for face_coordinates in faces:

            x1, x2, y1, y2 = apply_offsets(face_coordinates, emotion_offsets)
            gray_face = gray_image[y1:y2, x1:x2]
            try:
                gray_face = cv2.resize(gray_face, (emotion_target_size))
            except:
                continue

            gray_face = preprocess_input(gray_face, True)
            gray_face = np.expand_dims(gray_face, 0)
            gray_face = np.expand_dims(gray_face, -1)
            emotion_prediction = emotion_classifier.predict(gray_face)
            emotion_probability = np.max(emotion_prediction)
            emotion_label_arg = np.argmax(emotion_prediction)
            emotion_text = emotion_labels[emotion_label_arg]
            emotion_window.append(emotion_text)

            if len(emotion_window) > frame_window:
                emotion_window.pop(0)
            try:
                emotion_mode = mode(emotion_window)
            except:
                continue
            
            if emotion_text == 'angry':
                playmusic(music_angry)
                color = emotion_probability * np.asarray((255, 0, 0))
            elif emotion_text == 'sad':
                playmusic(music_sad)
                color = emotion_probability * np.asarray((0, 0, 255))
            elif emotion_text == 'happy':
                playmusic(music_happy)
                color = emotion_probability * np.asarray((255, 255, 0))
            elif emotion_text == 'surprise':
                color = emotion_probability * np.asarray((0, 255, 255))
            else:
                color = emotion_probability * np.asarray((0, 255, 0))

            color = color.astype(int)
            color = color.tolist()

            draw_bounding_box(face_coordinates, rgb_image, color)
            draw_text(face_coordinates, rgb_image, emotion_mode,
                    color, 0, -45, 1, 1)

        bgr_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR)

        # flask 에서 image 재처리
        ret, jpeg = cv2.imencode('.jpg',bgr_image)
        frame = jpeg.tobytes()
        yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()

@app.route('/')
def index():
    return render_template("index.html")
@app.route('/run')
def run():
    return render_template("generic.html")

@app.route('/video_feed')
def video_feed():
    global cap
    return Response(gen(cap), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == "__main__":
    #app.run(host='0.0.0.0', port=9900, debug=True)
    app.run(debug=True)
    # host 등을 직접 지정하고 싶다면
    # app.run(host="127.0.0.1", port="5000", debug=True)


from flask import Flask, render_template, Response
import cv2
import pygame
import numpy as np
from keras.models import load_model
from statistics import mode
from utils.datasets import get_labels
from utils.inference import detect_faces
from utils.inference import draw_text
from utils.inference import draw_bounding_box
from utils.inference import apply_offsets
from utils.inference import load_detection_model
from utils.preprocessor import preprocess_input

# Create Flask Entity Instant
app = Flask(__name__)

# parameters for loading data and images
emotion_model_path = './models/emotion_model.hdf5'
emotion_labels = get_labels('fer2013')

# hyper-parameters for bounding boxes shape
frame_window = 10
emotion_offsets = (20, 40)

# loading models
face_cascade = cv2.CascadeClassifier('./models/haarcascade_frontalface_default.xml')
emotion_classifier = load_model(emotion_model_path)

# getting input model shapes for inference
emotion_target_size = emotion_classifier.input_shape[1:3]

# starting lists for calculating modes
emotion_window = []

cap = cv2.VideoCapture(0)

pygame.mixer.init(16000, -16, 1, 2048)

music_sad = "music/sad.mp3"   # mp3 or mid file
music_angry = "music/angry.mp3"
music_happy = "music/happy.mp3"


def playmusic(soundfile):
    if not pygame.mixer.music.get_busy():
        pygame.mixer.music.stop()
        pygame.mixer.music.load(soundfile)
        pygame.mixer.music.play()
        pygame.mixer.music.fadeout(10000)

def gen(video):
    while True:
        success, bgr_image = cap.read()

        gray_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY)
        rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)

        faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5,
                minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE)

        for face_coordinates in faces:

            x1, x2, y1, y2 = apply_offsets(face_coordinates, emotion_offsets)
            gray_face = gray_image[y1:y2, x1:x2]
            try:
                gray_face = cv2.resize(gray_face, (emotion_target_size))
            except:
                continue

            gray_face = preprocess_input(gray_face, True)
            gray_face = np.expand_dims(gray_face, 0)
            gray_face = np.expand_dims(gray_face, -1)
            emotion_prediction = emotion_classifier.predict(gray_face)
            emotion_probability = np.max(emotion_prediction)
            emotion_label_arg = np.argmax(emotion_prediction)
            emotion_text = emotion_labels[emotion_label_arg]
            emotion_window.append(emotion_text)

            if len(emotion_window) > frame_window:
                emotion_window.pop(0)
            try:
                emotion_mode = mode(emotion_window)
            except:
                continue
            
            if emotion_text == 'angry':
                playmusic(music_angry)
                color = emotion_probability * np.asarray((255, 0, 0))
            elif emotion_text == 'sad':
                playmusic(music_sad)
                color = emotion_probability * np.asarray((0, 0, 255))
            elif emotion_text == 'happy':
                playmusic(music_happy)
                color = emotion_probability * np.asarray((255, 255, 0))
            elif emotion_text == 'surprise':
                color = emotion_probability * np.asarray((0, 255, 255))
            else:
                color = emotion_probability * np.asarray((0, 255, 0))

            color = color.astype(int)
            color = color.tolist()

            draw_bounding_box(face_coordinates, rgb_image, color)
            draw_text(face_coordinates, rgb_image, emotion_mode,
                    color, 0, -45, 1, 1)

        bgr_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR)

        # flask 에서 image 재처리
        ret, jpeg = cv2.imencode('.jpg',bgr_image)
        frame = jpeg.tobytes()
        yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()

@app.route('/')
def index():
    return render_template("index.html")
@app.route('/run')
def run():
    return render_template("generic.html")

@app.route('/video_feed')
def video_feed():
    global cap
    return Response(gen(cap), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == "__main__":
    #app.run(host='0.0.0.0', port=9900, debug=True)
    app.run(debug=True)
    # host 등을 직접 지정하고 싶다면
    # app.run(host="127.0.0.1", port="5000", debug=True)


# Create Flask Entity Instant # parameters for loading data and images # hyper-parameters for bounding boxes shape # loading models # getting input model shapes for inference # starting lists for calculating modes # mp3 or mid file # flask 에서 image 재처리 #app.run(host='0.0.0.0', port=9900, debug=True) # host 등을 직접 지정하고 싶다면 # app.run(host="127.0.0.1", port="5000", debug=True)