Commit 9f491647 authored by tihmels's avatar tihmels

Kommentare geschrieben

parent 53c5fa46
class RingBuffer:
"""
Simple fixed-size ringbuffer
"""
def __init__(self, size):
self.data = [None for i in range(size)]
def append(self, x):
"""
Append an element
:param x: the element
:return:
"""
self.data.pop(0)
self.data.append(x)
def get(self):
"""
return array with elements
:return: array with elements
"""
return self.data
......@@ -7,6 +7,14 @@ from email.mime.text import MIMEText
def sendMail(subject, to='tjado.ihmels@uni-oldenburg.de', body='', filepath=''):
"""
For a longer runtime on a remote server emails serve as feedback
:param subject: subject
:param to: email adress
:param body: email text
:param filepath: optional attachment. For example a logfile
:return:
"""
fromaddr = "projectmood18@gmail.com"
msg = MIMEMultipart()
......
"""
Diese Klasse enthält Funktionen zum Bearbeiten von Bildern in OpenCV und PIL's Image.
PIL => PIL ist die Python-Imaging-Bibliothek
Utility Class for working with images in OpenCV
"""
import cv2
import numpy as np
......@@ -9,28 +8,28 @@ from PIL import Image
def image_as_nparray(image):
"""
Konvertiert PIL Image in ein Numpy Array
Convert PIL Image to Numpy array
:param image: PIL's Image object.
:return: Numpy Array der Bilder.
:return: Numpy Array
"""
return np.asarray(image)
def nparray_as_image(nparray, mode='RGB'):
"""
Konvertiert Numpy Array der Bilder in PIL Image
Convert numpy array to PIL image
:param nparray: Numpy's array of image.
:param mode: Modus der Umwandlung. Standardeinstellung ist "RGB".
:return: PIL Image mit dem Bild
:param mode: transformation mode
:return: PIL image
"""
return Image.fromarray(np.asarray(np.clip(nparray, 0, 255), dtype='uint8'), mode)
def load_image(source_path):
"""
Lädt das RGB-Bild und konvertiert es in Graustufen.
:param source_path: Quellpfad des Bildes.
:return: Bild wird vom Pfad geladen und in Graustufen konvertiert.
Load the RGB image and convert to grayscale
:param source_path: source path to image
:return: converted image
"""
source_image = cv2.imread(source_path)
return cv2.cvtColor(source_image, cv2.COLOR_BGR2GRAY)
......@@ -38,24 +37,23 @@ def load_image(source_path):
def draw_with_alpha(source_image, image_to_draw, coordinates):
"""
Zeichnet ein teilweise transparentes Bild über ein anderes Bild.
:param source_image: Bild zum Übermalen.
:param image_to_draw: Bild zum Zeichnen.
:param coordinates: : Koordinaten um ein Bild zu zeichnen. Tupel von x, y, Breite und Höhe.
Draw a partially transparent image on another image
:param source_image: Background image
:param image_to_draw: Overdraw image
:param coordinates: : Coordinates to which the image should be drawn
"""
x, y, w, h = coordinates
image_to_draw = image_to_draw.resize((h, w), Image.ANTIALIAS)
image_array = image_as_nparray(image_to_draw)
for c in range(0, 3):
source_image[y:y + h, x:x + w, c] = image_array[:, :, c] * (image_array[:, :, 3] / 255.0) \
+ source_image[y:y + h, x:x + w, c] * (1.0 - image_array[:, :, 3] / 255.0)
source_image[y:y + h, x:x + w, c] = image_array[:, :, c] * (image_array[:, :, 3] / 255.0) + source_image[y:y + h, x:x + w, c] * (1.0 - image_array[:, :, 3] / 255.0)
def draw_img(source_image, image_to_draw, coordinates):
"""
Zeichnet ein teilweise transparentes Bild über ein anderes Bild.
:param source_image: Bild zum Übermalen.
:param image_to_draw: Bild zum Zeichnen.
:param coordinates: : Koordinaten um ein Bild zu zeichnen. Tupel von x, y, Breite und Höhe.
Draw an image to another image
:param source_image: Background image
:param image_to_draw: Overdraw image
:param coordinates: : Coordinates to which the image should be drawn
"""
x, y, w, h = coordinates
image_to_draw = image_to_draw.resize((h, w), Image.ANTIALIAS)
......
......@@ -5,7 +5,6 @@ import glob
import logging
import random
import cv2
import cv2.face
import numpy as np
import sys
......
......@@ -15,10 +15,8 @@ logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(name)-12s %(leve
datefmt='%m-%d %H:%M',
filename=logfile,
filemode='w')
"""
Argument Parser erlaubt Parameter für die Verarbeitung anzugeben.
"""
# Argument Parser erlaubt Parameter für die Verarbeitung anzugeben.
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')
......@@ -41,6 +39,7 @@ parser.add_argument('-x', '--email', action='store_true', help='activate email n
arguments = parser.parse_args()
logging.debug(arguments)
# if no emotions are declared, exit
if not arguments.emotions:
print('No emotions declared')
sys.exit()
......@@ -54,6 +53,7 @@ minNeighbors = arguments.minNeighbors
minSize = arguments.minSize
email = arguments.email
# check if files exist at destination path and ask the user to continue
if len(os.listdir(dataset_path)) > 0:
delete_data = input(
'Im Dataset befinden sich Dateien. Durch diesen Vorgang werden die existierenden Daten gelöscht. Fortfahren (y/n): ')
......@@ -66,14 +66,20 @@ if len(os.listdir(dataset_path)) > 0:
print('process aborted by user')
sys.exit()
# count some values for debugging
totalFiles: int = 0
totalFaces: int = 0
undetected: list = []
def detect_faces(emotion):
"""
Holt alle Dateien zu einer Emotion aus dem sorted_set
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:
"""
# get all files from an emotion folder
files = glob.glob(source_path + '{}/*'.format(emotion))
global undetected
......@@ -84,15 +90,17 @@ def detect_faces(emotion):
file_name_number = 0
for f in files:
frame = cv2.imread(f) # Open image
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Convert image to grayscale
frame = cv2.imread(f) # open image
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # convert image to grayscale
# extract face coordinates via haarcascade
facefeatures = locate_faces(gray, scaleFactor, minNeighbors, (minSize, minSize))
if facefeatures is '':
logging.info('No face detected in ' + f)
undetected.append(f)
if len(undetected) % 200 == 0 and email:
# could indicate that something went wrong, check the log
sendMail('Already ' + str(len(undetected)) + ' undetected faces', filepath=logfile)
else:
# Cut and save face
......@@ -100,9 +108,10 @@ def detect_faces(emotion):
totalFaces += 1
gray = gray[y:y + h, x:x + w] # Cut the frame to size
try:
save_file = dataset_path + '{}/{}{}.jpg'.format(emotion, arguments.prefix, file_name_number)
out = cv2.resize(gray, (resizeFactor, resizeFactor)) # Resize face so all images have same size
success = cv2.imwrite(save_file, out) # Write image
save_file = dataset_path + '{}/{}{}.jpg'.format(emotion, arguments.prefix,
file_name_number) # filepath + name
success = cv2.imwrite(save_file, out) # Write image to filesystem
if not success:
logging.error('Problem while writing file ' + str(f) + ' occurred...')
if email:
......@@ -118,11 +127,11 @@ def detect_faces(emotion):
file_name_number += 1
for emotion in emotions:
# create emotion folder if not exist
if not os.path.exists(dataset_path + emotion):
os.makedirs(dataset_path + emotion)
detect_faces(emotion) # Call functional
detect_faces(emotion) # sort faces into dataset
logging.info('{} faces in {} files found'.format(totalFaces, totalFiles))
logging.info('In {} files no face could be detected'.format(totalFiles - totalFaces))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment