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')