Tensorflow之人脸识别

  • 环境搭建
  • 开发工具
  • 截取人脸
  • 训练评估模型
  • 识别人脸
  • 总结

环境搭建

1.python3.5以上
2.opencv
3.pillow
4.tensorflow
5.keras
6.sklearn

开发工具

pycharm(社区版是免费的)
下载链接https://www.jetbrains.com/pycharm/download/#section=windows

截取人脸

这里主要使用opencv来进行人脸检测跟截取人脸图像
首先创建一个python文件,具体代码如下:

import os
import cv2
import sysfrom PIL import Imagedef CatchPICFromVideo(window_name, camera_idx, catch_pic_num, path_name):cv2.namedWindow(window_name)# 视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头cap = cv2.VideoCapture(1)#cap = cv2.VideoCapture("./video/5e4d1779fd14f7ce6526924bb99e281f.mp4")# 告诉OpenCV使用人脸检测器classfier = cv2.CascadeClassifier("./xml/haarcascade_frontalface_alt2.xml")# 识别出人脸后要画的边框的颜色,RGB格式color = (0, 255, 0)num = 0while cap.isOpened():ok, frame = cap.read()  # 读取一帧数据if not ok:breakgrey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 将当前帧图像转换成灰度图像# 人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))if len(faceRects) > 0:  # 大于0则检测到人脸for faceRect in faceRects:  # 单独框出每一张人脸x, y, w, h = faceRect# 将当前帧保存为图片img_name = '%s/%d.jpg' % (path_name, num)image = frame[y - 10: y + h + 10, x - 10: x + w + 10]cv2.imwrite(img_name, image)num += 1if num > (catch_pic_num):  # 如果超过指定最大保存数量退出循环break# 画出矩形框cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)# 显示当前捕捉到了多少人脸图片了font = cv2.FONT_HERSHEY_SIMPLEXcv2.putText(frame, 'num:%d' % (num), (x + 10, y + 10), font, 0.8, (255, 0, 255), 2)# 超过指定最大保存数量结束程序if num > (catch_pic_num): break# 显示图像cv2.imshow(window_name, frame)c = cv2.waitKey(10)if c & 0xFF == ord('q'):break# 释放摄像头并销毁所有窗口cap.release()cv2.destroyAllWindows()
if  __name__ == '__main__':if len(sys.argv) != 1:print("Usage:%s camera_id face_num_max path_name\r\n" % (sys.argv[0]))else:dirName = "leiliang"if not os.path.exists("./faces/"+dirName):os.makedirs("./faces/"+dirName)CatchPICFromVideo("Face Interception", 0, 1000, './faces/'+dirName)

训练评估模型

创建一个python文件,加载已经截取的人脸数据,具体代码如下:

import os
import sys
import numpy as np
import cv2IMAGE_SIZE = 64# 按照指定图像大小调整尺寸
def resize_image(image, height=IMAGE_SIZE, width=IMAGE_SIZE):if image is None:return Nonetop, bottom, left, right = (0, 0, 0, 0)# 获取图像尺寸h, w, _ = image.shape# 对于长宽不相等的图片,找到最长的一边longest_edge = max(h, w)# 计算短边需要增加多上像素宽度使其与长边等长if h < longest_edge:dh = longest_edge - htop = dh // 2bottom = dh - topelif w < longest_edge:dw = longest_edge - wleft = dw // 2right = dw - leftelse:pass# RGB颜色BLACK = [0, 0, 0]# 给图像增加边界,是图片长、宽等长,cv2.BORDER_CONSTANT指定边界颜色由value指定constant = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=BLACK)# 调整图像大小并返回return cv2.resize(constant, (height, width))# 读取训练数据
images = []
labels = []def read_path(path_name):for dir_item in os.listdir(path_name):# 从初始路径开始叠加,合并成可识别的操作路径full_path = os.path.abspath(os.path.join(path_name, dir_item))if os.path.isdir(full_path):  # 如果是文件夹,继续递归调用read_path(full_path)else:  # 文件if dir_item.endswith('.jpg'):image = cv2.imread(full_path)image = resize_image(image, IMAGE_SIZE, IMAGE_SIZE)# 放开这个代码,可以看到resize_image()函数的实际调用效果# cv2.imwrite('1.jpg', image)if image is not None:images.append(image)labels.append(path_name)return images, labels# 从指定路径读取训练数据
def load_dataset(path_name):images, labels = read_path(path_name)# 将输入的所有图片转成四维数组,尺寸为(图片数量*IMAGE_SIZE*IMAGE_SIZE*3)# 图片为64 * 64像素,一个像素3个颜色值(RGB)images = np.array(images)# 标注数据,文件夹下都是脸部图像labelArray = np.array([])labelName = ''i = 1for label in labels:if labelName == '':labelName = os.path.basename(label);labelArray = np.append(labelArray,[i])name = os.path.basename(label);if labelName != name:i = i+1labelName = name;return images, labelArray,i+1if __name__ == '__main__':if len(sys.argv) != 1:print("Usage:%s path_name\r\n" % (sys.argv[0]))else:images, labels,i = load_dataset("./faces")

