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

3
import argparse
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')
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))
57
    random.shuffle(files)
58

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

63 64
    return training, prediction

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
76

77

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)
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))
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))
97 98 99

    return training_data, training_labels, prediction_data, prediction_labels

100

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

Arne Gerdes's avatar
Arne Gerdes committed
121

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

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

tihmels's avatar
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')
145

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