sorted_set_facedetector.py 6.2 KB
Newer Older
Arne Gerdes's avatar
Arne Gerdes committed
1
import argparse
Arne Gerdes's avatar
Arne Gerdes committed
2
import glob
3
import logging
Arne Gerdes's avatar
Arne Gerdes committed
4
import os
5
6
7
import shutil
import sys

Arne Gerdes's avatar
Arne Gerdes committed
8
import cv2
9
from email_service import sendMail
tihmels's avatar
tihmels committed
10
from face_detect import locate_faces
Arne Gerdes's avatar
Arne Gerdes committed
11

12
13
14
logfile = 'logs/sorted_set_facedetector.log'

logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
15
                    datefmt='%m-%d %H:%M',
16
                    filename=logfile,
17
                    filemode='w')
18

tihmels's avatar
tihmels committed
19
# Argument Parser erlaubt Parameter für die Verarbeitung anzugeben.
tihmels's avatar
tihmels committed
20
21
22
23
24
25
26
27
28
parser = argparse.ArgumentParser(description='Dataset Preprocessor')
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('-s', '--source', action='store', dest='img_source', default='resources/img_data/sorted_set/',
29
                    help='path to image source')
tihmels's avatar
tihmels committed
30
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')
tihmels's avatar
tihmels committed
32
33
parser.add_argument('-r', '--resize', action='store', dest='resize', default=250, type=int, help='resize factor')
parser.add_argument('-c', '--scale', action='store', dest='scaleFactor', default=1.1, type=float,
tihmels's avatar
tihmels committed
34
35
36
37
                    help='scale factor (ViolaJ)')
parser.add_argument('-n', '--minneighbors', action='store', dest='minNeighbors', default=6, type=int, help='min neighbors (ViolaJ)')
parser.add_argument('-m', '--minsize', action='store', dest='minSize', default=50, type=int, help='min size (ViolaJ)')
parser.add_argument('-p', '--prefix', action='store', dest='prefix', default='', help='prefix for files')
tihmels's avatar
tihmels committed
38
parser.add_argument('-x', '--email', action='store_true', help='activate email notifications')
39
arguments = parser.parse_args()
40
41
logging.debug(arguments)

tihmels's avatar
tihmels committed
42
# if no emotions are declared, exit
43
44
45
46
if not arguments.emotions:
    print('No emotions declared')
    sys.exit()

47
48
49
50
51
52
53
54
source_path = arguments.img_source
dataset_path = arguments.dataset
resizeFactor = arguments.resize
emotions = arguments.emotions
scaleFactor = arguments.scaleFactor
minNeighbors = arguments.minNeighbors
minSize = arguments.minSize
email = arguments.email
55

tihmels's avatar
tihmels committed
56
# check if files exist at destination path and ask the user to continue
tihmels's avatar
tihmels committed
57
58
if len(os.listdir(dataset_path)) > 0:
    delete_data = input(
59
        'Im Dataset befinden sich Dateien. Durch diesen Vorgang werden die existierenden Daten gelöscht. Fortfahren (y/n): ')
60

tihmels's avatar
tihmels committed
61
62
63
64
    if delete_data == 'y':
        dir = [f for f in os.listdir(dataset_path) if os.path.isdir(os.path.join(dataset_path, f))]
        for d in dir:
            shutil.rmtree(os.path.join(dataset_path, d))
65
    else:
tihmels's avatar
tihmels committed
66
        print('process aborted by user')
67
        sys.exit()
Arne Gerdes's avatar
Arne Gerdes committed
68

tihmels's avatar
tihmels committed
69
# count some values for debugging
tihmels's avatar
tihmels committed
70
71
72
73
totalFiles: int = 0
totalFaces: int = 0
undetected: list = []