再通过keras创建卷积神经网络模型(这里需要了解什么是卷积神经网络也是本次人脸识别的重点,可以自己百度一下这里不做详细介绍),再创建一个python文件,具体代码如下:

import os
import random
import numpy as np
from sklearn.model_selection import train_test_split
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.models import load_model
from keras import backend as Kfrom Include.load_dataset import load_dataset, resize_image, IMAGE_SIZEclass Dataset:def __init__(self, path_name):# 训练集self.train_images = Noneself.train_labels = None# 验证集self.valid_images = Noneself.valid_labels = None# 测试集self.test_images = Noneself.test_labels = None# 数据集加载路径self.path_name = path_name# 当前库采用的维度顺序self.input_shape = None# 加载数据集并按照交叉验证的原则划分数据集并进行相关预处理工作def load(self, img_rows=IMAGE_SIZE, img_cols=IMAGE_SIZE,img_channels=3):# 加载数据集到内存images, labels,nb_classes = load_dataset(self.path_name)train_images, valid_images, train_labels, valid_labels = train_test_split(images, labels, test_size=0.3,random_state=random.randint(0, 100))_, test_images, _, test_labels = train_test_split(images, labels, test_size=0.5,random_state=random.randint(0, 100))# 当前的维度顺序如果为'th',则输入图片数据时的顺序为:channels,rows,cols,否则:rows,cols,channels# 这部分代码就是根据keras库要求的维度顺序重组训练数据集if K.image_dim_ordering() == 'th':train_images = train_images.reshape(train_images.shape[0], img_channels, img_rows, img_cols)valid_images = valid_images.reshape(valid_images.shape[0], img_channels, img_rows, img_cols)test_images = test_images.reshape(test_images.shape[0], img_channels, img_rows, img_cols)self.input_shape = (img_channels, img_rows, img_cols)else:train_images = train_images.reshape(train_images.shape[0], img_rows, img_cols, img_channels)valid_images = valid_images.reshape(valid_images.shape[0], img_rows, img_cols, img_channels)test_images = test_images.reshape(test_images.shape[0], img_rows, img_cols, img_channels)self.input_shape = (img_rows, img_cols, img_channels)# 输出训练集、验证集、测试集的数量print(train_images.shape[0], 'train samples')print(valid_images.shape[0], 'valid samples')print(test_images.shape[0], 'test samples')# 我们的模型使用categorical_crossentropy作为损失函数,因此需要根据类别数量nb_classes将# 类别标签进行one-hot编码使其向量化train_labels = np_utils.to_categorical(train_labels, nb_classes)valid_labels = np_utils.to_categorical(valid_labels, nb_classes)test_labels = np_utils.to_categorical(test_labels, nb_classes)# 像素数据浮点化以便归一化train_images = train_images.astype('float32')valid_images = valid_images.astype('float32')test_images = test_images.astype('float32')# 将其归一化,图像的各像素值归一化到0~1区间train_images /= 255valid_images /= 255test_images /= 255self.train_images = train_imagesself.valid_images = valid_imagesself.test_images = test_imagesself.train_labels = train_labelsself.valid_labels = valid_labelsself.test_labels = test_labels# CNN网络模型类
class Model:def __init__(self):self.model = None# 建立模型def build_model(self, dataset):nb_classes = len(os.listdir("./faces"))+1# 构建一个空的网络模型,它是一个线性堆叠模型,各神经网络层会被顺序添加,专业名称为序贯模型或线性堆叠模型self.model = Sequential()# 以下代码将顺序添加CNN网络需要的各层,一个add就是一个网络层# model.add(Convolution2D(#     32,  # 32个滤波器 -》生成 32深度#     3,3,  #滤波器窗口 大小(3,3)#     border_mode='same',  # 过滤模式#     input_shape=dataset.input_shape  # 输入形状 就是 图片形状  # 默认 data_format:channels_last  (rows,cols,channels)# ))self.model.add(Convolution2D(32, 3, 3, border_mode='same',input_shape=dataset.input_shape))  # 1 2维卷积层self.model.add(Activation('relu'))  # 2 激活函数层self.model.add(Convolution2D(32, 3, 3))  # 3 2维卷积层self.model.add(Activation('relu'))  # 4 激活函数层self.model.add(MaxPooling2D(pool_size=(2, 2)))  # 5 池化层self.model.add(Dropout(0.25))  # 6 Dropout层self.model.add(Convolution2D(64, 3, 3, border_mode='same'))  # 7  2维卷积层self.model.add(Activation('relu'))  # 8  激活函数层self.model.add(Convolution2D(64, 3, 3))  # 9  2维卷积层self.model.add(Activation('relu'))  # 10 激活函数层self.model.add(MaxPooling2D(pool_size=(2, 2)))  # 11 池化层self.model.add(Dropout(0.25))  # 12 Dropout层self.model.add(Flatten())  # 13 Flatten层self.model.add(Dense(512))  # 14 Dense层,又被称作全连接层self.model.add(Activation('relu'))  # 15 激活函数层self.model.add(Dropout(0.5))  # 16 Dropout层self.model.add(Dense(nb_classes))  # 17 Dense层self.model.add(Activation('softmax'))  # 18 分类层,输出最终结果# 输出模型概况self.model.summary()# 训练模型def train(self, dataset, batch_size=20, nb_epoch=100, data_augmentation=True):sgd = SGD(lr=0.01, decay=1e-6,momentum=0.9, nesterov=True)  # 采用SGD+momentum的优化器进行训练,首先生成一个优化器对象self.model.compile(loss='categorical_crossentropy',optimizer=sgd,metrics=['accuracy'])  # 完成实际的模型配置工作# 不使用数据提升,所谓的提升就是从我们提供的训练数据中利用旋转、翻转、加噪声等方法创造新的# 训练数据,有意识的提升训练数据规模,增加模型训练量if not data_augmentation:self.model.fit(dataset.train_images,dataset.train_labels,batch_size=batch_size,nb_epoch=nb_epoch,validation_data=(dataset.valid_images, dataset.valid_labels),shuffle=True)# 使用实时数据提升else:# 定义数据生成器用于数据提升,其返回一个生成器对象datagen,datagen每被调用一# 次其生成一组数据(顺序生成),节省内存,其实就是python的数据生成器datagen = ImageDataGenerator(featurewise_center=False,  # 是否使输入数据去中心化(均值为0),samplewise_center=False,  # 是否使输入数据的每个样本均值为0featurewise_std_normalization=False,  # 是否数据标准化(输入数据除以数据集的标准差)samplewise_std_normalization=False,  # 是否将每个样本数据除以自身的标准差zca_whitening=False,  # 是否对输入数据施以ZCA白化rotation_range=20,  # 数据提升时图片随机转动的角度(范围为0~180)width_shift_range=0.2,  # 数据提升时图片水平偏移的幅度(单位为图片宽度的占比,0~1之间的浮点数)height_shift_range=0.2,  # 同上,只不过这里是垂直horizontal_flip=True,  # 是否进行随机水平翻转vertical_flip=False)  # 是否进行随机垂直翻转# 计算整个训练样本集的数量以用于特征值归一化、ZCA白化等处理datagen.fit(dataset.train_images)# 利用生成器开始训练模型self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels,batch_size=batch_size),samples_per_epoch=dataset.train_images.shape[0],nb_epoch=nb_epoch,validation_data=(dataset.valid_images, dataset.valid_labels))MODEL_PATH = './model/faces.face.model.h5'def save_model(self, file_path=MODEL_PATH):self.model.save(file_path)def load_model(self, file_path=MODEL_PATH):self.model = load_model(file_path)def evaluate(self, dataset):score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose=1)print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100))# 识别人脸def face_predict(self, image):# 依然是根据后端系统确定维度顺序if K.image_dim_ordering() == 'th' and image.shape != (1, 3, IMAGE_SIZE, IMAGE_SIZE):image = resize_image(image)  # 尺寸必须与训练集一致都应该是IMAGE_SIZE x IMAGE_SIZEimage = image.reshape((1, 3, IMAGE_SIZE, IMAGE_SIZE))  # 与模型训练不同,这次只是针对1张图片进行预测elif K.image_dim_ordering() == 'tf' and image.shape != (1, IMAGE_SIZE, IMAGE_SIZE, 3):image = resize_image(image)image = image.reshape((1, IMAGE_SIZE, IMAGE_SIZE, 3))# 浮点并归一化image = image.astype('float32')image /= 255# 给出输入属于各个类别的概率,这里是二值类别,则该函数会给出输入图像属于0和1的概率各为多少result = self.model.predict_proba(image)print('result:', result)print(max(result[0]))if max(result[0]) < 0.99:return -1# 给出类别预测result = self.model.predict_classes(image)# 返回类别预测结果return result[0]dataset = Dataset('./faces/')
dataset.load()
if __name__ == '__main__':model = Model()model.build_model(dataset)# 先前添加的测试build_model()函数的代码model.build_model(dataset)# 测试训练函数的代码model.train(dataset)if __name__ == '__main__':model = Model()model.build_model(dataset)model.train(dataset)if not os.path.exists("./model"):os.makedirs("./model")model.save_model(file_path='./model/faces.face.model.h5')if __name__ == '__main__':# 评估模型model = Model()model.load_model(file_path='./model/faces.face.model.h5')model.evaluate(dataset)

识别人脸

加载训练模型得到的结果,进行人脸识别,创建一个python文件,具体代码如下:

import os
import cv2
import sys
import gc
from face_train import Modelif __name__ == '__main__':if len(sys.argv) != 1:print("Usage:%s camera_id\r\n" % (sys.argv[0]))sys.exit(0)# 加载模型model = Model()model.load_model(file_path='./model/faces.face.model.h5')# 框住人脸的矩形边框颜色color = (0, 255, 0)# 捕获指定摄像头的实时视频流cap = cv2.VideoCapture(1)#cap = cv2.VideoCapture("./video/5e4d1779fd14f7ce6526924bb99e281f.mp4")# 人脸识别分类器本地存储路径cascade_path = "./xml/haarcascade_frontalface_alt2.xml"# 循环检测识别人脸while True:ret, frame = cap.read()  # 读取一帧视频if ret is True:# 图像灰化,降低计算复杂度frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)else:continue# 使用人脸识别分类器,读入分类器cascade = cv2.CascadeClassifier(cascade_path)# 利用分类器识别出哪个区域为人脸faceRects = cascade.detectMultiScale(frame_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]faceID = model.face_predict(image)print(faceID)cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness=2)# 文字提示是谁if faceID != -1:name = os.listdir("./faces")[faceID-1]cv2.putText(frame, name,(x+10, y+10),  # 坐标cv2.FONT_HERSHEY_SIMPLEX,  # 字体0.6,  # 字号(255, 0, 255),  # 颜色1)  # 字的线宽else:passcv2.imshow("faces", frame)# 等待10毫秒看是否有按键输入k = cv2.waitKey(10)# 如果输入q则退出循环if k & 0xFF == ord('q'):break# 释放摄像头并销毁所有窗口cap.release()cv2.destroyAllWindows()

总结

以上的代码仅做参考,其中最重要的是卷积神经网络。

Tensorflow之人脸识别相关推荐

  1. python爬取网易藏宝阁手机版_Python3 TensorFlow打造人脸识别智能小程序

    Python3 TensorFlow打造人脸识别智能小程序 第1章 课程导学 本章节主要介绍课程的主要内容.核心知识点.课程涉及到的应用案例.深度学习算法设计通用流程.适应人群.学习本门课程的前置条件 ...

  2. 基于Python的OpenCV+TensorFlow+Keras人脸识别实现

    前言:本节要讲的人脸识别主要是借鉴了 一位研究生前辈的文章 我只是在他的基础上进行了改动,让代码能在现在的TensorFlow2.X 等的环境下运行 先看一下效果图 完整工程及源代码请点击链接下载:人 ...

  3. Python+Tensorflow+Opencv人脸识别(任意数量人脸)

    Python+Tensorflow+Opencv的人脸识别 简单的人脸识别 准备工作 开始--先获取必要的人脸图像 训练--分类吧 识别大脸 简单的人脸识别 一直想做机器学习的东东,最近由于工作的调整 ...

  4. python 深度学习源码_「深度学习」用TensorFlow实现人脸识别(附源码,快速get技能)...

    本文将会带你使用python码一个卷积神经网络模型,实现人脸识别,操作难度比较低,动手跟着做吧,让你的电脑认出你那帅气的脸. 由于代码篇幅较长,而且最重要的缩进都没了,建议直接打开源码或者点击分享-& ...

  5. 【TensorFlow】人脸识别OpenFace、Face-recognition、Insightface和FaceNet源码运行

    比较人脸识别OpenFace.Face-recognition.Insightface: FaceNet源码运行 https://github.com/davidsandberg/facenet 1. ...

  6. Android TensorFlow 实时人脸识别

    ,这是TF实现的MobileFaceNet项目,经过该步骤,我们将训练得到一个人脸识别的模型. 在模式部署到Android时,使用TensorFlow Lite解决方案,将训练得到的模型经过优化压缩, ...

  7. Android从零开始配置opencv+tensorflow进行人脸识别+口罩识别(二:opencv展示当前图像并作适当调整)

    前言 上一章已经成功导入了opencv,但并没说如何展示从摄像头获取图像并展示出来,这章将简单的说说怎么展示,以及里面出现的问题作修正 一.使用opencv正常展示图像 首先准备一个空的activit ...

  8. python基于tensorflow的人脸识别系统设计与实现.zip(论文+源码)

    摘 要 人脸识别技术是模式是别和计算机视觉研究中的一个重要领域,在边防安全.视频监控.身份验证等方面有重要的应用价值.人脸检测是快速.准确识别人脸的前提,其目的是将人脸从图像背景中检测出来.传统的课堂 ...

  9. 基于TensorFlow开发人脸识别

    正在开发中,待补充

