人脸表情识别

人脸表情识别

目前人们对表情识别的研究大都是从静态图像或者图像序列中提取表情特征,然后根据这些特征信息通过设计相应的分类算法把表情归为某一类别以完成分类任务。大多是分为三步,第一步预处理及人脸获取,第二步,特征提取,第三步,归类。将重点放在人脸整体上,将人脸整体进行分析处理,算法核心是降维处理。本文在此基础上将特征提取分为两步,将重点放在表情关键部分。人脸表情主要体现在眼睛、鼻子、嘴巴、眉毛四个关键部分,通过对这四个关键部分的定位,可以将人脸特征选择缩小至这些部位中。减少了大量计算量,同时也提高了识别率。先人脸特征点定位出人脸区域的关键部位,再对人脸区域的关键部位进行特征提取,而非对整体进行特征提取。经过特征提取,大量的冗余的数据被去除,空间维数大大降低。

本次实验分为以下四部分:

人脸检测识别   找出图像中人脸的大概区域

人脸特征点定位   更加准确的定位出眼睛/眉毛等一些人脸区域的关键部位

表情特征提取   面部表情识别的核心步骤

表情分类   通过设置机制对表情进行分类,将表情归入相应类别

本次实验详细步骤如下:

图像预处理:

由于输入图像的来源,采集环境不同,图像采集的时候人脸离采集器的距离,焦距的大小等使得人脸在整幅图像中的大小位置不确定,在得到数据之后,通常的情况下,人脸表情图像中往往包含有各种环境条件的限制和随机噪声的干扰,这样会对图像的重点部分造成影响,所以要考虑在获取图像数据之后就要对其进行灰度修正和噪声过滤等预处理,来突出图像中感兴趣的特征,而且减弱无关的特征信息。对于本文所涉及的人脸表情,只需要保留面部部分特征,可以舍去头发,服饰,背景等无关信息。图像的预处理分为点运算和几何处理。点运算可以改变图像的直方图分布,使图像更加清晰, 利于后期的处理。除了点运算之外的图像预处理就是几何运算,几何运算可以得到人脸的位置端正的人脸图像。通过点运算和几何运算可以得到尺寸,人脸位置统一的标准化人脸图像。本次实验的方法把原始的 JAFFE 人脸表情图像转换为归一化图像。

  具体的预处理包含以下几个步骤:人脸的定位、人脸区域的几何归一化以及灰度归一化。  

几何归一化是指根据人脸表情图像的特征点和和几何模型确定主要的矩形特征区域,然后把原大小为 256×256 的图像剪裁成 150×100 的图像,这样就可以使图像中人脸的大小都一致。 灰度归一化是为了减少光照对图像的影响,对图像进行光照补偿,这样有助 于提高识别率。通过归一化就将图像的每个像素亮度值都转换到[0,1]之间,如果某个图像需要归一化,就首先把它转化成一维向量 x,然后对每一个元素 x(i)进行处理。

人脸检测识别:

人脸检测是要找出图像中人脸的大概区域,对于任意一幅给定的图像,通过算法搜索图像,判断图像中是否存在人脸。如果算法 检测出输入的图像中存在人脸图像,那么就将人脸从整个图像背景中分离出来,将人脸的位置以坐标 形式返回,同时返回人脸的大小和此时的姿态。人脸检测是人脸表情识别最基础的一步,能不能从图像 中提取人脸,以及提取出来的人脸是否符合后期处理的标准,等等这些条件直接影响后期的识别率。本次实验通过使用Opencv现有的Haar分类器将人脸从整个图像背景中分离出来。Haar分类器就是对人脸和非人脸进行分类的算法;

Haar分类器实际上是Boosting算法的一个应用,Haar分类器用到了Boosting算法中的AdaBoost算法,在AdaBoost算法的基础上,使用Haar-like小波特征和积分图方法进行人脸检测,并对AdaBoost训练出的强分类器进行级联,并且在底层的特征提取中采用了高效率的矩形特征和积分图方法

Haar分类器 =  Haar-like特征 + 积分图方法 + AdaBoost + 级联;

Haar分类器算法的要点如下:

① 使用Haar-like特征做检测。

② 使用积分图(Integral Image)对Haar-like特征求值进行加速。

③ 使用AdaBoost算法训练区分人脸和非人脸的强分类器。

④ 使用筛选式级联把强分类器级联到一起,提高准确率。

人脸特征点定位:

人脸检测是要找出图像中人脸的大概区域,而人脸特征点定位则是要更加准确的定位出眼睛、眉毛、 鼻子、嘴巴轮廓等一些人脸区域中的关键部位。以便对得到的人脸进行进一步的处理。研究方法主要分为两大类,一类是基于模型的方法,一类是基于回归的方法。

  次实验采用基于模型的方法,使用的是微软研究院孙剑的基于回归的 Explicit Shape Regression 算法,这种算法在人脸特征部位定位方面取得了很好的效果。通过 ESR 算法能够精确的定 位人脸关键点部位,给后期处理减少了大量的数据量。ESR 核心内容是使用了 cascade regression 框架, cascaderegression 框架是 P.Dollár 在 CVPR2010 的 Cascaded PoseRegression 中提出的一种方法,用来解 决对齐问题。孙剑在 esr 方法在此基础上做了几个扩展,使他更为适合做人脸关键点定位。

  要思路:通过对输入训练集最小化对齐误差,我们可以得到一系列的回归函数,通过这些函数, 可以进一步的推断出人脸整体的形状。

表情特征提取:

本次实验采用Gabor滤波器进行特征提取。Gabor 小波有很好的仿生效果,可以很好 表达表情的变化。但是考虑到提取出的特征维数过 高,算法复杂,耗时较大,故不对全图像进行特征向量求解,而是针对人脸关键部位。Gabor 滤波器公式化定义如下,其中 入为正弦函数的波长, θ为 Gabor 核函数的方向, ∅为相位偏移, r为图像空间的宽高比,b 为 Gabor 滤波器的带宽值, 6的值随着带宽 b 的变化而变化,这里需要注意的 是,b 的值必须是正实时,否则将影响结果的计算。b 的值越小,式子的标准差越大,这样的情况下, Gabor 形状就会越大。

Gabor特征提取将特征部位特征值取出来之后,接下来的工作就是对特征进行降维处理,维度太高影响系统的运行速度。本文中使用 的的特征降维算法是主成分分析算法,简称为 PCA 算法,PCA 算法主要 用于数据的降维处理,在很多数据分析的系统中,数据以多维的方式处理,而多维数据中,某些数据本 身没有区分性,如果用这些数据进行区分,那么结果代表性不大。这些数据也成为无用数据,我们要 做的是找到多维数据中那些变化比较大的数据,变化大小可以通过数据的方差来辨别,通过去除这些变 化小的维,使得留下来的数据都是能够最大限度表达原始的数据。这样处理过的数据,数据维度低了, 但是数据的原始含义并没有发生变化。

表情分类:

人脸表情识别过程中,最后一步,也是直接影响结果的一步就是表情分类。表情分类是指通过设计 分类机制来对表情进行分类,将表情归入相应的类别。常用的分类方法是按照感情分类,将表情分类到 PaulEkman 归纳的 6 种基本感情。在本文中,我们将所有表情分为四类,悲伤、开心、惊讶、害怕。人 脸表情分类的方法有很多,主要利用基于机器学习的方法如人工神经网络,贝叶斯分类,支持向量机以 及一些其他的分类算法。

本次实验采用LibSVM 对表情进行分类,LibSVM 是林智仁先生编写的 SVM 软件,该软件将 SVM 方法集合在一起, 该软件很大程度上方便了我们分类时使用 SVM 的方法。 表情分类流程:一步准备训练数据,对数据的处理,处理成 libsvm 的标准格式。第二步训练 model,调整好参数,载入数据进行训练。第三步利用训练好的 model 对样本数据进行预测。最后分析预 测结果,和标准结果进行比对分析。

