本项目基于python,用到了opencv、dlib等开发包,实现了单张训练样本的人脸识别,有较为友好的UI界面,识别速度经优化后尚可。
实现上思路与这篇博客一致,解决了这篇博客中存在的几个问题:
基于以上问题,采取的解决方案如下:
首先运行FaceRecognition.py,会经历:读取人脸集、人脸检测、提取人脸特征向量、存储人脸特征向量、对单张测试人脸图进行识别、打印识别结果 的过程。
然后运行main.py,会经历:初始化界面、加载各种参数模型、手动选择单张人脸测试图、基于opencv人脸检测器检测人脸、提取该人脸特征向量、计算欧氏距离、找出距离最小的人脸标签、输出人脸识别结果 这么几个过程。
这个项目目前bug多多,准确率也还有很大提高空间,欢迎各位多多交流,这个项目的更多详情请见这里,如果对你也有所帮助,请轻轻点个star(别太重了,怕疼(⊙o⊙)…)。
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)
num = 1
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)
print('人脸特征提取,第 %d 个人' % num)
num += 1
# 特征向量列表存入文件
numpy.save('vectors.npy', descriptors)
'''
对单张人脸进行识别
'''
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)
result = name_list[min_dist][:-4]
print(result)
# -*- coding: utf-8 -*-
import sys, os, numpy, cv2, dlib
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(699, 300)
self.toolButton = QtWidgets.QToolButton(Dialog)
self.toolButton.setGeometry(QtCore.QRect(390, 10, 31, 21))
self.toolButton.setObjectName("toolButton")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(460, 10, 75, 23))
self.pushButton.setObjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(130, 10, 251, 20))
self.lineEdit.setObjectName("lineEdit")
self.graphicsView = QtWidgets.QGraphicsView(Dialog)
self.graphicsView.setGeometry(QtCore.QRect(290, 41, 251, 241))
self.graphicsView.setObjectName("graphicsView")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(290, 41, 251, 241))
self.label.setObjectName("label")
self.label.setScaledContents(True) #label自适应图片大小
self.graphicsView_2 = QtWidgets.QGraphicsView(Dialog)
self.graphicsView_2.setGeometry(QtCore.QRect(10, 40, 256, 241))
self.graphicsView_2.setObjectName("graphicsView_2")
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setGeometry(QtCore.QRect(13, 41, 251, 241))
self.label_2.setObjectName("label_2")
self.label_2.setScaledContents(True) #label自适应图片大小
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(10, 10, 111, 21))
font = QtGui.QFont()
font.setFamily("Agency FB")
font.setPointSize(11)
self.label_3.setFont(font)
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setGeometry(QtCore.QRect(550, 210, 81, 21))
font = QtGui.QFont()
font.setFamily("Agency FB")
font.setPointSize(11)
self.label_4.setFont(font)
self.label_4.setObjectName("label_4")
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(550, 240, 141, 20))
font = QtGui.QFont()
font.setFamily("Agency FB")
font.setPointSize(11)
self.lineEdit_2.setFont(font)
self.lineEdit_2.setObjectName("lineEdit_2")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "龟速人脸识别demo"))
self.toolButton.setText(_translate("Dialog", "..."))
self.pushButton.setText(_translate("Dialog", "开始识别"))
self.lineEdit.setText(_translate("Dialog", "E:/"))
self.label.setText(_translate("Dialog", "识别结果"))
self.label_2.setText(_translate("Dialog", "待测人脸"))
self.label_3.setText(_translate("Dialog", "待测人照片路径:"))
self.label_4.setText(_translate("Dialog", "识别结果:"))
class Myshow(QtWidgets.QWidget, Ui_Dialog):
def __init__(self):
super(Myshow, self).__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.Recognition)
self.toolButton.clicked.connect(self.ChoosePath)
self.predictor_path = 'shape_predictor_68_face_landmarks.dat'
self.face_rc_model_path = 'dlib_face_recognition_resnet_model_v1.dat'
self.face_folder_path = 'E:\candidate_face'
self.name_list = os.listdir(self.face_folder_path)
self.descriptors = numpy.load('vectors.npy')
# dlib方法检测人脸
# self.detector = dlib.get_frontal_face_detector()
# opencv方法检测人脸
self.face_cascade = cv2.CascadeClassifier('lbpcascade_frontalface_improved.xml')
self.feature_point = dlib.shape_predictor(self.predictor_path)
self.feature_model = dlib.face_recognition_model_v1(self.face_rc_model_path)
self.test_path = 'E:/'
def ChoosePath(self):
file_name = QtWidgets.QFileDialog.getOpenFileName(self, "open file dialog", self.test_path, "图片(*.jpg)")
print(file_name[0])
self.test_path = file_name[0]
self.lineEdit.setText(self.test_path)
self.label_2.setPixmap(QtGui.QPixmap(self.test_path)) #显示待测人脸图
# 清空不相关内容
self.label.clear()
self.lineEdit_2.clear()
def Recognition(self):
test_img = cv2.imread(self.test_path)
# dlib方法检测人脸
# dets = self.detector(test_img, 1)
# for k, d in enumerate(dets):
# shape = self.feature_point(test_img, d)
# test_feature = self.feature_model.compute_face_descriptor(test_img, shape)
# test_feature = numpy.array(test_feature)
# opencv方法检测人脸
gray = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY)
dets = self.face_cascade.detectMultiScale(gray, 1.1, 6)
mark = 0
for (x, y, w, h) in dets:
mark = 1
d = dlib.rectangle(numpy.long(x),numpy.long(y),numpy.long(x+w),numpy.long(y+h))
shape = self.feature_point(test_img, d)
test_feature = self.feature_model.compute_face_descriptor(test_img, shape)
test_feature = numpy.array(test_feature)
if mark == 1:
dist = []
count = 0
for i in self.descriptors:
dist_ = numpy.linalg.norm(i - test_feature)
print('%s : %f' % (self.name_list[count], dist_))
dist.append(dist_)
count += 1
min_dist = numpy.argmin(dist)
print('%s' % self.name_list[min_dist][:-4])
show_img_path = os.path.join(self.face_folder_path, self.name_list[min_dist])
self.label.setPixmap(QtGui.QPixmap(show_img_path)) #显示人脸识别结果图
self.lineEdit_2.setText(self.name_list[min_dist][:-4])
else :
self.lineEdit_2.setText('haven\'t find any people')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Myshow()
w.show()
sys.exit(app.exec_())