Arne Gerdes's avatar
Arne Gerdes committed
74
def detect_faces(emotion):
Arne Gerdes's avatar
Arne Gerdes committed
75
    """
tihmels's avatar
tihmels committed
76
77
78
79
    This function iterates the presorted set from one emotion and generates the dataset for recognition
    Haarcascade locates the face and with the coordinates the pictures will be resized and converted to grayscale
    :param emotion: the emotion
    :return:
Arne Gerdes's avatar
Arne Gerdes committed
80
    """
tihmels's avatar
tihmels committed
81
82

    # get all files from an emotion folder
83
    files = glob.glob(source_path + '{}/*'.format(emotion))
84
85
86
87

    global undetected
    global totalFaces
    global totalFiles
Arne Gerdes's avatar
Arne Gerdes committed
88

89
    logging.info("Found {} {} files".format(len(files), emotion))
90

tihmels's avatar
tihmels committed
91
    file_name_number = 0
Arne Gerdes's avatar
Arne Gerdes committed
92
    for f in files:
tihmels's avatar
tihmels committed
93
94
        frame = cv2.imread(f)  # open image
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # convert image to grayscale
Arne Gerdes's avatar
Arne Gerdes committed
95

tihmels's avatar
tihmels committed
96
        # extract face coordinates via haarcascade
97
        facefeatures = locate_faces(gray, scaleFactor, minNeighbors, (minSize, minSize))
tihmels's avatar
tihmels committed
98
99

        if facefeatures is '':
tihmels's avatar
tihmels committed
100
            logging.info('No face detected in ' + f)
101
            undetected.append(f)
102
            if len(undetected) % 200 == 0 and email:
tihmels's avatar
tihmels committed
103
                # could indicate that something went wrong, check the log
tihmels's avatar
tihmels committed
104
                sendMail('Already ' + str(len(undetected)) + ' undetected faces', filepath=logfile)
105
106
107
108
109
110
        else:
            # Cut and save face
            for (x, y, w, h) in facefeatures:  # get coordinates and size of rectangle containing face
                totalFaces += 1
                gray = gray[y:y + h, x:x + w]  # Cut the frame to size
                try:
111
                    out = cv2.resize(gray, (resizeFactor, resizeFactor))  # Resize face so all images have same size
tihmels's avatar
tihmels committed
112
113
114
                    save_file = dataset_path + '{}/{}{}.jpg'.format(emotion, arguments.prefix,
                                                                    file_name_number)  # filepath + name
                    success = cv2.imwrite(save_file, out)  # Write image to filesystem
115
                    if not success:
tihmels's avatar
tihmels committed
116
                        logging.error('Problem while writing file ' + str(f) + ' occurred...')
117
                        if email:
Arne Gerdes's avatar
Arne Gerdes committed
118
                            sendMail('Problem while writing file',
tihmels's avatar
tihmels committed
119
                                     body=str(f) + ' to ' + save_file)
120
                except:
121
                    logging.error('Some error with ' + f)
122
                    if email:
tihmels's avatar
tihmels committed
123
                        sendMail('Some error occured', body=f, filepath=logfile)
124
                    pass  # If error, pass file
125

tihmels's avatar
tihmels committed
126
        totalFiles += 1  # Increment image number
tihmels's avatar
tihmels committed
127
        file_name_number += 1
128

129
for emotion in emotions:
tihmels's avatar
tihmels committed
130
    # create emotion folder if not exist
131
132
    if not os.path.exists(dataset_path + emotion):
        os.makedirs(dataset_path + emotion)
Arne Gerdes's avatar
Arne Gerdes committed
133

tihmels's avatar
tihmels committed
134
    detect_faces(emotion)  # sort faces into dataset
135

136
137
logging.info('{} faces in {} files found'.format(totalFaces, totalFiles))
logging.info('In {} files no face could be detected'.format(totalFiles - totalFaces))
tihmels's avatar
tihmels committed
138

139
for f in undetected:
140
141
    logging.info(f)

142
143
if email:
    sendMail('Facedetector finished notification', filepath=logfile)