基于flask+opencv+sklearn+tensorflow的人脸识别系统(一)

近年以来,人工智能技术飞速发展,其主要分为鉴别和生成两个方面,其中人脸识别技术是其鉴别技术的重要分支,本文详细讲解使用opencv+sklearn+tensorflow技术,实现人脸识别的学习性项目。

一、系统功能分析

本项目具体功能模块如下所示:

1、采样样本照片

调用本地计算机摄像头采集照片作为样本,设置使用快捷键进行采样和取样,一次性可以多张照片,采样照片越多,人脸识别的成功率越高。

2、图片处理

将采集到原始图像转化为标准数据文件,即数据集。

3、深度学习

创建深度学习模型,学习训练、将训练结果保存为".h5"文件.

4、人脸识别

使用训练所得的模型实现人脸识别功能,即可以从本地摄像头识别,还可从网络摄像头识别。

二、系统流程分析

项目实现的流程如下所示:

三、技术分析

项目主要用到以下的框架:

(1)Flask

典型的Python Web开发框架

(2)opencv-Python

它是OpenCV的Python接口,一个开源发行的跨平台计算机视觉库,轻量级且高效(由一系列C函数和少量C++类构成),提供Python,Rupy,MATLAB等语言的接口,实现图像处理和计算机视觉方面的通用算法。

(3)sklearn

机器学习中常用第三方模块,对常用机器学习方法进行封装,包括回归、降维、分类、聚类等方法。

(4)tensorflow

TensorFlow是一个由Google Brain团队开发的开源机器学习框架。最初是作为Google内部工具而开发的,但随后在2015年被开源,以便更广泛的社群能够利用和贡献于这个框架。TensorFlow支持从研究到生产的全面工作流程,包括模型设计、训练、优化和部署。

四、框架安装

安装以上框架需要使用以下命令:

pip install flask   //安装Flask框架

pip install opencv-python  //安装opencv-python框架

pip install scikit-learn  //安装sklearn框架

pip install tensorflow //安装tensoflow框架

五、照片样本采集

样本采集模块getCameraPics.py基本摄像头采集视频流中的数据,截取人脸照片作为样本并存储。具体代码如下:


import os
import cv2
import random
import numpy as np
from tensorflow.python.keras.utils import np_utils
from keras.models import Sequential,load_model
from keras.layers import Dense,Activation,Convolution2D,MaxPooling2D,Flatten,Dropout
from sklearn.model_selection import train_test_split

def cameraAutoForPictures(saveDir='data/'):
    "调用计算机摄像头来自动获取图片"
    if not os.path.exists(saveDir):
        os.makedirs(saveDir)
    count=1
    cap=cv2.VideoCapture(0)
    width,height,w=640,480,360
    cap.set(cv2.CAP_PROP_FRAME_WIDTH,width)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT,height)
    crop_w_start=(width-w)//2
    crop_h_start=(height-w)//2
    print('width:',width)
    print('height:',height)
    while True:
        ret,frame=cap.read()
        frame=frame[crop_h_start:crop_h_start+w,crop_w_start:crop_w_start+w]
        frame=cv2.flip(frame,1,dst=None)
        cv2.imshow("capture",frame)
        action=cv2.waitKey(1)&0xff
        if action==ord('c'):
            saveDir=input(u"请输入新的存储目录:")
            if not os.path.exists(saveDir):
                os.makedirs(saveDir)
        elif action==ord('p'):
            cv2.imwrite("%s/%d.jpg" % (saveDir,count),cv2.resize(frame,(224,224),interpolation=cv2.INTER_AREA))
            print(u"%s:%d张图片" % (saveDir,count))
            count+=1
        if action==ord('q'):
                    break
    cap.release()
    cv2.destroyAllWindows()

if __name__=='__main__':
    cameraAutoForPictures(saveDir='data/guanxi/')

通过上述代码,启动摄像头后借助键盘完成图片获取操作,其中按键C(change)表示设置一个存储样本照片的目录,按键P(photo)表示执行截图操作,按键Q(quit)表示退出拍摄。运行后打开计算机本地摄像头,按下键盘中P会截取照片,并保存在data/guanxi/目录中。

六、深度学习和训练

处理样本照片,形成数据集,构建卷积网络模型并使用数据集进行训练,将训练后的模型保存为“.h5"模型文件,根据模型文件实现人脸识别。

1、原始图像预处理

原始图像预处理代码文件dataHelper.py如下:

import os
import cv2
import time

def readAllImg(path,*suffix):
    "基于后缀读取文件"
    try:
        s=os.listdir(path)
        resultArray=[]
        for i in s :
            if endwith(i,suffix):
                document=os.path.join(path,i)
                img=cv2.imread(document)
                resultArray.append(img)
    except IOError:
        print("Error")
    else:
        print("读取成功")
        return resultArray
    
def endwith(s,*endstring):
    "对字符串的后续和标签进行匹配" 
    resultArray=map(s.endswith,endstring)
    if True in resultArray:
        return True
    else:
        return False
        

def readPicSaveFace(sourcePath,objectPath,*suffix):
    "图片标准化存储"
    if not os.path.exists(objectPath):
        os.makedirs(objectPath)
    try:
        resultArray=readAllImg(sourcePath,*suffix)
        count=1
        face_cascade=cv2.CascadeClassifier('config/haarcascade_frontalface_alt.xml')
        for i in resultArray:
            if type(i)!=str:
                gray=cv2.cvtColor(i,cv2.COLOR_BGR2GRAY)
                faces=face_cascade.detectMultiScale(gray,1.1,5)
                print(faces)
                for (x,y,w,h) in faces:
                    listStr=[str(int(time.time()))]
                    fileName=".join(listStr)"
                    f=cv2.resize(gray[y:(y+h),x:(x+w)],(200,200))
                    cv2.imwrite(objectPath+os.sep+'%s.jpg'%fileName,f)
                    count+=1
    except Exception as e :
        print("Exception: ",e)
    else:
        print("Read "+str(count-1)+' Faces to Destination'+objectPath)

if __name__=='__main__':
    print('dataProcessing!!!')
    readPicSaveFace('data/guanxi/','dataset/chengsongtao/','jpg','JPG','png','PNG','tiff')

代码首先检测是否存在标准化存储目录,如无则创建之,其次读入所有样本图片,使用OpenCV自带的人脸检测haarcascade_frontalface_alt.xml分类器获取人脸定位,并保存为大小为200*200大小的灰度图像。OpenCV-Python的分类器在lib/site-page/data文件夹中,复制相应的分类器并保存在项目目录下的config文件夹中,其中cv2.CascadeClassifier.detectMultiScale() 函数各个参数及返回值的含义为:

        image:待检测图像,通常为灰度图像。
        scaleFactor:表示在前后两次相继的扫描中,搜索窗口的缩放比例。
        minNeighbors:表示构成检测目标的相邻矩形的最小个数。默认情况下,该值为 3,意味着有 3 个以上的检测标记存在时,才认为人脸存在。如果希望提高检测的准确率,可以将该值设置得更大,但同时可能会让一些人脸无法被检测到。
        flags:该参数通常被省略。在使用低版本 OpenCV(OpenCV 1.X 版本)时,它可能会被设置为 CV_HAAR_DO_CANNY_PRUNING,表示使用 Canny 边缘检测器来拒绝一些区域。
        minSize:目标的最小尺寸,小于这个尺寸的目标将被忽略。
        maxSize:目标的最大尺寸,大于这个尺寸的目标将被忽略。
        objects:返回值,目标对象的矩形框向量组。

如果需要处理多人的样本图片,需要在__main__下添加多个对应的的处理目录,运行上述文件后,会在dataset目录下得到处理后照片。

2、数据集处理类

编写faceRegnitionModel.py文件,功能是通过深度学习和训练构建人脸识别模块,将训练后得到的模型文件face.h5保存在本地。类DataSet是保存和读取格式化后的训练数据,具体代码如下:

class DataSet(object):
    def __init__(self,path):
        "初始化"
        self.num_classes=None
        self.X_train=None
        self.X_test=None
        self.Y_train=None
        self.Y_test=None
        self.img_size=128
        self.extract_data(path)
    
    def read_file(self,path):
        img_list=[]
        label_list=[]
        dir_counter=0
        IMG_SIZE=128
        for child_dir in os.listdir(path):
            child_path=os.path.join(path,child_dir)
            for dir_image in os.listdir(child_path):
                if dir_image.endswith('jpg'):
                    img=cv2.imread(os.path.join(child_path,dir_image))
                    resized_img=cv2.resize(img,(IMG_SIZE,IMG_SIZE))
                    recolored_img=cv2.cvtColor(resized_img,cv2.COLOR_BGR2GRAY)
                    img_list.append(recolored_img)
                    label_list.append(dir_counter)
            dir_counter+=1
        img_list=np.array(img_list)
        return img_list,label_list,dir_counter
    
    def extract_data(self,path):
        imgs,labels,counter=self.read_file(path)
X_train,X_test,Y_train,Y_test=train_test_split(imgs,labels,test_size=0.2,random_state=random.randint(0,100))
        X_train=X_train.reshape(X_train.shape[0],1,self.img_size,self.img_size)/255.0
        X_test=X_test.reshape(X_test.shape[0],1,self.img_size,self.img_size)/255.0
        X_train=X_train.astype('float32')
        X_test=X_test.astype('float32')
        Y_train=np_utils.to_categorical(Y_train,num_classes=counter)
        Y_test=np_utils.to_categorical(Y_test,num_classes=counter)

        self.X_train=X_train
        self.X_test=X_test
        self.Y_train=Y_train
        self.Y_test=Y_test
        self.num_classes=counter
  
    def check(self):
        "校验"
        print('num of dim :',self.X_test.ndim)
        print('shape: ',self.X_test.shape)
        print('size: ',self.X_test.size)
        print('num of dim : ',self.X_train.ndim)
        print('shape: ',self.X_train.shape)
        print('size: ',self.X_train.size)
    
    def read_name_list(self,path):
        name_list=[]
        for child_dir in os.listdir(path):
            name_list.append(child_dir)
        return name_list

函数extract_data()抽取数据,使用机器学习SKlearn中的函数train_test_split将原始数据集按照一定比例划分训练集和测试集对模型进行训练,通过reshape()将图片转换成128*128的灰度图像,通过函数astype()将图片转换为float32数据类型。其中train_test_split()函数原型如下所示:

train_test_split(train_data,train_target,test_size,random_state)

各参数具体说明如下:

        train_data: 表示被划分的样本特征集

        train_target:表示划分的样本标签

        test_size: 表示样本按比例划分,返回第的第一个参数值为train_data*test_size

        random_state:表示随机种子,当为整数时,不管循环多少次X_train与第一次相同,其值不能为小数。

函数check(self)实现数据校验,打印输出图片的基本信息,函数read_file(self,path) 读取指定路径的图片信息。函数read_name_list(self,path)读取训练数据集。

3、模型构建与训练

类Model创建一个基于CNN的人脸识别模型,开始构建数据模型并进行训练,具体代码如下:

class Model(object):
    "人脸识别模型"
    FILE_PATH="face.h5"
    IMAGE_SIZE=128

    def __init__(self):
        self.model=None

    def read_trainData(self,dataset):
        self.dataset=dataset
    
    def build_model(self):
        self.model=Sequential()
        self.model.add(
            Convolution2D(
                filters=32,
                kernel_size=(5,5),
                padding='same',
                input_shape=self.dataset.X_train.shape[1:]
            )
        )
        self.model.add(Activation('relu'))
        self.model.add(
            MaxPooling2D(
                pool_size=(2,2),
                strides=(2,2),
                padding='same'
            )
        )
        self.model.add(
            Convolution2D(
                filters=64,
                kernel_size=(5,5),
                padding='same'
            )
        )
        self.model.add(Activation('relu'))
        self.model.add(
            MaxPooling2D(
                pool_size=(2,2),
                strides=(2,2),
                padding='same'
            )
        )
        self.model.add(Flatten())
        self.model.add(Dense(1024))
        self.model.add(Activation('relu'))
        self.model.add(Dense(self.dataset.num_classes))
        self.model.add(Activation('softmax'))
        self.model.summary()
    
    def train_model(self):
         self.model.compile(
             optimizer='adam',
             loss='categorical_crossentropy',
             metrics=['accuracy'] )
         self.model.fit(self.dataset.X_train,self.dataset.Y_train,epochs=10,batch_size=10)
    
    def evaluate_model(self):
        print('\nTesting--------------')
        loss,accuracy=self.model.evaluate(self.dataset.X_test,self.dataset.Y_test)
        print('test loss: ', loss)
        print('test accuracy: ',accuracy)
    
    def save(self,file_path=FILE_PATH):
        print('Model Saved Finished!!!')
        self.model.save(file_path)
    
    def load(self,file_path=FILE_PATH):
        print('Model Loaded Successful!!!')
        self.model=load_model(file_path)
    
    def predict(self,img):
        img=img.reshape((1,1,self.IMAGE_SIZE,self.IMAGE_SIZE))
        img=img.astype('float32')
        img=img/255.0
        result=self.model.predict_proba(img)
        max_index=np.argmax(result)
        return max_index.result[0][max_index]

类Model创建一个基于CNN的人脸识别模型,其模型结构如下所示:

模型输入为1*128*128,训练、评估、保存效果如下所示:

调用上面的函数,打印输出模型训练和评估结果,具体的代码如下:

if __name__=='__main__':
    dataset=DataSet('dataset/')
    model=Model()
    model.read_trainData(dataset)
    model.build_model()
    model.train_model()
    model.evaluate_model()
    model.save()

七、人脸识别

使用人工智能技术实现深度学习后,生成一个数据模型文件, 通过调用这个模型文件可以实现人脸识别功能,实例cameraDemp.py文件,通过OpenCV-Python直接调用摄像头实现人脸识别功能,代码如下所示:

from faceRegnitionModel import  Model

threshold=0.7  #如果模型认为概率高于70%则显示为模型中已有的人物

def read_name_list(path):
    "读取训练数据集"
    name_list=[]
    for child_dir in os.listdir(path):
        name_list.append(child_dir)
    return name_list

class Camera_reader(object):    
    def __init__(self):
        self.model=Model()
        self.model.load()
        self.img_size=128
    
    def build_camera(self):
        "调用摄像头实现实时人脸识别"
        name_list=read_name_list('dataset/')
        cameraCapture=cv2.VideoCapture(0)
        face_cascade=cv2.CascadeClassifier('config/haarcascade_frontalface_alt.xml')
        while True:
            ret,frame=cameraCapture.read()
            gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
            faces=face_cascade.detectMultiScale(gray,1.05,5) 
            for (x,y,w,h) in faces:
                ROI=gray[x:x+w,y:y+h]
                ROI=cv2.resize(ROI,(self.img_size,self.img_size),interpolation=cv2.INTER_LINEAR)
                label,prob=self.model.predict(ROI)                          
                if prob>threshold:
                    show_name=name_list[label]
                else:
                    show_name="Stranger"
                cv2.putText(frame,show_name,(x,y-20),cv2.FONT_HERSHEY_SIMPLEX,1,255,2)
                frame=cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
            cv2.imshow("capture",frame)
            action=cv2.waitKey(1)&0xff
            if action==ord('q'):
                break     
       
        cameraCapture.release()
        cv2.destroyAllWindows()
              
if __name__=='__main__':
    camera=Camera_reader()
    camera.build_camera()

具体的执行逻辑是先开启摄像头,再获取视频帧 ,最后是调用脸部检测分类器,获取脸部视频帧区域参数 ,调用模型进行识别并在原帧上进行标记。执行后会开启摄像头并识别人物且进行标记。

  • 24
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值