本次实验采用一种新的人脸情绪识别流程,重点放在表情关键部分。大多数的人脸情绪识别算法将重点放在人脸整体上,将人脸整体进行分析处理,算法核心 是降维处理。本次实验采用人脸关键部位特征提取算法,基于回归的 Explicit Shape Regression 算法, 过 ESR 算法能够精确的定 位人脸关键点部位,给后期处理减少了大量的数据量。本次实验的人脸特征向量选择采用了 Gabor 小波,因为 Gabor 小波有很好的仿生效果,可以很好 表达表情的变化 ,考虑到提取出的特征维数过 高,算法复杂,耗时较大,不对全图像进行特征向量求解,而是针对人脸关键部位。

  • 4
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的卷积神经网络实现人脸表情识别检测的代码,包含了图片实际检测的部分: 首先,我们需要导入一些必要的库: ```python import numpy as np import cv2 import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers, models ``` 然后,我们需要准备数据。我们将使用FER2013数据集,该数据集包含了7种不同的人脸表情类别。我们将使用以下代码加载和预处理数据: ```python # Load data with open("fer2013.csv") as f: content = f.readlines() lines = np.array(content) num_of_instances = lines.size print("Number of instances: ",num_of_instances) print("Instance length: ",len(lines[1].split(",")[1].split(" "))) # Initialize train and test set x_train, y_train, x_test, y_test = [], [], [], [] # Transfer train and test set data for i in range(1,num_of_instances): try: emotion, img, usage = lines[i].split(",") val = img.split(" ") pixels = np.array(val, 'float32') emotion = keras.utils.to_categorical(emotion, 7) if 'Training' in usage: y_train.append(emotion) x_train.append(pixels) elif 'PublicTest' in usage: y_test.append(emotion) x_test.append(pixels) except: print("", end="") # Data transformation x_train = np.array(x_train, 'float32') y_train = np.array(y_train, 'float32') x_test = np.array(x_test, 'float32') y_test = np.array(y_test, 'float32') # Normalization x_train /= 255 x_test /= 255 # Reshape x_train = x_train.reshape(x_train.shape[0], 48, 48, 1) x_test = x_test.reshape(x_test.shape[0], 48, 48, 1) ``` 接下来,我们将定义一个简单的卷积神经网络模型: ```python model = models.Sequential() # 1st convolution layer model.add(layers.Conv2D(64, (3, 3), activation='relu', input_shape=(48,48,1))) model.add(layers.MaxPooling2D(pool_size=(2, 2))) model.add(layers.Dropout(0.25)) # 2nd convolution layer model.add(layers.Conv2D(128, (5, 5), activation='relu')) model.add(layers.MaxPooling2D(pool_size=(2, 2))) model.add(layers.Dropout(0.25)) # 3rd convolution layer model.add(layers.Conv2D(512, (3, 3), activation='relu')) model.add(layers.MaxPooling2D(pool_size=(2, 2))) model.add(layers.Dropout(0.25)) # 4th convolution layer model.add(layers.Conv2D(512, (3, 3), activation='relu')) model.add(layers.MaxPooling2D(pool_size=(2, 2))) model.add(layers.Dropout(0.25)) # Flatten layer model.add(layers.Flatten()) # Fully connected layer 1st layer model.add(layers.Dense(256, activation='relu')) model.add(layers.Dropout(0.25)) # Fully connected layer 2nd layer model.add(layers.Dense(512, activation='relu')) model.add(layers.Dropout(0.25)) model.add(layers.Dense(7, activation='softmax')) ``` 接下来,我们将编译模型并进行训练: ```python model.compile(loss='categorical_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001, decay=1e-6), metrics=['accuracy']) model_info = model.fit( x_train, y_train, batch_size=64, epochs=50, validation_data=(x_test, y_test), shuffle=True ) ``` 最后,我们将使用OpenCV读取一张人脸图片并进行表情识别: ```python # Load the cascade face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # Read the input image img = cv2.imread('test.jpg') # Convert into grayscale gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Detect faces faces = face_cascade.detectMultiScale(gray, 1.1, 4) # Draw rectangle around the faces and predict emotion for (x, y, w, h) in faces: roi_gray = gray[y:y + h, x:x + w] roi_gray = cv2.resize(roi_gray, (48, 48)) img_pixels = tf.keras.preprocessing.image.img_to_array(roi_gray) img_pixels = np.expand_dims(img_pixels, axis=0) img_pixels /= 255 predictions = model.predict(img_pixels) # Find max indexed array max_index = np.argmax(predictions[0]) emotions = ('angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral') predicted_emotion = emotions[max_index] # Draw rectangle around the face cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # Draw label cv2.putText(img, predicted_emotion, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) # Display the output cv2.imshow('img', img) cv2.waitKey() ``` 希望这个代码能够帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值