fer2013人脸表情数据集简介
fer2013人脸表情数据集由35886张人脸表情图片组成,其中,测试图(Training)28708张,公共验证图(PublicTest)和私有验证图(PrivateTest)各3589张,每张图片是由大小固定为48×48的灰度图像组成,共有7种表情,分别对应于数字标签0-6,具体表情对应的标签和中英文如下:0 anger 生气; 1 disgust 厌恶; 2 fear 恐惧; 3 happy 开心; 4 sad 伤心;5 surprised 惊讶; 6 normal 中性。
但是,数据集并没有直接给出图片,而是将表情、图片数据、用途的数据保存到csv文件中,如下图所示,
如上图所示,第一张图是csv文件的开头,第一行是表头,说明每列数据的含义,第一列表示表情标签,第二列即为图片数据,这里是原始的图片数据,最后一列为用途。
将表情图片提取出来
知道数据结构以后,就好办了,使用pandas解析csv文件,再将原始图片数据保存为jpg文件,并根据用途和标签标签进行分类,分别保存到对应文件夹下,代码比较简单,并且做了详细备注,直接给完整代码如下:
import cv2
# pip install opencv-python -i https://mirrors.aliyun.com/pypi/simple/
import pandas as pd
import numpy as np
import os
emotions = {
'0': 'anger', # 生气
'1': 'disgust', # 厌恶
'2': 'fear', # 恐惧
'3': 'happy', # 开心
'4': 'sad', # 伤心
'5': 'surprised', # 惊讶
'6': 'normal', # 中性
}
#创建文件夹
def createDir(dir):
if os.path.exists(dir) == False:
os.makedirs(dir)
createDir("../imgs")
def saveImageFromFer2013(file):
#读取csv文件
faces_data = pd.read_csv(file)
# print(faces_data.head(10))
# print(faces_data.columns) #['emotion', 'pixels', 'Usage']
# print(faces_data.shape)(35887, 3)
# print(len(faces_data)) # 35887
#遍历csv文件内容,并将图片数据按分类保存
print(faces_data.head())
for index in range(len(faces_data)):
#解析每一行csv文件内容
emotion_data = faces_data.iloc[index, 0]
# print(emotion_data)
image_data = faces_data.iloc[index, 1]
# print(image_data)
# print(type(image_data))
usage_data = faces_data.iloc[index, 2]
# ['222', '222', '210'] 变成[222, 222, 210]
data = list(map(float, image_data.split()))
#将图片数据转换成48*48
image = np.array(data).reshape(48, 48)
print(image.shape)
#选择分类,并创建文件名
dirName = usage_data
emotionName = emotions[str(emotion_data)]
# print(emotionName)
#图片要保存的文件夹
image_path = os.path.join(dirName, emotionName)
print(image_path)
# 创建“用途文件夹”和“表情”文件夹
createDir(image_path)
#图片文件名
image_Name = os.path.join(image_path, str(index) + '.jpg')
cv2.imwrite(image_Name, image) #使用cv2实现图片与numpy数组的相互转化
saveImageFromFer2013('../datasets/fer2013/fer2013.csv')
运行结果,
运行完上面的代码后,得到3个文件夹,文件下有相应的表情的子文件夹,
子文件夹下又有相应的图片,
加载fer2013数据集合
创建 utils.py
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
def load_data(data_file):
""" loads fer2013.csv dataset
# Arguments: data_file fer2013.csv
# Returns: faces and emotions
faces: shape (35887,48,48,1)
emotions: are one-hot-encoded
"""
data = pd.read_csv(data_file)
print(data.head())
pixels = data['pixels'].to_list()
weight, height = 48, 48
faces = []
for pixel_squence in pixels:
face = [int(pixel) for pixel in pixel_squence.split()]
face = np.array(face).reshape(weight, height)
faces.append(face)
faces = np.array(faces)
## 扩充一个维度
faces = np.expand_dims(faces,-1)
# 获取该列的one_hot表示
df = pd.get_dummies(data['emotion'])
emotions = df.values
return faces, emotions
def preprocess_input(images):
"归一化数据"
images = images/255
return images
faces, emotions = load_data('../datasets/fer2013/fer2013.csv')
print('faces.shape = ', faces.shape)
print('emotions.shape = ', emotions.shape)
print("faces[0].shape = ", faces[0].shape) # 一张表情图
one_face = faces[0].reshape(48, -1)
print('one_face.shape = ', one_face.shape)
one_emotion = emotions[0]
print('one_emotion = ', one_emotion)
plt.imshow(one_face, cmap='gray')
plt.show()
print(preprocess_input(one_face))
该函数输入的是fer2013.csv文件路径,返回值是一个元组,包含faces图像矩阵以及emotions的one-hot-encoded矩阵。
data = pd.read_csv(data_file)
利用pandas读取csv文件到data变量。
pixels = data[‘pixels’].tolist() 返回一个列表,列表中每个数据如下:
70 80 82 72 58 58 60 63 54 58 60 48 89 115 121 119 115 110 98 91 84 84 90 99 110 126 143 153 158 171 169 172 169 165 129 110 113 107 95 79 66 62 56 57 61 52 43 41 65 61 58 57 56 69 75 70 65 56 54 105 146 154 151 151 155 ...
列表中每个数据都是表情图片像素点的值的集合,用空格分隔。
接下来,遍历图像列表,
faces = []
for pixel_squence in pixels:
face = [int(pixel) for pixel in pixel_squence.split()]
face = np.array(face).reshape(weight, height)
faces.append(face)
遍历图像列表,将每一个图片像素数据先用空格分隔,然后转换为列表,之后在转换为48*48的矩阵,最后加入到列表faces。
faces = np.array(faces)
将列表faces再次转换成numpy矩阵,此时faces的shape为(35887,48,48)
faces = np.expand_dims(faces,-1)
扩充faces的维度,扩充之后的faces的shape为(35887,48,48,1),做此步操作的原因是,神经网络的输入为图片,格式为(height,width,通道信息)。
df = pd.get_dummies(data['emotion'])
pd.get_dummies(data[‘emotion’])获得每一个表情分类的one-hot表示,返回的是一个dataframe,最后调用
emotions = df.values
将类型转换为矩阵