【人工智能项目】LBP+SVM人脸表情识别

本文介绍了使用传统机器学习方法结合局部二值模式(LBP)提取人脸表情特征,通过SVM模型实现人脸表情识别的过程。从fer2013.csv数据集生成图片,分析类别分布,提取特征并进行训练,最后评估了模型性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【人工智能项目】人脸表情识别

在这里插入图片描述
本次将采用传统的机器方法对人脸表情进行识别,主要步骤为先提取人脸表情的特征,拼接特征,送入机器学习模型当中训练测试,得到最终的检测结果。那开搞!!!
在这里插入图片描述

生成本次所需的图片

本次所用的数据是fer2013.csv数据,图片以像素值的形式保存在了csv文件中,所以我们需要先生成图片。

import pandas as pd

df = pd.read_csv("./fer2013.csv")
df.head()

#encoding:utf-8
import pandas as pd
import numpy as np
import os
import cv2

emotions = {
    "0":"anger",
    "1":"disgust",
    "2":"fear",
    "3":"happy",
    "4":"sad",
    "5":"surprised",
    "6":"normal"
}

def createDir(dir):
    if os.path.exists(dir) is False:
        os.makedirs(dir)

        
def saveImageFromFer2013(file):
    
    # 读取csv文件
    faces_data = pd.read_csv(file)
    imageCount = 0
    # 遍历csv文件内容,并将图片数据按分类保存
    for index in range(len(faces_data)):
        # 解析每一行csv文件内容
        emotion_data = faces_data.loc[index][0]
        image_data = faces_data.loc[index][1]
        usage_data = faces_data.loc[index][2]
        # 将图片数据转换为48*48
        data_array = list(map(float,image_data.split()))
        data_array = np.asarray(data_array)
        image = data_array.reshape(48,48)
        
        # 选择分类,并创建文件名
        dirName = usage_data
        emotionName = emotions[str(emotion_data)]
        
        # 图片要保存的文件夹
        imagePath = os.path.join(dirName,emotionName)
        
        # 创建分类文件夹以及表情文件夹
        createDir(dirName)
        createDir(imagePath)
        
        # 图片文件名
        imageName = os.path.join(imagePath,str(index)+".jpg")
        
        # 保存图片
        cv2.imwrite(imageName,image)
        imageCount = index
    print("总共有"+str(imageCount)+"张图片")

if __name__ == "__main__":
    saveImageFromFer2013("fer2013.csv")

总共有35886张图片

对生成的图片进行可视化展示分析。

# 可视化图像 anger disgust fear happy normal sad surprised
from tensorflow.keras.preprocessing.image import load_img,img_to_array
import matplotlib.pyplot as plt
import os
import warnings

%matplotlib inline

# 图像像素大小为48*48
pic_size = 48
plt.figure(0,figsize=(12,20))
cpt = 0
for expression in os.listdir("./Training/"):
    for i in range(1,6):
        cpt = cpt +1
        plt.subplot(7,5,cpt)
        img = load_img("./Training/"+expression+"/"+os.listdir("./Training/"+expression)[i],target_size=(pic_size,pic_size))
        plt.imshow(img,cmap="gray")
plt.tight_layout()
plt.show()        

在这里插入图片描述
之后对训练图像中类别数量进行统计

# 统计训练图像中每个类别的数量
for expression in os.listdir("./Training/"):
    print(str(len(os.listdir("./Training/"+expression)))+" " + expression +" images")

95 anger images
436 disgust images
4097 fear images
7215 happy images
4965 normal images
4830 sad images
3171 surprised images

特征提取工作

import os
import numpy as np
from skimage import feature as skif
from skimage import io, transform
import random
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVR

