process_model.py 5.37 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
8
import random
import cv2
import numpy as np
9
10
import sys

11
12
13
14
from email_service import sendMail

logfile = 'logs/process_model.log'

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

20
# Argument parser allows to specify program parameters
21
parser = argparse.ArgumentParser(description='Process Model Application')
tihmels's avatar
tihmels committed
22
23
24
25
26
27
28
29
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
30
                    help='path to dataset')
tihmels's avatar
tihmels committed
31
parser.add_argument('-i' '--iterations', action='store', dest='iterations', type=int, default=1,
32
                    help='number of iterations')
tihmels's avatar
tihmels committed
33
parser.add_argument('-p', '--properties', nargs='*', dest='properties', help='pre-processing steps for logging')
34
35
36
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')
37
38
39
arguments = parser.parse_args()
logging.debug(arguments)

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

logging.info('Fisherface training started')
45
46
47

def _get_faces_from_emotion(emotion):
    """
48
49
50
    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
51
    """
52
    files = glob.glob(arguments.dataset + '{}/*'.format(emotion))
Arne Gerdes's avatar
Arne Gerdes committed
53
    random.shuffle(files)
Arne Gerdes's avatar
Arne Gerdes committed
54

55
    # Mix the dataset in training and comparison images in the ratio 80 to 20
tihmels's avatar
tihmels committed
56
57
    training = files[:int(len(files) * 1)]
    prediction = files[-int(len(files) * 0):]
Arne Gerdes's avatar
Arne Gerdes committed
58

Arne Gerdes's avatar
Arne Gerdes committed
59
60
    return training, prediction

Arne Gerdes's avatar
Arne Gerdes committed
61

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

Arne Gerdes's avatar
Arne Gerdes committed
73

Arne Gerdes's avatar
Arne Gerdes committed
74
def make_sets():
75
76
77
78
    """
    Creates the training set
    :return: The created training data
    """
Arne Gerdes's avatar
Arne Gerdes committed
79
80
81
82
    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
def run_recognizer():
102
103
104
105
    """
    Performs the actual training with Fisherfaces and Logged the results
    :return: The correctly recognized faces in percent
    """
Arne Gerdes's avatar
Arne Gerdes committed
106
107
    training_data, training_labels, prediction_data, prediction_labels = make_sets()

tihmels's avatar
tihmels committed
108
    logging.debug('Training...')
Arne Gerdes's avatar
Arne Gerdes committed
109
110
111
112
113
    fishface.train(training_data, np.asarray(training_labels))

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

Arne Gerdes's avatar
Arne Gerdes committed
125

126
# Emotions list
tihmels's avatar
tihmels committed
127
fishface = cv2.face.FisherFaceRecognizer_create()
Arne Gerdes's avatar
Arne Gerdes committed
128
metascore = []
tihmels's avatar
tihmels committed
129

130
# Argument parser
131
for i in range(1, arguments.iterations + 1):
Arne Gerdes's avatar
Arne Gerdes committed
132
    correct = run_recognizer()
133
    logging.info("{} : {}%".format(i, int(correct)))
Arne Gerdes's avatar
Arne Gerdes committed
134
    metascore.append(correct)
135

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

    file.close()

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

146
# Argument parser
147
if not arguments.test:
tihmels's avatar
tihmels committed
148
    fishface.write('resources/models/detection_model.xml')
Arne Gerdes's avatar
Arne Gerdes committed
149

150
# Argument parser
151
if arguments.email:
tihmels's avatar
tihmels committed
152
    sendMail('Fisherface training finished', body=str(arguments), filepath='resources/models/detection_model.xml')