为了账号安全,请及时绑定邮箱和手机立即绑定

基于OpenCV和Keras实现人脸识别系列——五、用CNN模型实现实时人脸识别

基于OpenCV和Keras的人脸识别系列手记:

项目完整代码参见Github仓库

本篇手记是上面这一系列的第五篇。

这篇手记我们将最终实现人脸识别的功能,和前面的几篇手记结合起来就是一个完整的实战项目:

  1. 用OpenCV打开摄像头
  2. 利用OpenCV自带的人脸探测器探测人脸
  3. 采集不同人的人脸并结合LFW的人脸数据准备数据集
  4. 对数据集进行预处理
  5. 用自己的数据集训练神经网络模型用于人脸识别
  6. 用训练好的数据集实现人脸识别

在开始上面的第六项之前,要先把之前训练好的CNN模型存储下来,并定义一个预测人脸的函数,最后在人脸识别程序中加载存储下来的模型并调用预测函数识别人脸。
face_train_keras.py文件中定义save_modelload_modelface_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。

点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消