最新文章

  1. 【模板】树链剖分 P3384
  2. python3 tensorflowprint错误_解决import tensorflow as tf 出错的原因
  3. Minor【 PHP框架】1.简介
  4. 在linux中dns不安装coching,ubuntu 8.04下openldap的安装和使用
  5. Codeforces Round #371 (Div. 2) C. Sonya and Queries —— 二进制压缩
  6. 基于java员工管理系统设计(含源文件)
  7. 一、app更新提示后台接口开发-(2)数据库表设计
  8. android多版本打包,Android的持续化集成及多版本打包
  9. 关于linux安装openoffice无法启动
  10. python实现一个土豆聊天 potato chat 机器人
  11. 早鸟票开售 | 世界级大师Sanjiv和他的敏捷领导力(CAL)认证课程
  12. 网络编程项目 (网络词典)
  13. Cocos Creator | 碰撞检测优化-四叉树
  14. 单词前缀dia/dis/duo/en/epi/eu等衍生单词(辅助记忆)
  15. ubantu下安装redis
  16. STM32F103 - 延迟函数 -unfinished -unfinished-unfinished
  17. 第四讲:统计分析之良率和敏感度分析
  18. 既想吸猫又不想当猫奴?这款治愈系的机器人或许会适合你
  19. Android R 11 后台定位权限没有 始终允许选项的解决方法
  20. CoSOD之Re-thinking Co-Salient Object Detection

热门文章

  1. 编写一个函数,由实参传来一个字符串,统计次字符串中字母、数字、空格和其他字符的个数,在主函数 中输入字符串以及输出上述的结果
  2. 实战突击JAVA开发项目_《实战突击Java项目开发案列整合》随书资料(视频+源码)_源雷技术空间...
  3. 亿万富翁Calvin Ayre梭哈BCH!
  4. dnf连接服务器黑屏xp系统,xp系统开机黑屏的解决办法
  5. Cesium 无人机巡检实时视频投射及模拟数据采集
  6. python lexical chain
  7. rabbitmq重启
  8. 基于LSI的 职位描述JD 匹配
  9. C++ Primer Plus 读书笔记
  10. 你用过“趣步”吗?听说最近区块链韭菜们都在跑步!