process_model.py 5.19 KB
Newer Older
Arne Gerdes's avatar
Arne Gerdes committed
1
2
3
"""
Diese Klasse macht das Training des Models möglich
"""
4
import argparse
Arne Gerdes's avatar
Arne Gerdes committed
5
import glob
tihmels's avatar
tihmels committed
6
import logging
Arne Gerdes's avatar
Arne Gerdes committed
7
import random
Arne Gerdes's avatar
Arne Gerdes committed
8

Arne Gerdes's avatar
Arne Gerdes committed
9
10
import cv2
import numpy as np
11
12
13
14
from email_service import sendMail

logfile = 'logs/process_model.log'

Arne Gerdes's avatar
Arne Gerdes committed
15
16
17
"""
Erstellt und gibt das Log-File aus 
"""
18
logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)-8s %(message)s',
tihmels's avatar
tihmels committed
19
                    datefmt='%m-%d %H:%M',
20
                    filename=logfile)
21

Arne Gerdes's avatar
Arne Gerdes committed
22
"""
23
Argument Parser erlaubt Parameter für die Verarbeitung anzugeben.
Arne Gerdes's avatar
Arne Gerdes committed
24
"""
Arne Gerdes's avatar
Arne Gerdes committed
25

26
parser = argparse.ArgumentParser(description='Process Model Application')
tihmels's avatar
tihmels committed
27
28
29
30
31
32
33
34
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
35
                    help='path to dataset')
tihmels's avatar
tihmels committed
36
37
38
39
40
parser.add_argument('-i' '--iterations', action='store', dest='iterations', type=int, default=30, help='number of iterations')
parser.add_argument('-p', '--properties', nargs='+', dest='properties', help='pre-processing steps for logging')
parser.add_argument('-t', '--test', action='store_true', help='prevent writing new model to classifier')
parser.add_argument('-c', '--csv', action='store_true', help='activate csv processing')
parser.add_argument('-x', '--email', action='store_true', help='activate email notifications')
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
arguments = parser.parse_args()
logging.debug(arguments)

dataset_path = arguments.dataset
iterations = arguments.iterations
emotions = arguments.emotions
properties = arguments.properties
csv = arguments.csv
email = arguments.email
test = arguments.test

"""
Liest Input Parameter 
"""
logging.info('Fisherface training started')
56

57
58
if email:
    sendMail('Fisherface training started')
Arne Gerdes's avatar
Arne Gerdes committed
59

Arne Gerdes's avatar
Arne Gerdes committed
60

61
62
63
64
65
66
def _get_faces_from_emotion(emotion):
    """
    Holt alle Dateien zu einer Emotion aus dem Dataset, mischt sie und teilt sie in ein Trainings- und Prognoseset.
    :param emotion: Die Emotion
    :return: training, prediction
    """
67
    files = glob.glob(dataset_path + '{}/*'.format(emotion))
Arne Gerdes's avatar
Arne Gerdes committed
68
    random.shuffle(files)
Arne Gerdes's avatar
Arne Gerdes committed
69
70
71
72
73
74
75

    """
    Mischt das Dataset in Trainings- und Vergleichsbilder im Verhältnis 80 zu 20 
    """
    training = files[:int(len(files) * 0.8)]
    prediction = files[-int(len(files) * 0.2):]

Arne Gerdes's avatar
Arne Gerdes committed
76
77
    return training, prediction

Arne Gerdes's avatar
Arne Gerdes committed
78

79
80
81
82
83
84
85
86
def image_preprocessing(image):
    """
    Preprocessing der Dateien
    :param item: Bild
    :return:
    """
    img = cv2.imread(image)  # open image
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # convert to grayscale
Arne Gerdes's avatar
Arne Gerdes committed
87
    clahe = cv2.createCLAHE(2.0, (8, 8))
tihmels's avatar
tihmels committed
88
89
    norm = clahe.apply(gray)
    return norm
Arne Gerdes's avatar
Arne Gerdes committed
90

Arne Gerdes's avatar
Arne Gerdes committed
91

Arne Gerdes's avatar
Arne Gerdes committed
92
93
94
95
96
97
def make_sets():
    training_data = []
    training_labels = []
    prediction_data = []
    prediction_labels = []
    for emotion in emotions:
98
        training, prediction = _get_faces_from_emotion(emotion)
Arne Gerdes's avatar
Arne Gerdes committed
99
100
        # Append data to training and prediction list, and generate labels 0-7
        for item in training:
tihmels's avatar
tihmels committed
101
102
            img = image_preprocessing(item)
            training_data.append(img)  # append image array to training data list
Arne Gerdes's avatar
Arne Gerdes committed
103
104
105
            training_labels.append(emotions.index(emotion))

        for item in prediction:  # repeat above process for prediction set
tihmels's avatar
tihmels committed
106
107
            img = image_preprocessing(item)
            prediction_data.append(img)
Arne Gerdes's avatar
Arne Gerdes committed
108
109
110
111
            prediction_labels.append(emotions.index(emotion))

    return training_data, training_labels, prediction_data, prediction_labels

Arne Gerdes's avatar
Arne Gerdes committed
112

Arne Gerdes's avatar
Arne Gerdes committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def run_recognizer():
    training_data, training_labels, prediction_data, prediction_labels = make_sets()

    fishface.train(training_data, np.asarray(training_labels))

    cnt = 0
    correct = 0
    incorrect = 0
    for image in prediction_data:
        pred, conf = fishface.predict(image)
        if pred == prediction_labels[cnt]:
            correct += 1
            cnt += 1
        else:
            incorrect += 1
            cnt += 1
    return ((100 * correct) / (correct + incorrect))

Arne Gerdes's avatar
Arne Gerdes committed
131

Arne Gerdes's avatar
Arne Gerdes committed
132
133
134
"""
Emotions Liste 
"""
tihmels's avatar
tihmels committed
135
fishface = cv2.face.FisherFaceRecognizer_create()
Arne Gerdes's avatar
Arne Gerdes committed
136
metascore = []
tihmels's avatar
tihmels committed
137

Arne Gerdes's avatar
Arne Gerdes committed
138
for i in range(1, iterations + 1):
Arne Gerdes's avatar
Arne Gerdes committed
139
    correct = run_recognizer()
140
    logging.info("{} : {}%".format(i, int(correct)))
Arne Gerdes's avatar
Arne Gerdes committed
141
    metascore.append(correct)
142

Arne Gerdes's avatar
Arne Gerdes committed
143
    if i % (int(iterations / 4)) == 0 and email:
144
145
146
147
148
149
150
151
152
153
154
155
        sendMail(str(i) + ' iterations done', body='up-to-date average: {}%'.format(np.mean(metascore)))

if csv:
    file = open("resources/csv/{}.csv".format('_'.join(properties).lower()), "w")
    for entry in metascore:
        file.write("{}\n".format(int(entry)))

    file.close()

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

if not test:
tihmels's avatar
tihmels committed
156
    fishface.write('resources/models/detection_model.xml')
Arne Gerdes's avatar
Arne Gerdes committed
157

158
159
if email:
    sendMail('Fisherface training finished')