process_model.py 5.24 KB
Newer Older
1
2
# This class makes the training of the model possible

3
import argparse
Arne Gerdes's avatar
Arne Gerdes committed
4
import glob
tihmels's avatar
tihmels committed
5
import logging
Arne Gerdes's avatar
Arne Gerdes committed
6
7
import random
import cv2
tihmels's avatar
tihmels committed
8
import cv2.face
Arne Gerdes's avatar
Arne Gerdes committed
9
import numpy as np
10
11
import sys

12
13
14
15
from email_service import sendMail

logfile = 'logs/process_model.log'

16
# Creates and configures the logger
17
logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)-8s %(message)s',
tihmels's avatar
tihmels committed
18
                    datefmt='%m-%d %H:%M',
19
                    filename=logfile)
20

21
# Argument parser allows to specify program parameters
22
parser = argparse.ArgumentParser(description='Process Model Application')
tihmels's avatar
tihmels committed
23
24
25
26
27
28
29
30
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')
parser.add_argument('-d', '--dataset', action='store', dest='dataset', default='resources/img_data/dataset/',
Arne Gerdes's avatar
Arne Gerdes committed
31
                    help='path to dataset')
32
33
parser.add_argument('-i' '--iterations', action='store', dest='iterations', type=int, default=30,
                    help='number of iterations')
tihmels's avatar
tihmels committed
34
parser.add_argument('-p', '--properties', nargs='+', dest='properties', help='pre-processing steps for logging')
35
36
37
parser.add_argument('-t', '--test', action='store_true', dest='test', help='prevent writing new model to classifier')
parser.add_argument('-c', '--csv', action='store_true', dest='csv', help='activate csv output')
parser.add_argument('-x', '--email', action='store_true', dest='email', help='activate email notifications')
38
39
40
arguments = parser.parse_args()
logging.debug(arguments)

41
42
43
if not arguments.emotions:
    print('No emotions declared')
    sys.exit()
44
45

logging.info('Fisherface training started')
46

47
if arguments.email:
48
    sendMail('Fisherface training started')
Arne Gerdes's avatar
Arne Gerdes committed
49

50
51
def _get_faces_from_emotion(emotion):
    """
52
53
54
    Get all the files to an emotion from the dataset, mix them, and split them into a training and test set.
     : param emotion: The emotion
     : return: training, prediction
55
    """
56
    files = glob.glob(arguments.dataset + '{}/*'.format(emotion))
Arne Gerdes's avatar
Arne Gerdes committed
57
    random.shuffle(files)
Arne Gerdes's avatar
Arne Gerdes committed
58

59
    # Mix the dataset in training and comparison images in the ratio 80 to 20
Arne Gerdes's avatar
Arne Gerdes committed
60
61
62
    training = files[:int(len(files) * 0.8)]
    prediction = files[-int(len(files) * 0.2):]

Arne Gerdes's avatar
Arne Gerdes committed
63
64
    return training, prediction

Arne Gerdes's avatar
Arne Gerdes committed
65

66
67
def image_preprocessing(image):
    """
68
69
    Preprocessing of the files
     : param item: picture
70
71
72
    """
    img = cv2.imread(image)  # open image
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # convert to grayscale
Arne Gerdes's avatar
Arne Gerdes committed
73
    clahe = cv2.createCLAHE(2.0, (8, 8))
tihmels's avatar
tihmels committed
74
75
    norm = clahe.apply(gray)
    return norm
Arne Gerdes's avatar
Arne Gerdes committed
76

Arne Gerdes's avatar
Arne Gerdes committed
77

Arne Gerdes's avatar
Arne Gerdes committed
78
79
80
81
82
def make_sets():
    training_data = []
    training_labels = []
    prediction_data = []
    prediction_labels = []
83
    for emotion in arguments.emotions:
84
        training, prediction = _get_faces_from_emotion(emotion)
Arne Gerdes's avatar
Arne Gerdes committed
85
86
        # Append data to training and prediction list, and generate labels 0-7
        for item in training:
tihmels's avatar
tihmels committed
87
            img = image_preprocessing(item)
88
89
            # append image array to training data list
            training_data.append(img)
90
            training_labels.append(arguments.emotions.index(emotion))
Arne Gerdes's avatar
Arne Gerdes committed
91

92
93
        # repeat above process for prediction set
        for item in prediction:
tihmels's avatar
tihmels committed
94
95
            img = image_preprocessing(item)
            prediction_data.append(img)
96
            prediction_labels.append(arguments.emotions.index(emotion))
Arne Gerdes's avatar
Arne Gerdes committed
97
98
99

    return training_data, training_labels, prediction_data, prediction_labels

Arne Gerdes's avatar
Arne Gerdes committed
100

Arne Gerdes's avatar
Arne Gerdes committed
101
102
103
def run_recognizer():
    training_data, training_labels, prediction_data, prediction_labels = make_sets()

tihmels's avatar
tihmels committed
104
    logging.debug('Training...')
Arne Gerdes's avatar
Arne Gerdes committed
105
106
107
108
109
    fishface.train(training_data, np.asarray(training_labels))

    cnt = 0
    correct = 0
    incorrect = 0
tihmels's avatar
tihmels committed
110
    logging.debug('Prediction...')
Arne Gerdes's avatar
Arne Gerdes committed
111
112
113
114
115
116
117
118
    for image in prediction_data:
        pred, conf = fishface.predict(image)
        if pred == prediction_labels[cnt]:
            correct += 1
            cnt += 1
        else:
            incorrect += 1
            cnt += 1
119
    return (100 * correct) / (correct + incorrect)
Arne Gerdes's avatar
Arne Gerdes committed
120

Arne Gerdes's avatar
Arne Gerdes committed
121

122
# Emotions list
tihmels's avatar
tihmels committed
123
fishface = cv2.face.FisherFaceRecognizer_create()
Arne Gerdes's avatar
Arne Gerdes committed
124
metascore = []
tihmels's avatar
tihmels committed
125

126
for i in range(1, arguments.iterations + 1):
Arne Gerdes's avatar
Arne Gerdes committed
127
    correct = run_recognizer()
128
    logging.info("{} : {}%".format(i, int(correct)))
Arne Gerdes's avatar
Arne Gerdes committed
129
    metascore.append(correct)
130

tihmels's avatar
nichts    
tihmels committed
131
    if arguments.email and i % (int(arguments.iterations / 4)) == 0:
132
133
        sendMail(str(i) + ' iterations done', body='up-to-date average: {}%'.format(np.mean(metascore)))

134
135
if arguments.csv:
    file = open("resources/csv/{}.csv".format('_'.join(arguments.properties).lower()), "w")
136
137
138
139
140
141
142
    for entry in metascore:
        file.write("{}\n".format(int(entry)))

    file.close()

logging.info("Fisherface training finished - {}% average\n".format(np.mean(metascore)))

143
if not arguments.test:
tihmels's avatar
tihmels committed
144
    fishface.write('resources/models/detection_model.xml')
Arne Gerdes's avatar
Arne Gerdes committed
145

146
if arguments.email:
147
    sendMail('Fisherface training finished')