本项目基于python,用到了opencv、dlib等开发包,实现了单张训练样本的人脸识别,有较为友好的UI界面,识别速度经优化后尚可。python
实现上思路与这篇博客一致,解决了这篇博客中存在的几个问题:git
基于以上问题,采起的解决方案以下:github
首先运行FaceRecognition.py,会经历:读取人脸集、人脸检测、提取人脸特征向量、存储人脸特征向量、对单张测试人脸图进行识别、打印识别结果 的过程。
而后运行main.py,会经历:初始化界面、加载各类参数模型、手动选择单张人脸测试图、基于opencv人脸检测器检测人脸、提取该人脸特征向量、计算欧氏距离、找出距离最小的人脸标签、输出人脸识别结果 这么几个过程。ruby
这个项目目前bug多多,准确率也还有很大提升空间,欢迎各位多多交流,这个项目的更多详情请见这里,若是对你也有所帮助,请轻轻点个star(别过重了,怕疼(⊙o⊙)…)。app
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_())