def add_extra_images(self): """ If --extra flag exists, adds images from extra-images dir to dataset :return: tuple of list dataset images, dataset labels """ detector = Detector() print('\nAdding extra images...') for emotion_index, emotion in enumerate(EMOTIONS): print('\nEmotion', emotion) files = glob.glob('{}\\{}\\*'.format(EXTRA_DIR, emotion)) total = len(files) for i, f in enumerate(files): image = cv2.imread(f) detected_faces = detector.detect_faces(image) for face in detected_faces: self.images.append(face) self.emotions.append( PrepareData._emotion_to_vec(emotion_index)) self.count.append(emotion_index) print('Progress: {}/{} {:.2f}%'.format(i, total, i * 100.0 / total))
class Recognizer: """ Class of recognizer. Recognize emotions on image using trained model """ def __init__(self): self.detector = Detector() self.model = TrainNetwork().load_trained_model() self.cap = cv2.VideoCapture(0) if not self.cap.isOpened(): print('Webcam is not open.') exit() def recognize(self, frame): """ Recognize emotions on frame for each face :param frame: input frame from webcam :return: tuple of list faces and predictions """ detected_faces = self.detector.detect_faces(frame) predictions = [] for face in detected_faces: face = face.reshape([-1, IMG_SIZE, IMG_SIZE, 1]) prediction = self.model.predict(face) print(EMOTIONS[np.argmax(prediction[0])]) predictions.append(prediction[0]) return detected_faces, predictions def run(self): """ Gets frames from webcam and push it to recognizer Stops by CTRL+C :return: """ predictions = [] times = [] try: while self.cap.isOpened(): sleep(0.5) _, frame = self.cap.read() faces, preds = self.recognize(frame) for f, p in zip(faces, preds): predictions.append(p) times.append(datetime.now().time()) Recognizer._save_recognized_image(frame, p, datetime.now()) except KeyboardInterrupt: self.cap.release() return times, predictions @staticmethod def _save_recognized_image(face, prediction, dt): """ Saves image from webcam with face(user data) :param face: face image :param prediction: emotion prediction :param dt: datetime :return: """ if not os.path.exists(os.path.join(os.getcwd(), USER_DATA_DIR)): os.mkdir(USER_DATA_DIR) emotion = EMOTIONS[np.argmax(prediction)]
class PrepareData: """ Class for prepare dataset """ def __init__(self): self.images = [] self.emotions = [] self.count = [] self.detector = Detector() def create_dataset_from_csv(self): """ Create dataset from fer2013 dataset csv file :return: tuple of list dataset images, dataset labels """ print('\nCreating dataset...') data = pd.read_csv(CSV_FILE_NAME) total = data.shape[0] for i, row in data.iterrows(): image = PrepareData._data_to_image(row['pixels']) emotion = PrepareData._emotion_to_vec(row['emotion']) detected_faces = self.detector.detect_faces(image, fer2013_image=True) for face in detected_faces: self.images.append(face) self.emotions.append(emotion) self.count.append(row['emotion']) print('Progress: {}/{} {:.2f}%'.format(i, total, i * 100.0 / total)) return self.images, self.emotions, self.count def add_extra_images(self): """ If --extra flag exists, adds images from extra-images dir to dataset :return: tuple of list dataset images, dataset labels """ detector = Detector() print('\nAdding extra images...') for emotion_index, emotion in enumerate(EMOTIONS): print('\nEmotion', emotion) files = glob.glob('{}\\{}\\*'.format(EXTRA_DIR, emotion)) total = len(files) for i, f in enumerate(files): image = cv2.imread(f) detected_faces = detector.detect_faces(image) for face in detected_faces: self.images.append(face) self.emotions.append( PrepareData._emotion_to_vec(emotion_index)) self.count.append(emotion_index) print('Progress: {}/{} {:.2f}%'.format(i, total, i * 100.0 / total)) @staticmethod def _data_to_image(data): """ Private method. Convert csv row of pixels to image :param data: row of pixels from csv file :return: """ data_image = [int(pixel) for pixel in data.split(' ')] image = np.asarray(data_image).reshape(IMG_SIZE, IMG_SIZE) image = cv2.resize(image.astype('uint8'), (IMG_SIZE, IMG_SIZE)) # image = image.astype('float32') / 255. return image @staticmethod def _emotion_to_vec(x): """ Private method. Convert num of emotion to emotions labels array([0., 0., 0. ,1., 0., 0., 0.,]) :param x: num of emotion :return: array """ d = np.zeros(len(EMOTIONS)) d[x] = 1.0 return d