一、主要的流程

二、主要步骤:
1.我们可以通过调用dlib这个库 使用特征提取器get_frontal_face_detector
以及使用训练好的特征预测器 从而得到dlib 的68点模型,为我们的情绪识别提供了很大帮助
# 使用特征提取器get_frontal_face_detector
self.detector = dlib.get_frontal_face_detector()
# dlib 的68点模型,使用训练好的特征预测器
self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
2.
首先 建cv2摄像头对象 之后进行分帧及灰度处理
之所以进行灰度处理是为了减小图像原始数据量,便于后续处理时计算量更少,因为情绪识别的图像处理一般不需要对彩色图像的RGB三个分量都进行处理
之后利用dlib进行检测人脸 并通过预测器得到68点数据的坐标
#建cv2摄像头对象,这里使用电脑自带摄像头,如果接了外部摄像头,则自动切换到外部摄像头
self.cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
#设置视频参数,propId设置的视频参数,value设置的参数值
self.cap.set(3,480)
# cap.isOpened() 返回true/false检查初始化是否成功
while(True):
# cap.read()
#返回两个值:
# 一个布尔值true/false,用来判断读取视频是否成功/是否到视频末尾
#图像对象,图像的三维矩阵
flag, im_rd = self.cap.read()
#每帧数据延时1ms,延时为0读取的是静态帧
k= cv2.waitKey(30)
#取灰度
img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)
#使用人脸检测器检测每一帧图像中的人脸。并返回人脸数rects
faces = self.detector(img_gray,0)
#待会要显示在屏幕上的字体
font = cv2.FONT_HERSHEY_SIMPLEX
#如果检测到人脸
if(len(faces) !=0):
#对每个人脸都标出68个特征点
# enumerate方法同时返回数据对象的索引和数据,k为索引,d为faces中的对象
fork, dinenumerate(faces):
#用红色矩形框出人脸
cv2.rectangle(im_rd, (d.left(), d.top()), (d.right(), d.bottom()), (0,0,255))
# print(d.top())
#计算人脸热别框边长
self.face_width = d.right() - d.left()
#使用预测器得到68点数据的坐标
shape = self.predictor(im_rd, d)
3.到1971年,这两个人研究了 6 种基本表情 (即高兴、悲伤、惊讶、恐惧、愤怒和厌恶 ) ,并系统地建立了上千幅不同的人脸表情图象库。
通过这个表格 我们可以看到 不同的表情对应了脸部不同的运动特征。如惊讶时 一般嘴巴张开 眉毛抬高 眼睛睁大

4.


首先来看一下对于眼睛睁开程度的测定,通过41 37 40 38 等坐标的运算 我们可以得到 眼睛睁开距离与识别框高度之比,我们也可以得到以下参数
mouse_width # 嘴巴宽度与识别框宽度之比
mouse_height # 嘴巴高度与识别框高度之比
k # 眉毛的倾斜方向
eyebrow_height # 眉毛高度与识别框高度之比
eyebrow_spacing # 眉毛间距与识别框高度之比
eye # 眼睛睁开距离与识别框高度之比
eye_long # 眼睛长度
mouth_higth # 嘴巴外圈张开
mouth_xia # 嘴巴下
我们计算了CK+这个人脸表情的数据集里 开心表情的嘴巴张开比例、嘴巴宽度、眉毛倾斜程度等特征,并导入excel表格生成折线图:

通过折线图可以很明显的看出什么参数可以使用,什么参数的可信度不高,什么参数在那个范围内可以作为一个指标。
我们分析了并结合平均值 极值 方差 稳定性等各个方面以及不同表情之间主要突出特征的主成分分析,通过对多个不同表情数据的分析,得出每个指标的参考值,可以写出简单的表情分类标准。
得到了以下代码
if(eye_long <=0.02and0.130.21andmouth_higth<0.04
and0<= mouth_xia_ <=0.1and0.350.43and
eye_hight <=0.08):
cv2.putText(im_rd,"angry", (d.left(), d.bottom() +20), cv2.FONT_HERSHEY_SIMPLEX,0.8, (0,0,255),2,4)
elif0.03<= mouth_higth <=0.3and(0.3<= mouth_width <=0.55)
and(0.08<= mouth_xia_ <=0.2 and0.20.3and 0.10.22):
cv2.putText(im_rd,"happy", (d.left(), d.bottom() +20), cv2.FONT_HERSHEY_SIMPLEX,0.8, (0,0,255),2,4)
elif0.040.11and0.15<= mouth_higth_wand0.20.4
and00.2and0.040.2and0.1 # or ((mouth_higth <= 0.1) and (0.12 < eye_hight)):
cv2.putText(im_rd,"surprise", (d.left(), d.bottom() +20), cv2.FONT_HERSHEY_SIMPLEX,0.8,
(0,0,255),2,4)
elif((0.03<= eye_hight <=0.08)and0.27<= brow_k <=0.35and
mouth_xia_ <0.1and0.050.15 and0.240.41):
# or (0.3 <= mouth_width and eye_hight <= 0.03):
cv2.putText(im_rd,"sadness", (d.left(), d.bottom() +20), cv2.FONT_HERSHEY_SIMPLEX,0.8,
(0,0,255),2,4)
elifmouth_xia_<0and0.250.4and0.040.1and0.3
cv2.putText(im_rd,"nature", (d.left(), d.bottom() +20), cv2.FONT_HERSHEY_SIMPLEX,0.8,
(0,0,255),2,4)
虽然简单的表情可以识别出来,但是一些复杂的表情识别准确率较低,所以我们决定暂时放弃了对这种方法的探索
于是我们又寻求了另一种分类方式Knn
KNN的全称是K Nearest Neighbors,意思是K个最近的邻居,从这个名字我们就能看出一些KNN算法的蛛丝马迹。K个最近邻居,毫无疑问,K的取值肯定是至关重要的。那么最近的邻居又是怎么回事呢?其实,KNN的原理就是当预测一个新的值x的时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别。听起来有点迷,我们还是来看看图吧。

图中绿色的点就是我们要预测的那个点,假设K=3。那么KNN算法就会找到与它距离最近的三个点(这里用圆圈把它圈起来了),看看哪种类别多一些,比如这个例子中是蓝色三角形多一些,新来的绿色点就归类到蓝三角了。
但是,当K=5的时候,判定就变成不一样了。这次变成红圆多一些,所以新来的绿点被归类成红圆。从这个例子中,我们就能看得出K的取值是很重要的。

就先介绍到这了
这是我们的一个课程设计
我们一步一步探索 表情识别部分由sklearn knn模型识别
我们也制作了交互页面gui 包括 摄像头实时识别及图片表情识别