-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathevaluate_emotion_detector.py
138 lines (113 loc) · 9.56 KB
/
evaluate_emotion_detector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from PIL import Image
import numpy as np
import pandas as pd
import os
import pandas as pd
import cv2
import pickle
import argparse
from tqdm import tqdm
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix
import seaborn as sn
import matplotlib.pyplot as plt
from utils.triangular_warper import triangular_warp
from sklearn.preprocessing import normalize
def get_images(images_dir):
print("Reading the images inside the dataset.")
images = []
for image_file in os.listdir(images_dir):
image_path = os.path.join(images_dir, image_file)
image = Image.open(image_path).convert('L') # L: greyscale image
images.append(image)
images = np.stack(images)
return images
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--dataset', type=str, default="ck_plus_setup_1", help='Name of the dataset.')
parser.add_argument('--dataset_dir', type=str, default="./datasets/ck_plus/setup_1/processed", help='Directory of the dataset that the regressor is trained on.')
parser.add_argument('--output_dir', type=str, default="./output", help='Where the results will be saved.')
parser.add_argument('--model_dir', type=str, default="./saved_models", help='Where the trained model will be loaded.')
parser.add_argument('--model_name', type=str, default="emotion_detector_svm_pca0.98", help='Name of the model in the saved models\' directory.')
args = parser.parse_args()
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_svm_pca0.98 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_decision_tree_pca0.98 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_knn_pca0.98 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_logistic_regressor_pca0.98 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_svm_pca0.5 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_decision_tree_pca0.5 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_knn_pca0.5 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_1 --model_name emotion_detector_logistic_regressor_pca0.5 --dataset_dir ./datasets/ck_plus/setup_1/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_svm_pca0.98 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_decision_tree_pca0.98 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_knn_pca0.98 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_logistic_regressor_pca0.98 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_svm_pca0.5 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_decision_tree_pca0.5 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_knn_pca0.5 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
# python evaluate_emotion_detector.py --dataset ck_plus_setup_2 --model_name emotion_detector_logistic_regressor_pca0.5 --dataset_dir ./datasets/ck_plus/setup_2/processed --output_dir ./output --model_dir ./saved_models
model_output_dir = os.path.join(args.output_dir, args.dataset, args.model_name)
os.makedirs(model_output_dir,exist_ok=True)
model_load_path= os.path.join(args.model_dir, args.dataset, f"{args.model_name}.model")
test_images_dir = os.path.join(args.dataset_dir, "test", "images")
test_emotions_path = os.path.join(args.dataset_dir, "test", "emotions.csv")
images = get_images(test_images_dir)
df_emotions_test = pd.read_csv(test_emotions_path, index_col=0)
print("Loading the classifier model.")
with open(model_load_path, 'rb') as model_file:
classifier_model = pickle.load(model_file)
z_fill_length = len(str(len(images)))
emotions_output_dir = os.path.join(model_output_dir, "emotion_results")
os.makedirs(emotions_output_dir,exist_ok=True)
convex_hulls_output_dir = os.path.join(model_output_dir, "convex_hulls")
os.makedirs(convex_hulls_output_dir,exist_ok=True)
normalized_images_output_dir = os.path.join(model_output_dir, "normalized_images")
os.makedirs(normalized_images_output_dir,exist_ok=True)
triangle_images_output_dir = os.path.join(model_output_dir, "triangle_images")
os.makedirs(triangle_images_output_dir,exist_ok=True)
print("Image processing visualization is started.")
landmarks_list = [classifier_model.landmark_detector.predict(image) for image in tqdm(images,desc='Extracting the landmark points',total=len(images))]
convex_hull_images, triangle_images, warped_images = triangular_warp(images, landmarks_list, classifier_model.landmark_detector.mean_landmarks, visualize=True)
for index_id, (convex_hull_image, triangle_image, warped_image) in tqdm(enumerate(zip(convex_hull_images, triangle_images, warped_images)),desc=f'Saving the processed images',total=len(convex_hull_images)):
image_name = str(df_emotions_test.index[index_id]).zfill(z_fill_length)
image_output_path = os.path.join(convex_hulls_output_dir, f"{image_name}.png")
cv2.imwrite(image_output_path, convex_hull_image)
image_output_path = os.path.join(triangle_images_output_dir, f"{image_name}.png")
cv2.imwrite(image_output_path, triangle_image)
image_output_path = os.path.join(normalized_images_output_dir, f"{image_name}.png")
cv2.imwrite(image_output_path, warped_image)
print("Predicting the emotions.")
predicted_emotions = classifier_model.predict(images)
real_emotions = df_emotions_test.values.flatten()
accuracy = accuracy_score(real_emotions, predicted_emotions)
f1 = f1_score(real_emotions, predicted_emotions, average="weighted")
labels = sorted(np.unique(np.concatenate((real_emotions, predicted_emotions))))
cm = confusion_matrix(real_emotions, predicted_emotions,labels=labels)
# Normalizing the confusion matrix
cm = normalize(cm, axis=1, norm='l1')
df_cm = pd.DataFrame(cm, labels, labels)
plt.figure(figsize=(10,7))
sn.set(font_scale=1.4)
sn.heatmap(df_cm, annot=True, annot_kws={"size": 16})
confusion_matrix_output_path = os.path.join(model_output_dir, f"confusion_matrix.png")
plt.savefig(confusion_matrix_output_path)
class_acccuracies = cm.diagonal()/cm.sum(axis=1)
eval_result_output_path = os.path.join(model_output_dir, f"eval_results.txt")
eval_file = open(eval_result_output_path, "w")
lines = [f"Overall Accuracy: {accuracy}\n", f"F1 Score: {f1}\n", f"Mean Class Accuracy: {class_acccuracies.mean()}\n"]
for label, class_accuracy in zip(labels, class_acccuracies):
lines.append(f"Accuracy of {label}: {class_accuracy}\n")
eval_file.writelines(lines)
eval_file.close()
for index_id, (image, normalized_image, real_emotion, predicted_emotion) in tqdm(enumerate(zip(images, warped_images, real_emotions, predicted_emotions)),desc=f'Predicting the emotions',total=len(images)):
height, width = image.shape
image = cv2.copyMakeBorder(image, 0, 50, 0, 0, cv2.BORDER_CONSTANT,value=(0,0,0))
image = cv2.putText(image, f'Real Emotion: {real_emotion.title()}', (width//2-80, height+29), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2, cv2.LINE_AA)
height, width = normalized_image.shape
normalized_image = cv2.copyMakeBorder(normalized_image, 0, 50, 0, 0, cv2.BORDER_CONSTANT,value=(0,0,0))
normalized_image = cv2.putText(normalized_image, f'Predicted Emotion: {predicted_emotion.title()}', (width//2-110, height+29), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2, cv2.LINE_AA)
output_image = np.concatenate((image, normalized_image),axis=1)
image_name = str(df_emotions_test.index[index_id]).zfill(z_fill_length)
image_output_path = os.path.join(emotions_output_dir, f"{image_name}.png")
cv2.imwrite(image_output_path, output_image)
if __name__ == "__main__":
main()