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
from cv2 import *
Arne Gerdes's avatar
Arne Gerdes committed
18
import numpy as np
19
from RingBuffer import RingBuffer
20
from WebcamVideoStream import WebcamVideoStream
21
from face_detect import extract_faces
tihmels's avatar
tihmels committed
22
from image_commons import nparray_as_image, draw_alpha_3dim, draw_2dim
Arne Gerdes's avatar
Arne Gerdes committed
23

tihmels's avatar
tihmels committed
24
parser = argparse.ArgumentParser(description='ProjectMood Emotion Detection')
tihmels's avatar
tihmels committed
25 26 27 28 29 30 31
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
32
parser.add_argument('-b', '--buffer', action='store', dest='buffer', default=12, type=int, help='size of ringbuffer')
tihmels's avatar
tihmels committed
33
parser.add_argument('-m', '--model', action='store', dest='model', default='resources/models/five_emotions.xml',
Arne Gerdes's avatar
Arne Gerdes committed
34
                    help='path to model')
tihmels's avatar
tihmels committed
35
parser.add_argument('-r', '--resize', action='store', type=int, dest='resizefactor')
tihmels's avatar
tihmels committed
36
arguments = parser.parse_args()
Arne Gerdes's avatar
Arne Gerdes committed
37

38

Arne Gerdes's avatar
Arne Gerdes committed
39 40
def _load_emoticons(emotions):
    """
41 42 43
    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
44
    """
45 46
    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
47

tihmels's avatar
tihmels committed
48

tihmels's avatar
tihmels committed
49
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
50
    """
tihmels's avatar
tihmels committed
51
    Shows a webcam input, recognizes faces and emotions in real time and draws emoticons next to the faces.
52 53 54 55 56
     : 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
57
    """
58
    cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
59 60
    width, height = window_size
    cv2.resizeWindow(window_name, width, height)
Arne Gerdes's avatar
Arne Gerdes committed
61

62
    vc = WebcamVideoStream().start()
63

tihmels's avatar
tihmels committed
64 65 66 67 68 69
    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
70

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

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

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

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

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

86 87 88 89
            # 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
90
            draw_2dim(frame, processed_image, (w - 300, h - 300, 250, 250))
91

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

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

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

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

    cv2.destroyWindow(window_name)


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

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

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