<img src="./2.png">
def get_lbp_data(images_data, hist_size=256, lbp_radius=1, lbp_point=8):
    n_images = images_data.shape[0]
    hist = np.zeros((n_images, hist_size))
    for i in np.arange(n_images):
        # 使用LBP方法提取图像的纹理特征.
        lbp = skif.local_binary_pattern(images_data[i], lbp_point, lbp_radius, 'default')
        # 统计图像的直方图
        max_bins = int(lbp.max() + 1)
        # hist size:256
        hist[i], _ = np.histogram(lbp, normed=True, bins=max_bins, range=(0, max_bins))

    return hist
import os
import cv2


anger_imgs_path = "./Training/anger/"
anger_hists = []
for img_path in os.listdir(anger_imgs_path):
    img = cv2.imread(os.path.join(anger_imgs_path,img_path))
    hist =  get_lbp_data(img, hist_size=256, lbp_radius=1, lbp_point=8)
    anger_hists.append(hist)
anger_hists = np.array(anger_hists)
print(anger_hists.shape)
import numpy as np
anger_arr = np.zeros(3995)
anger_arr.shape

同理,对其余文件夹中的图片进行相同操作,生成各个表情的特征之后,对其拼接。

x_train = np.vstack((anger_hists,disgust_hists,fear_hists,happy_hists,normal_hists,sad_hists,surprised_hists))

y_train = []

anger_list = list(anger_arr)
disgust_list = list(disgust_arr)
fear_list = list(fear_arr)
happy_list = list(happy_arr)
normal_list = list(normal_arr)
sad_list = list(sad_arr)
surprised_list = list(surprised_arr)


anger_list.extend(disgust_list)
anger_list.extend(fear_list)
anger_list.extend(happy_list)
anger_list.extend(normal_list)
anger_list.extend(sad_list)
anger_list.extend(surprised_list)


y_train = np.array(anger_list)
x_train.shape
y_train.shape

重新划分

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(X,y,test_size=0.1,random_state=2019)

SVM模型

from sklearn.svm import SVC

svm = SVC(kernel="linear")
svm.fit(x_train,y_train)

SVC(C=1.0, break_ties=False, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape=‘ovr’, degree=3, gamma=‘scale’, kernel=‘linear’,
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)

from sklearn.externals import joblib
svm = joblib.load("svm_train_model.m")
print ("Done\n")
from sklearn.metrics import accuracy_score,f1_score,confusion_matrix,classification_report

from sklearn.externals import joblib
joblib.dump(svm, "svm_train_model.m")
print ("Done\n")
prediction =svm.predict(x_test)
score=accuracy_score(y_test,prediction)
import seaborn as sns

garbage_types = ['anger','disgust','fear','happy','normal',
               'sad','surprised']
labels = {0:'anger',1:'disgust',2:'fear',3:'fear',4:'normal',
          5:'sad',6:'surprised'}




acc = accuracy_score(y_test,prediction)
print(acc)
con_matrix = confusion_matrix(y_test, prediction,
                              labels=[0, 1, 2, 3, 4, 5, 6])
plt.figure(figsize=(10, 10))
plt.title('Prediction of garbage types')
plt.ylabel('True label')
plt.xlabel('Predicted label')
# plt.show(sns.heatmap(con_matrix, annot=True, fmt="d",annot_kws={"size": 7},cmap='Blues',square=True))
ax = sns.heatmap(con_matrix, annot=True, fmt="d", annot_kws={"size": 7}, cmap='Blues', square=True)
bottom, top = ax.get_ylim()
ax.set_ylim(bottom + 0.5, top - 0.5)
plt.show()

小节

LBP+SVM人脸识别的准确率相比较深度学习比较一般,不过主要是让大家了解如何提取特征,送入机器学习模型当中。那么本次就到这里了,下次见!

在这里插入图片描述

