webcam.py 4.88 KB
Newer Older
tihmels's avatar
tihmels committed
1
2
3
4
5
6
7
8
9
10
11
12
13
# ***************************************************
# * Copyright © 2010-2011 Tjado Ihmels <tjado.ihmels@uni-oldenburg.de>
# *
# * This file is part of whiteboard-project-matcher.
# *
# * whiteboard-project-matcher can not be copied and/or distributed without the express
# * permission of Tjado Ihmels
# *
# * Parts of this program are legally copied and adapted from
# * van Gent, P. (2016). Emotion Recognition With Python, OpenCV and a Face Dataset. A tech blog about fun things with Python and embedded electronics. Retrieved from:
# * http://www.paulvangent.com/2016/04/01/emotion-recognition-with-python-opencv-and-a-face-dataset/
# ***************************************************/

tihmels's avatar
tihmels committed
14
import argparse
Arne Gerdes's avatar
Arne Gerdes committed
15
16

import cv2
tihmels's avatar
tihmels committed
17
import cv2.face
Arne Gerdes's avatar
Arne Gerdes committed
18
import numpy as np
19

20
from RingBuffer import RingBuffer
21
from WebcamVideoStream import WebcamVideoStream
22
from face_detect import extract_faces
23
from image_commons import nparray_as_image, draw_with_alpha, draw_img
Arne Gerdes's avatar
Arne Gerdes committed
24

tihmels's avatar
tihmels committed
25
parser = argparse.ArgumentParser(description='ProjectMood Emotion Detection')
tihmels's avatar
tihmels committed
26
27
28
29
30
31
32
parser.add_argument('-0', action='append_const', dest='emotions', const='neutral', help='neutral')
parser.add_argument('-1', action='append_const', dest='emotions', const='happy', help='happy')
parser.add_argument('-2', action='append_const', dest='emotions', const='sadness', help='sadness')
parser.add_argument('-3', action='append_const', dest='emotions', const='surprise', help='surprise')
parser.add_argument('-4', action='append_const', dest='emotions', const='fear', help='fear')
parser.add_argument('-5', action='append_const', dest='emotions', const='disgust', help='disgust')
parser.add_argument('-6', action='append_const', dest='emotions', const='anger', help='anger')
tihmels's avatar
tihmels committed
33
parser.add_argument('-b', '--buffer', action='store', dest='buffer', default=12, type=int, help='size of ringbuffer')
tihmels's avatar
tihmels committed
34
parser.add_argument('-m', '--model', action='store', dest='model', default='resources/models/five_emotions.xml',
Arne Gerdes's avatar
Arne Gerdes committed
35
                    help='path to model')
tihmels's avatar
tihmels committed
36
parser.add_argument('-r', '--resize', action='store', type=int, dest='resizefactor')
tihmels's avatar
tihmels committed
37
arguments = parser.parse_args()
Arne Gerdes's avatar
Arne Gerdes committed
38

39

Arne Gerdes's avatar
Arne Gerdes committed
40
41
def _load_emoticons(emotions):
    """
42
43
44
    Load the emoticons from the emojis folder.
     : param emotions: emotions as an array.
     : return: Array of Emotions graphics.
Arne Gerdes's avatar
Arne Gerdes committed
45
    """
46
47
    return [nparray_as_image(cv2.imread('resources/emojis/{}.png'.format(emotion), -1), mode=None) for emotion in
            emotions]
Arne Gerdes's avatar
Arne Gerdes committed
48

tihmels's avatar
tihmels committed
49

tihmels's avatar
tihmels committed
50
def show_webcam_and_run(model, emoticons, window_size=(600, 600), window_name=parser.description, update_time=1):
Arne Gerdes's avatar
Arne Gerdes committed
51
    """
tihmels's avatar
tihmels committed
52
    Shows a webcam input, recognizes faces and emotions in real time and draws emoticons next to the faces.
53
54
55
56
57
     : param model: Trained Model
     : param emoticons: list of emoticons.
     : param window_size: Size of the webcam window.
     : param window_name: name of the webcam window.
     : param update_time: Image update time.
Arne Gerdes's avatar
Arne Gerdes committed
58
    """
59
    cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
60
61
    width, height = window_size
    cv2.resizeWindow(window_name, width, height)
Arne Gerdes's avatar
Arne Gerdes committed
62

63
    vc = WebcamVideoStream().start()
64

tihmels's avatar
tihmels committed
65
66
67
68
69
70
    if not arguments.resizefactor:
        # a random image from the dataset to determine the image format (important for Fisherface)
        random = cv2.imread('resources/img_data/dataset/{}/0.jpg'.format(arguments.emotions[0]))
        resizefactor = np.size(random, 0)
    else:
        resizefactor = arguments.resizefactor
tihmels's avatar
tihmels committed
71

72
    # The RingBuffer stores the last x Predictions
tihmels's avatar
tihmels committed
73
    buffer = RingBuffer(arguments.buffer)
74

75
    frame = vc.read()
Arne Gerdes's avatar
Arne Gerdes committed
76

77
    while True:
tihmels's avatar
tihmels committed
78
        for normalized_face in extract_faces(frame, resizefactor):
79
            prediction = model.predict(normalized_face)  # do prediction
80

81
            # Save the Predictions
82
            buffer.append(prediction[0])
Arne Gerdes's avatar
Arne Gerdes committed
83

84
            # Get the entries as an array
85
            predictions = buffer.get()
Arne Gerdes's avatar
Arne Gerdes committed
86

87
88
89
90
            # Read the processed input image
            processed_image = nparray_as_image(normalized_face[:, :], mode='L')
            w, h = vc.size()
            # And print it to the frame
tihmels's avatar
tihmels committed
91
            draw_img(frame, processed_image, (w - 300, h - 300, 250, 250))
92

93
            # No entry in the ring buffer is None
94
            if not (any(x is None for x in predictions)):
95
                # Counting occurrences of predictions
96
                unique, counts = np.unique(predictions, return_counts=True)
Arne Gerdes's avatar
Arne Gerdes committed
97

98
                # Most frequent value is displayed
Arne Gerdes's avatar
Arne Gerdes committed
99
                image_to_draw = emoticons[unique[0]]
100
                draw_with_alpha(frame, image_to_draw, (40, 40, 200, 200))
Arne Gerdes's avatar
Arne Gerdes committed
101

102
103
        cv2.imshow(window_name, frame)
        frame = vc.read()
Arne Gerdes's avatar
Arne Gerdes committed
104
105
        key = cv2.waitKey(update_time)

106
107
        # exit on ESC
        if key == 27:
108
            vc.stop()
Arne Gerdes's avatar
Arne Gerdes committed
109
110
111
112
113
114
            break

    cv2.destroyWindow(window_name)


if __name__ == '__main__':
tihmels's avatar
tihmels committed
115
    emoticons = _load_emoticons(arguments.emotions)
Arne Gerdes's avatar
Arne Gerdes committed
116
117

    fisher_face = cv2.face.FisherFaceRecognizer_create()
Arne Gerdes's avatar
Arne Gerdes committed
118

119
    # Load the trained model
tihmels's avatar
tihmels committed
120
    fisher_face.read(arguments.model)
121
    show_webcam_and_run(fisher_face, emoticons)