完整代码已上传
优快云下载:https://download.youkuaiyun.com/download/pmj110119/11293264
百度云:https://pan.baidu.com/s/16ZgaX3J_6na6Y9-Uh--70g 提取码:6sk4
模型训练部分参见上一篇博客:
Keras实战——人脸表情识别(一)模型的搭建和训练
https://blog.youkuaiyun.com/pmj110119/article/details/94874335
一、将之前训练好的模型加载出来
model_path 为模型保存的路径,其中应含有 model_json.json 与 model_weight..h5 两个文件
#加载模型结构
json_file=open(model_path+'model_json.json') #加载模型结构文件
loaded_model_json = json_file.read()
json_file.close()
model = model_from_json(loaded_model_json) #结构文件转化为模型
#加载权重
model.load_weights(model_path+'model_weight.h5')#h5文件保存模型的权重数据
二、检测出人脸——opencv人脸检测器
我们训练时使用的数据集图片,整张图片就是一个人脸。然而一般情况下处理的图片,人脸只是图片中一部分甚至一张图片中会有好几个人脸。因此,要先把人脸“抠”出来,再使用我们的模型对其进行表情识别。
OpenCV支持利用样本的Haar特征进行分类器的训练,其自带检测人脸的haar分类器,我们直接使用就好。
首先要找到 haarcascade_frontalface_alt.xml 这个文件,将其复制粘贴到 Project 的路径
(xml文件的路径:opencv根目录/sources/data/haarcascades,找不到的话可以去下面的链接下载)
链接:https://pan.baidu.com/s/1BGcTix_10W9fUaHyvXo4mw 提取码:d2xi
#人脸识别分类器本地存储路径
cascade_path = root_path+"haarcascade_frontalface_alt.xml"
#使用人脸识别分类器,读入分类器
cascade = cv2.CascadeClassifier(cascade_path)
接下来,只要一行代码即可得到检测到人脸
#利用分类器识别出哪个区域为人脸,返回检测到的人脸序列(矩形框四个参数)
faceRects = cascade.detectMultiScale(frame_gray, scaleFactor = 1.1,
minNeighbors = 1, minSize = (120, 120))
这里的frame_gray即为灰度化后的原图,可以是一张图片,也可以是视频流的一帧
三、识别人脸表情
终于到了使用模型的时候。
识别表情前,先对人脸进行裁切、水平翻转,同时对三张图片进行识别,识别结果进行线性加权融合。用这种方法可以增强分类器在空间上对局部位移和轻微形变的鲁棒性
代码如下
if len(faceRects) > 0:
for faceRect in faceRects:
x, y, w, h = faceRect #人脸矩形框的左上角坐标、宽、高
images=[]
rs_sum=np.array([0.0]*num_class) #([0, 0, 0, 0, 0, 0, 0])
#截取脸部图像提交给模型识别这是谁
image = frame_gray[y: y + h, x: x + w ] #注意这里x、y的先后顺序
image=cv2.resize(image,(img_size,img_size)) #将人脸缩放成网络所对应的输入图片大小
image=image*(1./255) #归一化
images.append(image)
images.append(cv2.flip(image,1)) #水平翻转
images.append(cv2.resize(image[2:45,:],(img_size,img_size))) #裁切
for img in images:
image=img.reshape(1,img_size,img_size,1)
#预测出每个类别的概率值
list_of_list = model.predict_proba(image,batch_size=32,verbose=1)
result = [prob for lst in list_of_list for prob in lst]
rs_sum+=np.array(result)
print(rs_sum)
label=np.argmax(rs_sum)
emo = emo_labels[label]
print ('Emotion : ',emo)
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness = 2)
font = cv2.FONT_HERSHEY_SIMPLEX
#文字提示是谁
cv2.putText(frame,'%s' % emo,(x + 30, y + 30), font, 1, (255,0,255),4)
cv2.imshow("识别朕的表情!", frame)