人脸表情识别 2020.8.22,重构了整个仓库代码,改用Tensorflow2中的keras api实现整个系统。考虑到很多反映jupyter notebook写的train使用起来不太方便,这里改成了py脚本实现。 2020.12.18,根据反馈,修改了Jaffe的优化器设置。 简介 使用卷积神经网络构建整个系统,在尝试了Gabor、LBP等传统人脸特征提取方式基础上,深度模型效果显著。在FER2013、JAFFE和CK+三个表情识别数据集上进行模型评估。 环境部署 基于Python3和Keras2(TensorFlow后端),具体依赖安装如下(推荐使用conda虚拟环境)。 git clone https://github.com/luanshiyinyang/FacialExpressionRecognition.git cd FacialExpressionRecognition conda create -n FER python=3.6 source activate FER conda install cudatoolkit=10.1 conda install cudnn=7.6.5 pip install -r requirements.txt 如果你是Linux用户,直接执行根目录下的env.sh即可一键配置环境,执行命令为bash env.sh。 数据准备 数据集和预训练模型均已经上传到百度网盘,链接给出,提取密码为2pmd。下载后将model.zip移动到根目录下的models文件夹下并解压得到一个*.h5的模型参数文件,将data.zip移动到根目录下的dataset文件夹下并解压得到包含多个数据集压缩文件,均解压即可得到包含图像的数据集(其中rar后缀的为原始jaffe数据集,这里建议使用我处理好的)。 项目说明 传统方法 数据预处理 图片降噪 人脸检测(HAAR分类器检测(opencv)) 特征工程 人脸特征提取 LBP Gabor 分类器 SVM 深度方法 人脸检测 HAAR分类器 MTCNN(效果更好) 卷积神经网络 用于特征提取+分类 网络设计 使用经典的卷积神经网络,模型的构建主要参考2018年CVPR几篇论文以及谷歌的Going Deeper设计如下网络结构,输入层后加入(1,1)卷积层增加非线性表示且模型层次较浅,参数较少(大量参数集中在全连接层)。 模型训练 主要在FER2013、JAFFE、CK+上进行训练,JAFFE给出的是半身图因此做了人脸检测。最后在FER2013上Pub Test和Pri Test均达到67%左右准确率(该数据集爬虫采集存在标签错误、水印、动画图片等问题),JAFFE和CK+5折交叉验证均达到99%左右准确率(这两个数据集为实验室采集,较为准确标准)。 执行下面的命令将在指定的数据集(fer2013或jaffe或ck+)上按照指定的batch_size训练指定的轮次。训练会生成对应的可视化训练过程,下图为在三个数据集上训练过程的共同绘图。 python src/train.py --dataset fer2013 --epochs 300 --batch_size 32 模型应用 与传统方法相比,卷积神经网络表现更好,使用该模型构建识别系统,提供GUI界面和摄像头实时检测(摄像必须保证补光足够)。预测时对一张图片进行水平翻转、偏转15度、平移等增广得到多个概率分布,将这些概率分布加权求和得到最后的概率分布,此时概率最大的作为标签(也就是使用了推理数据增强)。 GUI界面 注意,GUI界面预测只显示最可能是人脸的那个脸表情,但是对所有检测到的人脸都会框定预测结果并在图片上标记,标记后的图片在output目录下。 执行下面的命令即可打开GUI程序,该程序依赖PyQT设计,在一个测试图片(来源于网络)上进行测试效果如下图。 python src/gui.py 上图的GUI反馈的同时,会对图片上每个人脸进行检测并表情识别,处理后如下图。 实时检测 实时检测基于Opencv进行设计,旨在用摄像头对实时视频流进行预测,同时考虑到有些人的反馈,当没有摄像头想通过视频进行测试则修改命令行参数即可。 使用下面的命令会打开摄像头进行实时检测(ESC键退出),若要指定视频进行进行检测,则使用下面的第二个命令。 python src/recognition_camera.py python src/recognition_camera.py --source 1 --video_path 视频绝对路径或者相对于该项目的根目录的相对路径 下图是动态演示的在Youtube上某个视频上的识别结果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mind_programmonkey

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值