├── dataset ├── pablo.png ├── jackman.png ├── monalisa.png └── fer2013 │ └── dataset_download.txt ├── README.md ├── model.py ├── test.py └── train.py /dataset/pablo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingliangliang1/facial/HEAD/dataset/pablo.png -------------------------------------------------------------------------------- /dataset/jackman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingliangliang1/facial/HEAD/dataset/jackman.png -------------------------------------------------------------------------------- /dataset/monalisa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingliangliang1/facial/HEAD/dataset/monalisa.png -------------------------------------------------------------------------------- /dataset/fer2013/dataset_download.txt: -------------------------------------------------------------------------------- 1 | 数据集下载: 2 | 3 | https://pan.baidu.com/s/1b5troPWfbw1-E_ff9XYdRg 4 | 提取码:nikm 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # facial 2 | 3 | ## 检测人脸表情 4 | 5 | Keras编写CNN框架的图像多分类 6 | 7 | 数据集 8 | https://pan.baidu.com/s/1b5troPWfbw1-E_ff9XYdRg 9 | 提取码:nikm 10 | 11 | 文件结构: 12 | * dataset 13 | * fer2013 训练数据集文件夹 14 | * .png .png格式的文件都是测试时使用 15 | * model.py 模型文件 16 | * train.py 训练 17 | * test.py 测试 18 | 19 | 20 | -------------------------------------------------------------------------------- /model.py: -------------------------------------------------------------------------------- 1 | import keras 2 | from keras.models import Sequential 3 | from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D 4 | from keras.layers import Dense, Activation, Dropout, Flatten 5 | 6 | def build_model(num_classes): 7 | # construct CNN structure 8 | model = Sequential() 9 | 10 | # 1st convolution layer 11 | model.add(Conv2D(64, (5, 5), activation='relu', input_shape=(48, 48, 1))) 12 | model.add(MaxPooling2D(pool_size=(5, 5), strides=(2, 2))) 13 | 14 | # 2nd convolution layer 15 | model.add(Conv2D(64, (3, 3), activation='relu')) 16 | # model.add(Conv2D(64, (3, 3), activation='relu')) 17 | model.add(AveragePooling2D(pool_size=(3, 3), strides=(2, 2))) 18 | 19 | # 3rd convolution layer 20 | model.add(Conv2D(128, (3, 3), activation='relu')) 21 | # model.add(Conv2D(128, (3, 3), activation='relu')) 22 | model.add(AveragePooling2D(pool_size=(3, 3), strides=(2, 2))) 23 | 24 | model.add(Flatten()) 25 | 26 | # fully connected neural networks 27 | model.add(Dense(1024, activation='relu')) 28 | model.add(Dropout(0.2)) 29 | model.add(Dense(1024, activation='relu')) 30 | model.add(Dropout(0.2)) 31 | 32 | model.add(Dense(num_classes, activation='softmax')) 33 | 34 | return model 35 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | from train import emotion_analysis, reshape_dataset 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | from keras.preprocessing import image 5 | from model import build_model 6 | 7 | if __name__ == '__main__': 8 | # path = '/home/jing/PycharmProjects/facial/dataset/fer2013/fer2013.csv' 9 | num_classes = 7 10 | 11 | # x_train, y_train, x_test, y_test = reshape_dataset(path, num_classes) 12 | 13 | model = build_model(num_classes) 14 | model.load_weights('/home/jing/PycharmProjects/facial/model_checkpoints/facial_expression_model_weights.h5') 15 | 16 | # monitor_testset_results = False 17 | # 18 | # if monitor_testset_results == True: 19 | # # make predictions for test set 20 | # predictions = model.predict(x_test) 21 | # 22 | # index = 0 23 | # for i in predictions: 24 | # if index < 30 and index >= 20: 25 | # # print(i) #predicted scores 26 | # # print(y_test[index]) #actual scores 27 | # 28 | # testing_img = np.array(x_test[index], 'float32') 29 | # testing_img = testing_img.reshape([48, 48]) 30 | # 31 | # plt.gray() 32 | # plt.imshow(testing_img) 33 | # plt.show() 34 | # 35 | # print(i) 36 | # 37 | # emotion_analysis(i) 38 | # print("----------------------------------------------") 39 | # index = index + 1 40 | 41 | # ------------------------------ 42 | # make prediction for custom image out of test set 43 | 44 | # img = image.load_img("/home/jing/PycharmProjects/facial/dataset/pablo.png", grayscale=True, target_size=(48, 48)) 45 | # img = image.load_img("/home/jing/PycharmProjects/facial/dataset/monalisa.png", grayscale=True, target_size=(48, 48)) 46 | img = image.load_img("/home/jing/PycharmProjects/facial/dataset/jackman.png", grayscale=True, target_size=(48, 48)) 47 | 48 | x = image.img_to_array(img) 49 | x = np.expand_dims(x, axis=0) 50 | 51 | x /= 255 52 | 53 | custom = model.predict(x) 54 | t1 = emotion_analysis(custom[0]) 55 | 56 | x = np.array(x, 'float32') 57 | x = x.reshape([48, 48]) 58 | plt.gray() 59 | 60 | plt.imshow(x) 61 | plt.show() 62 | # ------------------------------ 63 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import keras 3 | from keras.preprocessing import image 4 | from keras.preprocessing.image import ImageDataGenerator 5 | from model import build_model 6 | import matplotlib.pyplot as plt 7 | import tensorflow as tf 8 | import pandas as pd 9 | 10 | 11 | def read_data_np(path): 12 | with open(path) as f: 13 | content = f.readlines() 14 | 15 | lines = np.array(content) 16 | 17 | num_of_instances = lines.size 18 | print("number of instances: ", num_of_instances) 19 | print("instance length: ", len(lines[1].split(",")[1].split(" "))) 20 | 21 | return lines, num_of_instances 22 | 23 | 24 | def read_data_pd(path): 25 | 26 | data_df = pd.read_csv(path, header=0) 27 | lines = len(data_df) 28 | print(data_df.head()) 29 | 30 | return data_df, lines 31 | 32 | 33 | def reshape_dataset(paths, num_classes): 34 | x_train, y_train, x_test, y_test = [], [], [], [] 35 | 36 | lines, num_of_instances = read_data_np(paths) 37 | # data_df, lines = read_data_pd(paths) 38 | 39 | # ------------------------------ 40 | # transfer train and test set data 41 | for i in range(1, num_of_instances): 42 | try: 43 | emotion, img, usage = lines[i].split(",") 44 | # emotion, img, usage = data_df['emotion'][i], data_df['pixels'][i], data_df['Usage'][i] 45 | 46 | val = img.split(" ") 47 | 48 | pixels = np.array(val, 'float32') 49 | 50 | emotion = keras.utils.to_categorical(emotion, num_classes) 51 | 52 | if 'Training' in usage: 53 | y_train.append(emotion) 54 | x_train.append(pixels) 55 | elif 'PublicTest' in usage: 56 | y_test.append(emotion) 57 | x_test.append(pixels) 58 | except: 59 | print("", end="") 60 | 61 | # ------------------------------ 62 | # data transformation for train and test sets 63 | x_train = np.array(x_train, 'float32') 64 | y_train = np.array(y_train, 'float32') 65 | x_test = np.array(x_test, 'float32') 66 | y_test = np.array(y_test, 'float32') 67 | 68 | x_train /= 255 # normalize inputs between [0, 1] 69 | x_test /= 255 70 | 71 | x_train = x_train.reshape(x_train.shape[0], 48, 48, 1) 72 | x_train = x_train.astype('float32') 73 | x_test = x_test.reshape(x_test.shape[0], 48, 48, 1) 74 | x_test = x_test.astype('float32') 75 | 76 | print(x_train.shape[0], 'train samples') 77 | print(x_test.shape[0], 'test samples') 78 | 79 | y_train = y_train.reshape(y_train.shape[0], 7) 80 | y_train = y_train.astype('int16') 81 | y_test = y_test.reshape(y_test.shape[0], 7) 82 | y_test = y_test.astype('int16') 83 | 84 | print('--------x_train.shape:', x_train.shape) 85 | print('--------y_train.shape:', y_train.shape) 86 | 87 | 88 | print(len(x_train), 'train x size') 89 | print(len(y_train), 'train y size') 90 | print(len(x_test), 'test x size') 91 | print(len(y_test), 'test y size') 92 | 93 | return x_train, y_train, x_test, y_test 94 | 95 | 96 | # def batch_process(path, batch_size): 97 | # x_train, y_train, x_test, y_test = reshape_dataset(path) 98 | # gen = ImageDataGenerator() 99 | # train_generator = gen.flow(x_train, y_train, batch_size=batch_size) 100 | # 101 | # return x_train, y_train, x_test, y_test, train_generator 102 | 103 | 104 | # def compile_model(models): 105 | # model = models.compile(loss='categorical_crossentropy' 106 | # , optimizer=keras.optimizers.Adam() 107 | # , metrics=['accuracy'] 108 | # ) 109 | # return model 110 | 111 | 112 | def emotion_analysis(emotions): 113 | objects = ('angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral') 114 | y_pos = np.arange(len(objects)) 115 | 116 | plt.bar(y_pos, emotions, align='center', alpha=0.5) 117 | plt.xticks(y_pos, objects) 118 | plt.ylabel('percentage') 119 | plt.title('emotion') 120 | plt.show() 121 | return plt 122 | 123 | 124 | if __name__ == '__main__': 125 | num_classes = 7 # angry, disgust, fear, happy, sad, surprise, neutral 126 | batch_size = 256 127 | epochs = 5 128 | 129 | config = tf.ConfigProto(device_count={'GPU': 0, 'CPU': 56}) # max: 1 gpu, 56 cpu 130 | sess = tf.Session(config=config) 131 | keras.backend.set_session(sess) 132 | 133 | path = '/home/jing/PycharmProjects/facial/dataset/fer2013/fer2013.csv' 134 | x_train, y_train, x_test, y_test = reshape_dataset(path, num_classes) 135 | 136 | gen = ImageDataGenerator() 137 | train_generator = gen.flow(x_train, y_train, batch_size=batch_size) 138 | 139 | 140 | # for data_batch, label_batch in train_generator: 141 | # print('data_batch:', data_batch.shape) 142 | # print('label_batch:', label_batch.shape) 143 | 144 | m = build_model(num_classes) 145 | print('model:', m) 146 | print('train_generator:', train_generator) 147 | # m = compile_model(m) 148 | m.compile(loss='categorical_crossentropy' 149 | , optimizer=keras.optimizers.Adam() 150 | , metrics=['accuracy'] 151 | ) 152 | print('m:', m) 153 | m.fit_generator(train_generator, steps_per_epoch=batch_size, epochs=epochs) 154 | 155 | m.save('/home/jing/PycharmProjects/facial/model_checkpoints/facial_expression_model_weights.h5') 156 | print('save weight..') 157 | --------------------------------------------------------------------------------