基于OpenCV和Keras的人脸识别系列手记:
项目完整代码参见Github仓库。
本篇手记是上面这一系列的第五篇。
这篇手记我们将最终实现人脸识别的功能,和前面的几篇手记结合起来就是一个完整的实战项目:
- 用OpenCV打开摄像头
- 利用OpenCV自带的人脸探测器探测人脸
- 采集不同人的人脸并结合LFW的人脸数据准备数据集
- 对数据集进行预处理
- 用自己的数据集训练神经网络模型用于人脸识别
- 用训练好的数据集实现人脸识别
在开始上面的第六项之前,要先把之前训练好的CNN模型存储下来,并定义一个预测人脸的函数,最后在人脸识别程序中加载存储下来的模型并调用预测函数识别人脸。
在face_train_keras.py
文件中定义save_model
、load_model
和face_predict
三个函数,分别用于存储模型、加载模型和预测人脸分类:
def save_model(self, file_path):
self.model.save(file_path)
def load_model(self, file_path):
self.model = load_model(file_path)
def face_predict(self, image):
# 将探测到的人脸reshape为符合输入要求的尺寸
image = resize_image(image)
image = image.reshape((1, IMAGE_SIZE, IMAGE_SIZE, 3))
# 图片浮点化并归一化
image = image.astype('float32') # float32 Single precision float: sign bit, 8 bits exponent, 23 bits mantissa
image /= 255
result = self.model.predict(image)
# print('result:', result)
# print(result.shape) # (1,2)
# print(type(result)) # <class 'numpy.ndarray'>
return result.argmax(axis=-1) # The axis=-1 in numpy corresponds to the last dimension
最后来执行训练、评估和保存模型,在face_train_keras.py
文件中继续增加:
if __name__ == '__main__':
dataset = Dataset('./dataset/')
dataset.load()
# 训练模型
model = Model()
model.build_model(dataset)
#测试训练函数的代码
model.train(dataset)
model.evaluate(dataset)
model.save_model('./model/me.face.model.h5') # 注意这里要在工作目录下先新建model文件夹,否则会报错:Unable to create file,error message = 'No such file or directory'
运行face_train_keras.py
就能像上篇手记中那样训练模型,不断改进了。
将训练好的模型保存下来以后,新建一个face_recognition.py
文件来实现实时人脸识别,这个程序基本上就是在用OpenCV打开摄像头并探测人脸的基础上调用了一下face_predict
函数:
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 11 17:33:58 2018
@author: 123
"""
import cv2
#import sys
from face_train_keras import Model
#加载模型
model = Model()
model.load_model(file_path = './model/me.face.model.h5')
#框住人脸的矩形边框颜色
cv2.namedWindow('Detecting your face.') # 创建窗口
color = (0, 255, 0)
classifier = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') # 加载分类器
#捕获指定摄像头的实时视频流
cap = cv2.VideoCapture(0)
while cap.isOpened():
ok, frame = cap.read() # type(frame) <class 'numpy.ndarray'>
if not ok:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化
faceRects=classifier.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(32,32))
if len(faceRects) > 0:
for faceRect in faceRects:
x, y, w, h = faceRect
#截取脸部图像提交给模型识别这是谁
image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
if image is None: # 有的时候可能是人脸探测有问题,会报错 error (-215) ssize.width > 0 && ssize.height > 0 in function cv::resize,所以这里要判断一下image是不是None,防止极端情况
break
else:
faceID = model.face_predict(image)
# print(faceID) # [0]
# print(type(faceID)) # <class 'numpy.ndarray'>
# print(faceID.shape) # (1,)
# #如果是“我”
if faceID[0] == 0:
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness = 2)
#文字提示是谁
cv2.putText(frame,'Bill',
(x + 30, y + 30), #坐标
cv2.FONT_HERSHEY_SIMPLEX, #字体
1, #字号
(255,0,255), #颜色
2) #字的线宽
else:
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness = 2)
#文字提示是谁
cv2.putText(frame,'Unknown',
(x + 30, y + 30), #坐标
cv2.FONT_HERSHEY_SIMPLEX, #字体
1, #字号
(255,0,255), #颜色
2) #字的线宽
cv2.imshow("Detecting your face.", frame)
#等待10毫秒看是否有按键输入
k = cv2.waitKey(10)
#如果输入q则退出循环
if k & 0xFF == ord('q'):
break
#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
这里和图片数据集预处理时一样,需要注意,由于OpenCV自带的人脸探测算法有Bug,探测得到的人脸图片有的大小是0KB,要判断一下,排除这种情况。
最后,运行这个程序,就能在摄像头中看到人脸识别的效果了!目前我得到的效果是在光线和人脸姿态比较好的情况下能准确识别出我和女朋友。
我把完整的程序放到了Github上。
目前,这个简单的人脸识别程序就完整了,当然,能够识别人脸以后还可以进一步实现一些小功能,这个会在系列后面的手记里完成,从下一篇手记开始,将记录我对迁移学习方案——FaceNet+KNN——的探索。
总结
CNN模型训练好以后只需保存模型并定义人脸预测函数供实时人脸识别程序调用即可。
本作品采用知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。要查看该许可协议,可访问 http://creativecommons.org/licenses/by-nc-sa/4.0/ 或者写信到 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA。
热门评论
请问博主在用笔记本摄像头做实时检测的时候画面卡顿吗?我借鉴了您第五篇手记的代码用在训练好的densenet二分类模型上,显示的画面有2秒的延迟,想请教一下原因,拜谢了
博主 你的第四篇手记打不开了 方便再上传一遍嘛