关于
本博客内容在python环境下实现了人脸识别的基本功能。
实现方法总体上与这篇博客相同,该博主的工程是在终端下运行,考虑到这种方法的不便,本博客对该方法进行了改进,可以直接在python IDE环境下编译运行。
前提环境
- python 3.6.5
- opencv 3.3.1
- numpy 1.14.3
- dlib 19.7.0 (配置方法可见这篇文章)
人脸识别
人脸识别总体上分为人脸检测、特征点定位、人脸对齐、特征向量提取、相似度衡量这几个步骤(不区分先后顺序,因为构建人脸特征向量数据库和进行单张人脸识别这两大部分的步骤有所不同)
工程目录结构
- E:\
- candidate_face
- liuyifei.jpg
- tangyan.jpg
- yangmi.jpg
- yangzi.jpg
- zhoudongyu.jpg
- pyproject
- shape_predictor_68_face_landmarks.dat
- dlib_face_recognition_resnet_model_v1.dat
- FaceRecognition.py
- test.jpg
- candidate_face
其中candidate_face文件夹中存放的是5个人(每人一张)的照片,届时用来提取她们各自的特征向量用来对比,pyproject文件夹中的shape_predictor_68_face_landmarks.dat是用来进行人脸关键点检测的参数模型,dlib_face_recognition_resnet_model_v1.dat是经过深度学习得到的参数模型,可以在这里下载获得。test.jpg是测试时的单张人脸图像,我这里是杨幂的图,如下图所示:
具体流程
- 读取候选人文件夹下每个人的人脸数据,然后对其中每个人脸进行人脸检测,提取人脸特征向量
- 对测试人员的人脸图像进行相同的操作
- 求得测试人员特征向量和每个候选人的人脸向量的欧氏距离,取距离最小的即为人脸识别结果
代码
import os,dlib,numpy,cv2
predictor_path = 'shape_predictor_68_face_landmarks.dat'
face_rc_model_path = 'dlib_face_recognition_resnet_model_v1.dat'
face_folder_path = 'E:\candidate_face'
test_img_path = 'E:\\test.jpg'
# 读取人脸集、人脸标签
def read_data(path):
try:
pic_name_list = os.listdir(path)
pic_list = []
for i in pic_name_list:
whole_path = os.path.join(path, i)
img = cv2.imread(whole_path)
pic_list.append(img)
except IOError:
print('read error')
return False
else:
print('read successfully')
return pic_name_list, pic_list
# 人脸检测器
detector = dlib.get_frontal_face_detector()
# 关键点检测器
feature_point = dlib.shape_predictor(predictor_path)
# 人脸参数模型
feature_model = dlib.face_recognition_model_v1(face_rc_model_path)
# 候选人特征向量列表
descriptors = []
if __name__ == '__main__':
name_list, pic_list = read_data(face_folder_path)
for i in pic_list:
# 人脸检测
dets = detector(i, 1)
for k, d in enumerate(dets):
# 关键点检测
shape = feature_point(i, d)
# 提取特征,128维
face_feature = feature_model.compute_face_descriptor(i, shape)
v = numpy.array(face_feature)
descriptors.append(v)
'''
对单张人脸进行识别
'''
test_img = cv2.imread(test_img_path)
dets = detector(test_img, 1)
for k, d in enumerate(dets):
shape = feature_point(test_img, d)
test_feature = feature_model.compute_face_descriptor(test_img, shape)
test_feature = numpy.array(test_feature)
dist = []
count = 0
for i in descriptors:
dist_ = numpy.linalg.norm(i-test_feature)
print('%s : %f' % (name_list[count], dist_))
dist.append(dist_)
count += 1
# 返回距离最小的下标
min_dist = numpy.argmin(dist)
# 截取姓名字符串,去掉末尾的.jpg
result = name_list[min_dist][:-4]
print(result)
闲话
这个项目只是一个简单的人脸识别demo,使用的都是别人做好的轮子,所以实现起来看似简单,但深究起来里面其实还有很多值得学习的地方,比如用到的两个最重要的模型,它们是怎么通过深度残差网络训练得到的、以及单张测试图片经过这个模型的前向传播的具体过程、以及这个项目还未实现的人脸对齐算法、以及人脸识别的精度问题等等都是值得深入探索的,任重而道远~
能力有限,写作水平拙劣,还望各位看官不吝赐教