├── emotion_detector ├── requirements.txt ├── .gitignore ├── .DS_Store ├── plot.png ├── __pycache__ │ ├── plot.cpython-38.pyc │ ├── plot.cpython-39.pyc │ ├── config.cpython-38.pyc │ ├── config.cpython-39.pyc │ ├── model.cpython-38.pyc │ ├── model.cpython-39.pyc │ ├── dataset_loader.cpython-38.pyc │ └── dataset_loader.cpython-39.pyc ├── model.py ├── config.py ├── plot.py ├── main.py └── dataset_loader.py ├── .DS_Store └── README.md /emotion_detector/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | pandas 3 | pillow 4 | tqdm -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/.DS_Store -------------------------------------------------------------------------------- /emotion_detector/.gitignore: -------------------------------------------------------------------------------- 1 | data/ 2 | fer2013/ 3 | model.h5 4 | haarcascade_frontalface_default.xml 5 | __pycache__ 6 | -------------------------------------------------------------------------------- /emotion_detector/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/.DS_Store -------------------------------------------------------------------------------- /emotion_detector/plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/plot.png -------------------------------------------------------------------------------- /emotion_detector/__pycache__/plot.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/plot.cpython-38.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/plot.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/plot.cpython-39.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/config.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/config.cpython-38.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/config.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/config.cpython-39.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/model.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/model.cpython-38.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/model.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/model.cpython-39.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/dataset_loader.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/dataset_loader.cpython-38.pyc -------------------------------------------------------------------------------- /emotion_detector/__pycache__/dataset_loader.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anathonic/Artificial-Intelligence-Methods-Final-Project/HEAD/emotion_detector/__pycache__/dataset_loader.cpython-39.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Artificial Intelligence methods-final project 2 |
3 | Dataset: 4 | https://www.kaggle.com/c/challenges-in-representation-learning-facial-expression-recognition-challenge/data?select=fer2013.tar.gz 5 |
6 | Haarcascades: 7 | https://github.com/opencv/opencv/tree/master/data/haarcascades 8 | -------------------------------------------------------------------------------- /emotion_detector/model.py: -------------------------------------------------------------------------------- 1 | from tensorflow.keras.models import Sequential 2 | from tensorflow.keras.layers import Dense, Dropout, Flatten 3 | from tensorflow.keras.layers import Conv2D 4 | from tensorflow.keras.layers import MaxPooling2D 5 | # tworzenie modelu 6 | model = Sequential() 7 | 8 | model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1))) 9 | model.add(Conv2D(64, kernel_size=(3, 3), activation='relu')) 10 | model.add(MaxPooling2D(pool_size=(2, 2))) 11 | model.add(Dropout(0.25)) 12 | 13 | model.add(Conv2D(128, kernel_size=(3, 3), activation='relu')) 14 | model.add(MaxPooling2D(pool_size=(2, 2))) 15 | model.add(Conv2D(128, kernel_size=(3, 3), activation='relu')) 16 | model.add(MaxPooling2D(pool_size=(2, 2))) 17 | model.add(Dropout(0.25)) 18 | 19 | model.add(Flatten()) 20 | model.add(Dense(1024, activation='relu')) 21 | model.add(Dropout(0.5)) 22 | model.add(Dense(7, activation='softmax')) -------------------------------------------------------------------------------- /emotion_detector/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | from tensorflow.keras.preprocessing.image import ImageDataGenerator 4 | 5 | os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 6 | 7 | # linia argumentów 8 | ap = argparse.ArgumentParser() 9 | ap.add_argument("--mode",help="train/start") 10 | mode = ap.parse_args().mode 11 | 12 | 13 | # foldery z datasetem 14 | train_dir = 'data/train' 15 | val_dir = 'data/test' 16 | 17 | num_train = 28709 18 | num_val = 7178 19 | batch_size = 64 20 | num_epoch = 50 21 | 22 | train_datagen = ImageDataGenerator(rescale=1./255) 23 | val_datagen = ImageDataGenerator(rescale=1./255) 24 | 25 | train_generator = train_datagen.flow_from_directory( 26 | train_dir, 27 | target_size=(48,48), 28 | batch_size=batch_size, 29 | color_mode="grayscale", 30 | class_mode='categorical') 31 | 32 | validation_generator = val_datagen.flow_from_directory( 33 | val_dir, 34 | target_size=(48,48), 35 | batch_size=batch_size, 36 | color_mode="grayscale", 37 | class_mode='categorical') 38 | 39 | -------------------------------------------------------------------------------- /emotion_detector/plot.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | def plot_model_history(model_history): 5 | fig, axs = plt.subplots(1,2,figsize=(15,5)) 6 | # historia dokładności 7 | axs[0].plot(range(1,len(model_history.history['accuracy'])+1),model_history.history['accuracy']) 8 | axs[0].plot(range(1,len(model_history.history['val_accuracy'])+1),model_history.history['val_accuracy']) 9 | axs[0].set_title('Model Accuracy') 10 | axs[0].set_ylabel('Accuracy') 11 | axs[0].set_xlabel('Epoch') 12 | axs[0].set_xticks(np.arange(1,len(model_history.history['accuracy'])+1),len(model_history.history['accuracy'])/10) 13 | axs[0].legend(['train', 'val'], loc='best') 14 | # historia straty 15 | axs[1].plot(range(1,len(model_history.history['loss'])+1),model_history.history['loss']) 16 | axs[1].plot(range(1,len(model_history.history['val_loss'])+1),model_history.history['val_loss']) 17 | axs[1].set_title('Model Loss') 18 | axs[1].set_ylabel('Loss') 19 | axs[1].set_xlabel('Epoch') 20 | axs[1].set_xticks(np.arange(1,len(model_history.history['loss'])+1),len(model_history.history['loss'])/10) 21 | axs[1].legend(['train', 'val'], loc='best') 22 | fig.savefig('plot.png') 23 | plt.show() -------------------------------------------------------------------------------- /emotion_detector/main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | from tensorflow.keras.optimizers import Adam 4 | from model import model 5 | from config import * 6 | from plot import plot_model_history 7 | 8 | 9 | 10 | # trenowanie modelu 11 | if mode == "train": 12 | model.compile(loss='categorical_crossentropy',optimizer=Adam(learning_rate=0.0001, decay=1e-6),metrics=['accuracy']) 13 | model_info = model.fit( 14 | train_generator, 15 | steps_per_epoch=num_train // batch_size, 16 | epochs=num_epoch, 17 | validation_data=validation_generator, 18 | validation_steps=num_val // batch_size) 19 | plot_model_history(model_info) 20 | model.save_weights('model.h5') 21 | 22 | # załadowanie modelu 23 | elif mode == "start": 24 | model.load_weights('model.h5') 25 | 26 | # zapobieganie niepotrzebnym komunikatom logowania 27 | cv2.ocl.setUseOpenCL(False) 28 | 29 | # foldery z emocjami 30 | emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"} 31 | 32 | # start kamery 33 | cap = cv2.VideoCapture(0) 34 | while True: 35 | # haarcascade do znalezienia twarzy i wyrysowania kwadratu 36 | ret, frame = cap.read() 37 | if not ret: 38 | break 39 | facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 40 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 41 | faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5) 42 | 43 | for (x, y, w, h) in faces: 44 | cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (0, 0, 255), 2) 45 | roi_gray = gray[y:y + h, x:x + w] 46 | cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0) 47 | prediction = model.predict(cropped_img) 48 | maxindex = int(np.argmax(prediction)) 49 | cv2.putText(frame, emotion_dict[maxindex], (x+80, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA) 50 | 51 | cv2.imshow('Video', cv2.resize(frame,(1600,1600),interpolation = cv2.INTER_CUBIC)) 52 | if cv2.waitKey(1) & 0xFF == ord('q'): 53 | break 54 | 55 | cap.release() 56 | cv2.destroyAllWindows() 57 | -------------------------------------------------------------------------------- /emotion_detector/dataset_loader.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | from PIL import Image 4 | from tqdm import tqdm 5 | import os 6 | 7 | # konwersja string - integer 8 | def atoi(s): 9 | n = 0 10 | for i in s: 11 | n = n*10 + ord(i) - ord("0") 12 | return n 13 | 14 | # tworzenie folderów 15 | main_dirs = ['test','train'] 16 | emotions = ['angry', 'disgusted', 'fearful', 'happy', 'sad', 'surprised', 'neutral'] 17 | os.makedirs('data', exist_ok=True) 18 | for dir in main_dirs: 19 | os.makedirs(os.path.join('data',dir), exist_ok=True) 20 | for emotion in emotions: 21 | os.makedirs(os.path.join('data',dir,emotion), exist_ok=True) 22 | 23 | # do zliczania plików png w kazdej kategorii 24 | angry = 0 25 | angry_test = 0 26 | disgusted = 0 27 | disgusted_test = 0 28 | fearful = 0 29 | fearful_test = 0 30 | happy = 0 31 | happy_test = 0 32 | sad = 0 33 | sad_test = 0 34 | surprised = 0 35 | surprised_test = 0 36 | neutral = 0 37 | neutral_test = 0 38 | 39 | 40 | # załadowanie pliku csv, obliczenie Training 41 | data = pd.read_csv('./fer2013/fer2013.csv') 42 | #print(data['Usage'].value_counts()) 43 | train_count = int(data['Usage'].value_counts()[0:1]) 44 | val_count = num_val = int(data['Usage'].value_counts()[1:2])+int(data['Usage'].value_counts()[2:3]) 45 | png = np.zeros((48,48),dtype=np.uint8) 46 | bytes = 48*48 47 | print("Saving images...") 48 | 49 | # czytanie pliku csv linia po linii 50 | for i in tqdm(range(len(data))): 51 | txt = data['pixels'][i] 52 | words = txt.split() 53 | 54 | # rozmiar obrazów 48x48 55 | for j in range(bytes): 56 | xind = j // 48 57 | yind = j % 48 58 | png[xind][yind] = atoi(words[j]) 59 | 60 | img = Image.fromarray(png) 61 | 62 | # train - czyli wlatuje Training (28709) 63 | if i < train_count: 64 | if data['emotion'][i] == 0: 65 | img.save('data/train/angry/im'+str(angry)+'.png') 66 | angry += 1 67 | elif data['emotion'][i] == 1: 68 | img.save('data/train/disgusted/im'+str(disgusted)+'.png') 69 | disgusted += 1 70 | elif data['emotion'][i] == 2: 71 | img.save('data/train/fearful/im'+str(fearful)+'.png') 72 | fearful += 1 73 | elif data['emotion'][i] == 3: 74 | img.save('data/train/happy/im'+str(happy)+'.png') 75 | happy += 1 76 | elif data['emotion'][i] == 4: 77 | img.save('data/train/sad/im'+str(sad)+'.png') 78 | sad += 1 79 | elif data['emotion'][i] == 5: 80 | img.save('data/train/surprised/im'+str(surprised)+'.png') 81 | surprised += 1 82 | elif data['emotion'][i] == 6: 83 | img.save('data/train/neutral/im'+str(neutral)+'.png') 84 | neutral += 1 85 | 86 | # test - czyli wlatuje PublicTest i PrivateTest (3589 x 2) 87 | else: 88 | if data['emotion'][i] == 0: 89 | img.save('data/test/angry/im'+str(angry_test)+'.png') 90 | angry_test += 1 91 | elif data['emotion'][i] == 1: 92 | img.save('data/test/disgusted/im'+str(disgusted_test)+'.png') 93 | disgusted_test += 1 94 | elif data['emotion'][i] == 2: 95 | img.save('data/test/fearful/im'+str(fearful_test)+'.png') 96 | fearful_test += 1 97 | elif data['emotion'][i] == 3: 98 | img.save('data/test/happy/im'+str(happy_test)+'.png') 99 | happy_test += 1 100 | elif data['emotion'][i] == 4: 101 | img.save('data/test/sad/im'+str(sad_test)+'.png') 102 | sad_test += 1 103 | elif data['emotion'][i] == 5: 104 | img.save('data/test/surprised/im'+str(surprised_test)+'.png') 105 | surprised_test += 1 106 | elif data['emotion'][i] == 6: 107 | img.save('data/test/neutral/im'+str(neutral_test)+'.png') 108 | neutral_test += 1 109 | 110 | print("Your Dataset is Ready!") 111 | --------------------------------------------------------------------------------