记录第一次个人实现人脸识别过程和流程,供今后方便参考,目前为止对神经网络的理论部分暂未学习,故因此本项目/实验仅是对官方的API文档学习后进行的简单逻辑拼凑
做的不好,仅供参考…
注:使用Jupyter运行代码效果更佳,下面给出的代码形式为一个个在Jupyter里的代码cell
项目/实验实现功能:目前为止能较为准确根据照片识别本人的人脸,调整训练集(用于训练的照片)可实现识别多个人脸(暂未进行大数据集测试,效果未知,仅供以后学习参考)
传入照片的路径,读取照片
传入load_image_file()的结果,可以提取出人脸 (不一定每次都能提取到)
返回的是人脸在图片中的位置list,[上,右,下,左],顺时针返回
传入face_locations()的结果
返回长度为128的一个列表,存放人脸128个特征信息
使用了序贯模型,并且只有三层连接层
只需要把list转换成array
import glob
from matplotlib import image
import tensorflow as tf
import face_recognition
from PIL import Image
import numpy as np
from tensorflow import keras
# 有多少种人脸
OUTPUT_NODE = 0
# 训练集数量
TRAIN_DATA_SIZE = 0
# 照片存放的文件夹
train_dir = "F:\project\人脸识别\Train_set\*.jpg"
#导入照片提取里面所有的.jpg文件 file_list存放的是每一张图片的路径的list
file_list = glob.glob(train_dir)
# 测试集特征存储数组
datas = []
# 标签存储数组即有多少中人脸,如:甲乙丙 labels长度为 3
labels = []
count = 0
for image_path in file_list:
# print(image_path)
# 读取人脸照片
image = face_recognition.load_image_file(image_path)
# 扣人脸
face_locations = face_recognition.face_locations(image)
# print(face_location)
for face_location in face_locations:
# 找到人脸位置,返回根据顺时针返回位置:上右下左
# print("这张照片人脸的位置为上:{},下{},左{},右{}".format(top,bottom,left,right))
top,right,bottom,left = face_location
# 构造人脸的矩阵
face_image = image[top:bottom, left:right]
# 特征提取
face_encode = face_recognition.face_encodings(face_image)
# 手动为每一张用于训练的照片打标签
if (len(face_encode) != 0):
if (count == 2):
datas.append(face_encode)
labels.append(2)
elif (count == 3):
datas.append(face_encode)
labels.append(3)
else:
datas.append(face_encode)
labels.append(1)
#下面标注的代码是检查人脸是否扣成功
# pil_image = Image.fromarray(face_image)
# print(pil_image)
# file_name = 'F:\project\人脸识别\TrainFace'
# pil_image.save(open(file_name + '\人脸' + str(count) + '.png','wb'),'png')
# pil_image.close()
count += 1
TRAIN_DATA_SIZE = len(datas)
OUTPUT_NODE = len(set(labels))
def generate():
# list转换成数组
train_x,train_y = np.array(datas),np.array(labels)
return train_x,train_y
generate()
与构造训练集代码类似
def initTestSet():
test_dir = "F:\project\人脸识别\Test_set\*.jpg"
file_test_list = glob.glob(test_dir)
# ans存放扣好的人脸
ans = []
for image_path in file_test_list:
image = face_recognition.load_image_file(image_path)
face_locations = face_recognition.face_locations(image)
print(face_locations)
# print(face_location)
for face_location in face_locations:
# 找到人脸位置,返回根据顺时针返回位置:上右下左
# print("这张照片人脸的位置为上:{},下{},左{},右{}".format(top,bottom,left,right))
top,right,bottom,left = face_location
# 构造人脸的矩阵
face_image = image[top:bottom, left:right]
print(face_encode)
ans.append(face_image)
return ans
test_image = initTestSet()
def train_face():
# 获取训练集
train_x, train_y = generate()
# 将训练集转换为张量,可放入显卡计算加快运行速度,前提tenserflow为GPU版
dataset = tf.data.Dataset.from_tensor_slices((train_x,train_y))
print(dataset)
# 数据打包
dataset = dataset.batch(32)
# 数据集重复一次,也可多次按需填
dataset = dataset.repeat()
# 序贯模型 多个网络层的线性叠加(暂时不知原理)
model = keras.Sequential([
# 实现全连接层,输入第一个参数与encoding结果一致即128
# 第二个参数为激活函数(暂时不知原理)这里的激活函数为线性整流函数作用:小于0变为0,大于0不变
keras.layers.Dense(128,activation=tf.nn.relu),
keras.layers.Dense(128,activation=tf.nn.relu),
# 输出类别是从0开始计算,由于label我是从1开始算,所以需要加1
keras.layers.Dense(OUTPUT_NODE + 1,activation=tf.nn.softmax)
# softmax 多分类函数
])
# 配置训练方法时告知优化器、损失函数和准确率
model.compile(optimizer="adam",loss='sparse_categorical_crossentropy',metrics=['accuracy'])
# 训练模型
model.fit(dataset,epochs=10,steps_per_epoch = 30)
# 保存模型,也可不存
model.save('model/face_model.h5')
train_face()
训练结果
def predict_image(image):
# 载入已经保存好的模型,没存可以忽略这一步
model = tf.keras.models.load_model('model/face_model.h5')
# 遍历测试集
for it in image:
# 特征提取
face_encode = face_recognition.face_encodings(it)
# 人脸识别,也能说预测这张照片里的人脸属于哪一类
# 在最新的ts中,只有predict没有predict_classes
# predict只会得到相关的矩阵,应该可以写成下面这样代替
'''
predictions1 = model.predict(np.array(face_encode[j]).reshape(1, 128))
print(predictions1)
if np.max(predictions1[0]) > 0.90:
print(np.argmax(predictions1[0]).dtype)
'''
prediction = model.predict_classes(np.array(face_encode))
# 输出结果
print(prediction)
print(len(test_image))
# 传入测试集 里面装的是人脸的矩阵
predict_image(test_image)
输出结果