process_model.py 5.27 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 8
import random
import cv2
tihmels's avatar
tihmels committed
9
import cv2.face
Arne Gerdes's avatar
Arne Gerdes committed
10
import numpy as np
11 12
import sys

13 14 15 16
from email_service import sendMail

logfile = 'logs/process_model.log'

17
# Erstellt und konfiguriert den Logger
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

22
# Argument Parser erlaubt Programmparameter anzugeben
23
parser = argparse.ArgumentParser(description='Process Model Application')
tihmels's avatar
tihmels committed
24 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')
parser.add_argument('-d', '--dataset', action='store', dest='dataset', default='resources/img_data/dataset/',
Arne Gerdes's avatar
Arne Gerdes committed
32
                    help='path to dataset')
33 34
parser.add_argument('-i' '--iterations', action='store', dest='iterations', type=int, default=30,
                    help='number of iterations')
tihmels's avatar
tihmels committed
35
parser.add_argument('-p', '--properties', nargs='+', dest='properties', help='pre-processing steps for logging')
36 37 38
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')
39 40 41
arguments = parser.parse_args()
logging.debug(arguments)

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

logging.info('Fisherface training started')
47

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

51 52 53 54 55 56
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
    """
57
    files = glob.glob(arguments.dataset + '{}/*'.format(emotion))
Arne Gerdes's avatar
Arne Gerdes committed
58
    random.shuffle(files)
Arne Gerdes's avatar
Arne Gerdes committed
59 60 61 62 63 64 65

    """
    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
66 67
    return training, prediction

Arne Gerdes's avatar
Arne Gerdes committed
68

69 70 71 72 73 74 75 76
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
77
    clahe = cv2.createCLAHE(2.0, (8, 8))
tihmels's avatar
tihmels committed
78 79
    norm = clahe.apply(gray)
    return norm
Arne Gerdes's avatar
Arne Gerdes committed
80

Arne Gerdes's avatar
Arne Gerdes committed
81

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

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

    return training_data, training_labels, prediction_data, prediction_labels

Arne Gerdes's avatar
Arne Gerdes committed
102

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

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

    cnt = 0
    correct = 0
    incorrect = 0
tihmels's avatar
tihmels committed
112
    logging.debug('Prediction...')
Arne Gerdes's avatar
Arne Gerdes committed
113 114 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
    return ((100 * correct) / (correct + incorrect))

Arne Gerdes's avatar
Arne Gerdes committed
123

Arne Gerdes's avatar
Arne Gerdes committed
124 125 126
"""
Emotions Liste 
"""
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
for i in range(1, arguments.iterations + 1):
Arne Gerdes's avatar
Arne Gerdes committed
131
    correct = run_recognizer()
132
    logging.info("{} : {}%".format(i, int(correct)))
Arne Gerdes's avatar
Arne Gerdes committed
133
    metascore.append(correct)
134

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

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

    file.close()

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

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
if arguments.email:
151
    sendMail('Fisherface training finished')