File size: 5,282 Bytes
095392e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3de05a3
 
 
 
 
 
 
 
095392e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
835b197
db9aa6f
3de05a3
d40b455
3de05a3
 
095392e
 
 
 
58104c3
 
095392e
 
 
 
 
 
 
 
 
 
 
4138b04
3de05a3
 
 
 
 
 
 
095392e
 
 
 
3de05a3
095392e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a1a5d57
23f926c
3de05a3
095392e
 
67969e1
16fa463
 
 
 
 
 
 
 
 
 
 
 
 
095392e
16fa463
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
095392e
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import openvino as ov
import cv2
import numpy as np
import PIL
import io
import tempfile
import streamlit as st
import moviepy.editor as mpy


class EmotionModel:
    def __init__(self):
        self.face_compiled_model, self.face_input_layer, self.face_output_layer = self.load_model('face-detection-adas-0001')
        self.emotion_compiled_model, self.emotion_input_layer, self.emotion_output_layer = self.load_model('emotions-recognition-retail-0003')

        self.emotions = {
            0:"neutral",
            1:"happy",
            2:"sad",
            3:"surprise",
            4:"anger"
        }
        
    def load_model(self, model_name):
        model_path = "models/" + model_name + ".xml"
        core = ov.Core()
        model = core.read_model(model=model_path)
        compiled_model = core.compile_model(model=model, device_name="CPU")
        input_layer = compiled_model.input(0)
        output_layer = compiled_model.output(0)
        return compiled_model, input_layer, output_layer

    def preprocess(self, img, input_layer):
 
        input_h, input_w = input_layer.shape[2], input_layer.shape[3]
        input_img = cv2.resize(img, (input_w,input_h))
        input_img = input_img.transpose(2, 0, 1)
        input_img = np.expand_dims(input_img, 0)
        
        return input_img

    def detect_faces(self, uploaded_img_cv, conf = 0.5):
        input_img = self.preprocess(uploaded_img_cv, self.face_input_layer)
        result_face = self.face_compiled_model([input_img])[self.face_output_layer]
        boxes = self.post_process_face(result_face, uploaded_img_cv, conf)

        return boxes

    def post_process_face(self, result_face, img, conf=0.5):
        boxes = []
        h,w,_ = img.shape
        predictions = result_face[0][0]       # ํ•˜์œ„ ์ง‘ํ•ฉ ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„
        confidence = predictions[:,2]    # conf ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ [img_id, label, conf, x_min, y_min, x_max, y_max]
      
        top_predictions = predictions[(confidence>conf)]         # ์ž„๊ณ„๊ฐ’๋ณด๋‹ค ํฐ conf ๊ฐ’์„ ๊ฐ€์ง„ ์˜ˆ์ธก๋งŒ ์„ ํƒ
        for detection in top_predictions:
            box = (detection[3:7]* np.array([w, h, w, h])).astype("int") # ์ƒ์ž ์œ„์น˜ ๊ฒฐ์ •
            box = [0 if i < 0 else i for i in box]
            (xmin, ymin, xmax, ymax) = box   # xmin, ymin, xmax, ymax์— ์ƒ์ž ์œ„์น˜ ๊ฐ’ ์ง€์ •
            boxes.append(box)
            cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 0, 255), 2)       # ์‚ฌ๊ฐํ˜• ๋งŒ๋“ค๊ธฐ
        
        return boxes

    def detect_emotions(self, uploaded_img_cv, boxes):
        for box in boxes:
            xmin, ymin, xmax, ymax = box
            emotion_input = uploaded_img_cv[ymin:ymax,xmin:xmax]
            input_img = self.preprocess(emotion_input, self.emotion_input_layer)       
            result_emotion = self.emotion_compiled_model([input_img])[self.emotion_output_layer]
            self.post_process_emotion(result_emotion, uploaded_img_cv, box)

    def post_process_emotion(self, result_emotion, img, face_position):
        
        predictions = result_emotion[0,:,0,0]   
        topresult_index = np.argmax(predictions)
        emotion = self.emotions[topresult_index]

        font_size = img.shape[0]/1000
        font_thickness = int(img.shape[0]/500)
        text_offset = int(img.shape[0]/30)
       
        cv2.putText(img, emotion,
                    (face_position[0],face_position[1]+text_offset),
                    cv2.FONT_HERSHEY_SIMPLEX, font_size, 
                    (255, 255,255), font_thickness)
        
        return emotion

    def process(self, img):

        if isinstance(img, np.ndarray):
            uploaded_img_cv = img
        else:
            uploaded_img = PIL.Image.open(img)
            uploaded_img_cv =  np.array(uploaded_img) 

        boxes = self.detect_faces(uploaded_img_cv)
        self.detect_emotions(uploaded_img_cv, boxes)
        
        return uploaded_img_cv

    def play_video(self, input_video):
        uploaded_video = io.BytesIO(input_video.read())
        temporary_location = "upload.mp4" 
        with open(temporary_location, "wb") as out: 
            out.write(uploaded_video.read())
        out.close() 
        
        camera = cv2.VideoCapture(temporary_location)
        fps = camera.get(cv2.CAP_PROP_FPS)
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
        processed_frames=[]
        total_frames = int(camera.get(cv2.CAP_PROP_FRAME_COUNT))
        progress_bar = st.progress(0)
        frame_count = 0
    
        st_frame = st.empty()
        while(camera.isOpened()):
            ret, frame = camera.read()
    
            if ret:
                emotion_img = self.process(frame)
                st_frame.image(emotion_img, channels = "BGR")
                processed_frames.append(cv2.cvtColor(emotion_img,cv2.COLOR_BGR2RGB))
                frame_count +=1
                progress_bar.progress(frame_count/total_frames, text = None)
    
            else:
                camera.release()
                st_frame.empty()
                progress_bar.empty()
                break
        clip = mpy.ImageSequenceClip(processed_frames,fps=fps)
        clip.write_videofile(temp_file.name)
    
        return temp_file.name