# This class makes the training of the model possible import argparse import glob import logging import random import cv2 import cv2.face import numpy as np import sys from email_service import sendMail logfile = 'logs/process_model.log' # Creates and configures the logger logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M', filename=logfile) # Argument parser allows to specify program parameters parser = argparse.ArgumentParser(description='Process Model Application') 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/', help='path to dataset') 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', 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') arguments = parser.parse_args() logging.debug(arguments) if not arguments.emotions: print('No emotions declared') sys.exit() logging.info('Fisherface training started') if arguments.email: sendMail('Fisherface training started') def _get_faces_from_emotion(emotion): """ 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 """ files = glob.glob(arguments.dataset + '{}/*'.format(emotion)) random.shuffle(files) # Mix the dataset in training and comparison images in the ratio 80 to 20 training = files[:int(len(files) * 0.8)] prediction = files[-int(len(files) * 0.2):] return training, prediction def image_preprocessing(image): """ Preprocessing of the files : param item: picture """ img = cv2.imread(image) # open image gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale clahe = cv2.createCLAHE(2.0, (8, 8)) norm = clahe.apply(gray) return norm def make_sets(): """ Creates the training set :return: The created training data """ training_data = [] training_labels = [] prediction_data = [] prediction_labels = [] for emotion in arguments.emotions: training, prediction = _get_faces_from_emotion(emotion) # Append data to training and prediction list, and generate labels 0-7 for item in training: img = image_preprocessing(item) # append image array to training data list training_data.append(img) training_labels.append(arguments.emotions.index(emotion)) # repeat above process for prediction set for item in prediction: img = image_preprocessing(item) prediction_data.append(img) prediction_labels.append(arguments.emotions.index(emotion)) return training_data, training_labels, prediction_data, prediction_labels def run_recognizer(): """ Performs the actual training with Fisherfaces and Logged the results :return: The correctly recognized faces in percent """ training_data, training_labels, prediction_data, prediction_labels = make_sets() logging.debug('Training...') fishface.train(training_data, np.asarray(training_labels)) cnt = 0 correct = 0 incorrect = 0 logging.debug('Prediction...') 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) # Emotions list fishface = cv2.face.FisherFaceRecognizer_create() metascore = [] # Argument parser for i in range(1, arguments.iterations + 1): correct = run_recognizer() logging.info("{} : {}%".format(i, int(correct))) metascore.append(correct) if arguments.email and i % (int(arguments.iterations / 4)) == 0: sendMail(str(i) + ' iterations done', body='up-to-date average: {}%'.format(np.mean(metascore))) # Argument parser if arguments.csv: file = open("resources/csv/{}.csv".format('_'.join(arguments.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))) # Argument parser if not arguments.test: fishface.write('resources/models/detection_model.xml') logging.info('saved trained classifier') # Argument parser if arguments.email: sendMail('Fisherface training finished', filepath='resources/models/detection_model.xml')