├── V1 ├── detect_face_harr.py ├── detect_face_recognition.py ├── face_data_collect.py ├── haarcascade_eye.xml ├── haarcascade_frontalface_default.xml ├── main.py ├── pace_names.txt ├── pyqt.py ├── readme.txt ├── recognition.py └── train_face.py ├── V2 ├── README.md ├── detect_face_harr.py ├── detect_face_recognition.py ├── face_data_collect.py ├── main.py ├── pace_names.txt ├── pyqt.py ├── recognition.py ├── train_face.py └── xx.txt └── 数字图像处理.pdf /V1/detect_face_harr.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | # minW = camera.get(3) # 图像宽度 480 3 | # minH = camera.get(4) # 图像高度 640 4 | #开启摄像头,采集图像,并截取脸部存起来作为数据集 5 | def Detect_Face(): 6 | # opencv自带的人脸识别分类器 7 | face_cascade = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml') 8 | # 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2 9 | camera = cv2.VideoCapture(0) 10 | while (True): 11 | ret, frame = camera.read()#获取图像 12 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化 13 | faces = face_cascade.detectMultiScale(gray, 1.3, 5,minSize=(60,60)) # 人脸检测 14 | for (x, y, w, h) in faces: 15 | img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) 16 | f = cv2.resize(gray[y:y + h, x:x + w], (200, 200)) 17 | cv2.imshow("face", f) 18 | cv2.imshow("camera", frame) 19 | if cv2.waitKey(int(1000 / 12)) & 0xff == ord("q"): 20 | break 21 | camera.release() 22 | cv2.destroyAllWindows() 23 | 24 | if __name__ == "__main__": 25 | Detect_Face() 26 | -------------------------------------------------------------------------------- /V1/detect_face_recognition.py: -------------------------------------------------------------------------------- 1 | import dlib 2 | import face_recognition 3 | import math 4 | import numpy as np 5 | import cv2 6 | #人脸检测+对齐 7 | predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") 8 | def rect_to_bbox(rect): 9 | """获得人脸矩形的坐标信息""" 10 | # print(rect) 11 | x = rect[3] 12 | y = rect[0] 13 | w = rect[1] - x 14 | h = rect[2] - y 15 | return (x, y, w, h) 16 | 17 | 18 | def face_alignment(faces): 19 | faces_aligned = []# 预测关键点 20 | for face in faces: 21 | rec = dlib.rectangle(0, 0, face.shape[0], face.shape[1]) 22 | shape = predictor(np.uint8(face), rec) 23 | # left eye, right eye, nose, left mouth, right mouth 24 | order = [36, 45, 30, 48, 54] 25 | for j in order: 26 | x = shape.part(j).x 27 | y = shape.part(j).y 28 | eye_center = ((shape.part(36).x + shape.part(45).x) * 1. / 2, # 计算两眼的中心坐标 29 | (shape.part(36).y + shape.part(45).y) * 1. / 2) 30 | dx = (shape.part(45).x - shape.part(36).x) 31 | dy = (shape.part(45).y - shape.part(36).y) 32 | angle = math.atan2(dy, dx) * 180. / math.pi # 计算角度 33 | RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵 34 | # 进行仿射变换,即旋转 35 | RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1]) 36 | ,borderMode=cv2.BORDER_CONSTANT, borderValue=(125, 125, 125)) 37 | 38 | faces_aligned.append(RotImg) 39 | return faces_aligned 40 | 41 | 42 | def test( ): 43 | camera = cv2.VideoCapture(0) 44 | while (True): 45 | read, img = camera.read() 46 | # 定位图片中的人脸 47 | face_locations = face_recognition.face_locations(img) 48 | # 提取人脸区域的图片并保存 49 | src_faces = [] 50 | src_face_num = 0 51 | for (i, rect) in enumerate(face_locations): 52 | src_face_num = src_face_num + 1 53 | (x, y, w, h) = rect_to_bbox(rect) 54 | detect_face = img[y:y + h, x:x + w] 55 | detect_face = cv2.cvtColor(detect_face, cv2.COLOR_BGR2GRAY) 56 | src_faces.append(detect_face) 57 | cv2.imshow("face", detect_face) 58 | #用框框圈住人脸 59 | img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 60 | cv2.imshow("image", img) 61 | # 人脸对齐操作并保存 62 | faces_aligned = face_alignment(src_faces) 63 | face_num = 0 64 | for faces in faces_aligned: 65 | face_num = face_num + 1 66 | cv2.imshow("Align_face", faces) 67 | 68 | if cv2.waitKey(int(1000/12)) & 0xff == ord("q"): 69 | break 70 | camera.release() 71 | cv2.destroyAllWindows() 72 | 73 | 74 | if __name__ == '__main__': 75 | test( ) 76 | print(" SUCCEED !!! ") 77 | 78 | -------------------------------------------------------------------------------- /V1/face_data_collect.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | 4 | #开启摄像头,采集图像,并截取脸部存起来作为数据集 5 | def generate_data(): 6 | # opencv自带的人脸识别分类器 7 | face_cascade = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml') 8 | count = 0 # 计数,采取图像照片 9 | new_name = input('\n enter user id:') 10 | file_name = './data_collection/' + new_name 11 | if not os.path.exists(file_name): # 如果目录不存在 12 | os.mkdir(file_name)# 以新的名字创建新的目录 13 | # 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2 14 | camera = cv2.VideoCapture(0) 15 | while (True): 16 | ret, frame = camera.read()#获取图像 17 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化 18 | faces = face_cascade.detectMultiScale(gray, 1.3, 5,minSize=(60,60)) # 人脸检测 19 | for (x, y, w, h) in faces: 20 | img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) 21 | f = cv2.resize(gray[y:y + h, x:x + w], (200, 200)) 22 | 23 | # cv2.imwrite(file_name + '/%s.jpg' % str(count), f) 24 | cv2.imshow("face", f) 25 | cv2.imwrite(file_name + '/%s.pgm' % str(count), f) 26 | count += 1 27 | 28 | cv2.imshow("camera", frame) 29 | if count >= 500: 30 | break 31 | if cv2.waitKey(int(1000 / 12)) & 0xff == ord("q"): 32 | break 33 | camera.release() 34 | cv2.destroyAllWindows() 35 | else: 36 | print("名称已存在") 37 | 38 | if __name__ == "__main__": 39 | generate_data() 40 | -------------------------------------------------------------------------------- /V1/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | from PyQt5.QtCore import * 4 | from PyQt5.QtGui import * 5 | from PyQt5.QtWidgets import QFileDialog, QMainWindow 6 | from pyqt import * #引用界面文件 7 | import recognition 8 | 9 | 10 | class PyQtMainEntry(QMainWindow, Ui_MainWindow): 11 | def __init__(self): 12 | super().__init__() 13 | self.setupUi(self) 14 | 15 | self.camera = cv2.VideoCapture(0) # 0-调用笔记本内置摄像头,1-调用usb摄像头 16 | self.is_camera_opened = False # 摄像头有没有打开标记 17 | 18 | # 定时器:30ms捕获一帧 19 | self._timer = QtCore.QTimer(self) 20 | self._timer.timeout.connect(self._queryFrame) 21 | self._timer.setInterval(30) 22 | 23 | def btnOpenCamera_Clicked(self): 24 | ''' 25 | 打开和关闭摄像头 26 | ''' 27 | self.is_camera_opened = ~self.is_camera_opened 28 | if self.is_camera_opened:#摄像头开着呢 29 | self.camera = cv2.VideoCapture(0) 30 | self.pushButton_2.setText("Close Camera") 31 | self._timer.start() 32 | else: 33 | self.camera.release() 34 | self.pushButton.setText("Open Camera") 35 | self._timer.stop() 36 | 37 | def btnCloseCamera_Clicked(self): 38 | pass 39 | 40 | @QtCore.pyqtSlot() 41 | def _queryFrame(self): 42 | ''' 43 | 循环捕获图片 44 | ''' 45 | self.frame = recognition.face_rec(self.camera) 46 | # ret, self.frame = self.camera.read() 47 | img_rows, img_cols, channels = self.frame.shape 48 | bytesPerLine = channels * img_cols 49 | 50 | cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB, self.frame) 51 | QImg = QImage(self.frame.data, img_cols, img_rows, 52 | bytesPerLine, QImage.Format_RGB888) 53 | self.label.setPixmap(QPixmap.fromImage(self.frame).scaled( 54 | self.label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)) 55 | 56 | 57 | if __name__ == "__main__": 58 | app = QtWidgets.QApplication(sys.argv) 59 | window = PyQtMainEntry() 60 | window.show() 61 | sys.exit(app.exec_()) 62 | -------------------------------------------------------------------------------- /V1/pace_names.txt: -------------------------------------------------------------------------------- 1 | a b mengwen_xu y -------------------------------------------------------------------------------- /V1/pyqt.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'untitled.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | class Ui_MainWindow(object): 14 | def setupUi(self, MainWindow): 15 | MainWindow.setObjectName("MainWindow") 16 | MainWindow.resize(746, 630) 17 | self.centralwidget = QtWidgets.QWidget(MainWindow) 18 | self.centralwidget.setObjectName("centralwidget") 19 | self.label = QtWidgets.QLabel(self.centralwidget) 20 | self.label.setGeometry(QtCore.QRect(20, 30, 320, 240)) 21 | self.label.setObjectName("label") 22 | self.pushButton = QtWidgets.QPushButton(self.centralwidget) 23 | self.pushButton.setGeometry(QtCore.QRect(30, 380, 75, 23)) 24 | self.pushButton.setObjectName("pushButton") 25 | self.label_2 = QtWidgets.QLabel(self.centralwidget) 26 | self.label_2.setGeometry(QtCore.QRect(420, 70, 200, 200)) 27 | self.label_2.setObjectName("label_2") 28 | self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) 29 | self.pushButton_2.setGeometry(QtCore.QRect(30, 450, 75, 23)) 30 | self.pushButton_2.setObjectName("pushButton_2") 31 | self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget) 32 | self.textBrowser.setGeometry(QtCore.QRect(460, 380, 181, 71)) 33 | self.textBrowser.setObjectName("textBrowser") 34 | MainWindow.setCentralWidget(self.centralwidget) 35 | self.menubar = QtWidgets.QMenuBar(MainWindow) 36 | self.menubar.setGeometry(QtCore.QRect(0, 0, 746, 23)) 37 | self.menubar.setObjectName("menubar") 38 | MainWindow.setMenuBar(self.menubar) 39 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 40 | self.statusbar.setObjectName("statusbar") 41 | MainWindow.setStatusBar(self.statusbar) 42 | 43 | self.retranslateUi(MainWindow) 44 | self.pushButton.clicked.connect(MainWindow.btnOpenCamera_Clicked) 45 | self.pushButton_2.clicked.connect(MainWindow.btnCloseCamera_Clicked) 46 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 47 | 48 | def retranslateUi(self, MainWindow): 49 | _translate = QtCore.QCoreApplication.translate 50 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 51 | self.label.setText(_translate("MainWindow", "捕获帧")) 52 | self.pushButton.setText(_translate("MainWindow", "Open Camera")) 53 | self.label_2.setText(_translate("MainWindow", "TextLabel")) 54 | self.pushButton_2.setText(_translate("MainWindow", "关闭")) 55 | -------------------------------------------------------------------------------- /V1/readme.txt: -------------------------------------------------------------------------------- 1 | 有些需要的模型没有发进来,需要再下载 2 | -------------------------------------------------------------------------------- /V1/recognition.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import face_data_collect 3 | import dlib 4 | import face_recognition 5 | import detect_face_recognition as dfr 6 | def rect_to_bbox(rect): 7 | """获得人脸矩形的坐标信息""" 8 | # print(rect) 9 | x = rect[3] 10 | y = rect[0] 11 | w = rect[1] - x 12 | h = rect[2] - y 13 | return (x, y, w, h) 14 | 15 | recognizer = cv2.face.LBPHFaceRecognizer_create() 16 | recognizer.read('trainer.yml') 17 | face_cascade = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml') 18 | font = cv2.FONT_HERSHEY_SIMPLEX 19 | 20 | idnum = 0 21 | 22 | # cam = cv2.VideoCapture(0) 23 | # minW = 0.1*cam.get(3)#图像宽度 24 | # minH = 0.1*cam.get(4)#图像高度 25 | 26 | 27 | def face_rec(camera): 28 | # 下面读取摄像头图像,用矩形标识检测到脸部和训练后结果比对,打印出对应标签所对应名字 29 | with open('pace_names.txt', 'r') as f: 30 | face_names = f.read() 31 | names = face_names.split() 32 | # 33 | # minW = 0.1 * camera.get(3) # 图像宽度 34 | # minH = 0.1 * camera.get(4) # 图像高度 35 | # print(minH,minW) 36 | 37 | while(True): 38 | read, img = camera.read() 39 | 40 | # face_locations = face_recognition.face_locations(img) # 定位图片中的人脸 41 | # src_faces = [] 42 | # src_face_num = 0 43 | # for (i, rect) in enumerate(face_locations): 44 | # src_face_num = src_face_num + 1 45 | # (x, y, w, h) = rect_to_bbox(rect)#读取单个人脸的初始坐标与宽度,高度 46 | # detect_face = img[y:y + h, x:x + w]#截取出人脸部分 47 | # detect_face = cv2.cvtColor(detect_face, cv2.COLOR_BGR2GRAY)#灰度化 48 | # src_faces.append(detect_face) 49 | # # cv2.imshow("face", detect_face) 50 | # # 用框框圈住人脸,注意位置偏移 51 | # img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 52 | # # cv2.imshow("image", img) 53 | # # 人脸对齐操作并保存 54 | # faces_aligned = dfr.face_alignment(src_faces) 55 | # face_num = 0 56 | # for roi_gray in faces_aligned: 57 | # face_num = face_num + 1 58 | # # cv2.imshow("Align_face", roi_gray) 59 | 60 | # #harr方法检测人脸 61 | #由于读取的摄像头大小为640x480,所以设置人脸最小为60x60 62 | faces = face_cascade.detectMultiScale(img, 1.3, 5,minSize=(60,60)) 63 | for (x, y, w, h) in faces: 64 | img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 65 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 66 | roi_gray = gray[y:y + h,x:x + w]#注意别弄错了位置 67 | 68 | try: 69 | roi_gray = cv2.resize(roi_gray, (200,200), interpolation=cv2.INTER_LINEAR) 70 | # cv2.imshow("roi_gray", roi_gray) 71 | params = recognizer.predict(roi_gray) 72 | print("Label:%s,Confidence:%.2f" % (params[0], params[1])) 73 | if params[1] < 70:#低于50以下是好的识别参考值,高于80的参考值都会认为是低的置信度评分 74 | cv2.putText(img, names[params[0]],(x,y-20),cv2.FONT_HERSHEY_SIMPLEX, 1,255,2) 75 | except: 76 | continue 77 | 78 | # cv2.imshow("cam",img) 79 | 80 | if cv2.waitKey(int(1000/12)) & 0xff == ord("q"): 81 | break 82 | # camera.release() 83 | # cv2.destroyAllWindows() 84 | return img 85 | 86 | 87 | 88 | if __name__ == "__main__": 89 | camera = cv2.VideoCapture(0) 90 | face_rec(camera) 91 | 92 | 93 | -------------------------------------------------------------------------------- /V1/train_face.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | import cv2 4 | 5 | picture_path = 'data_collection'# 人脸数据路径 6 | recognizer = cv2.face.LBPHFaceRecognizer_create()#cv中自带的识别模型 7 | detector = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml')#cv中的检测人脸文件 8 | face_names = [] 9 | 10 | 11 | 12 | 13 | #读取样本文件,并加载到一个列表里,返回值包括2部分,[文件列表,对应标签],标签用来对照姓名用。 14 | def read_image(path,sz=None): 15 | pr_img=[] #图像列表 16 | pr_flg=[] #对应标签 17 | pr_count=0 #初始化检测到的人数 18 | for dirname,dirnames,filenames in os.walk(path):#遍历当前程序目录 19 | # print("1",dirname,dirnames,filenames) 20 | for subdirname in dirnames: #遍历程序文件夹下的各个目录 21 | # print("2",subdirname, dirnames) 22 | subject_path=os.path.join(dirname,subdirname) 23 | #这时候subdirname是循环处理data_collection文件夹下的文件夹,这时如果有新的面孔加进来需要更新标签名字 24 | face_names.append(subdirname) 25 | for filename in os.listdir(subject_path): #遍历文件夹下文件 26 | try: 27 | filepath=os.path.join(subject_path,filename) 28 | im=cv2.imread(filepath,cv2.IMREAD_GRAYSCALE) #读取文件下PGM文件 29 | if im.shape!=(200,200): #判断像素是否200 30 | im=cv2.resize(im,(200,200)) 31 | pr_img.append(np.asarray(im,dtype=np.uint8)) #添加图像 32 | pr_flg.append(pr_count)#添加标签 33 | except: 34 | print("io error") 35 | pr_count+=1 #另一个人的标签 36 | 37 | with open('pace_names.txt', 'w') as f: #把名字写入文件 38 | f.write(' '.join(face_names)) #每个元素间加一个空格转换为字符串 39 | return [pr_img, pr_flg] 40 | 41 | 42 | def train_model(path, epoch=5): 43 | 44 | print('Training faces. It will take a few seconds. Wait ...') 45 | faces, ids = read_image(path) 46 | if os.path.exists('trainer.yml'):#是否存在文件 47 | A = recognizer.read('trainer.yml') #读取模型参数 48 | for s in range(1, epoch): 49 | print('Training ... %dth' % s) 50 | recognizer.train(faces, np.array(ids)) #训练模型 51 | 52 | recognizer.write('trainer.yml') #保存模型参数 53 | print('Complete the training !') 54 | 55 | 56 | if __name__ == "__main__": 57 | train_model(picture_path, 10) -------------------------------------------------------------------------------- /V2/README.md: -------------------------------------------------------------------------------- 1 | # Face_Rec 2 | 还需要两个外部文件haarcascade_frontalface_default.xml, shape_predictor_68_face_landmarks.dat 3 | 4 | 人脸识别系统 5 | detect_face_harr.py 6 | detect_face_recognition.py 7 | 分别是不同的人脸检测程序 8 | 9 | face_data_collect.py人脸收集程序 10 | train_face.py人脸数据训练 11 | recognition.py人脸识别 12 | 13 | pyqt.py图形界面程序 14 | -------------------------------------------------------------------------------- /V2/detect_face_harr.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | # minW = camera.get(3) # 图像宽度 480 3 | # minH = camera.get(4) # 图像高度 640 4 | #开启摄像头,采集图像,并截取脸部存起来作为数据集 5 | def Detect_Face(): 6 | # opencv自带的人脸识别分类器 7 | face_cascade = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml') 8 | # 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2 9 | camera = cv2.VideoCapture(0) 10 | while (True): 11 | ret, frame = camera.read()#获取图像 12 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化 13 | faces = face_cascade.detectMultiScale(gray, 1.3, 5,minSize=(60,60)) # 人脸检测 14 | for (x, y, w, h) in faces: 15 | img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) 16 | f = cv2.resize(gray[y:y + h, x:x + w], (200, 200)) 17 | cv2.imshow("face", f) 18 | cv2.imshow("camera", frame) 19 | if cv2.waitKey(int(1000 / 12)) & 0xff == ord("q"): 20 | break 21 | camera.release() 22 | cv2.destroyAllWindows() 23 | 24 | if __name__ == "__main__": 25 | Detect_Face() 26 | -------------------------------------------------------------------------------- /V2/detect_face_recognition.py: -------------------------------------------------------------------------------- 1 | import dlib 2 | import face_recognition 3 | import math 4 | import numpy as np 5 | import cv2 6 | #人脸检测+对齐 7 | predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") 8 | def rect_to_bbox(rect): 9 | """获得人脸矩形的坐标信息""" 10 | # print(rect) 11 | x = rect[3] 12 | y = rect[0] 13 | w = rect[1] - x 14 | h = rect[2] - y 15 | return (x, y, w, h) 16 | 17 | 18 | def face_alignment(faces): 19 | faces_aligned = []# 预测关键点 20 | for face in faces: 21 | rec = dlib.rectangle(0, 0, face.shape[0], face.shape[1]) 22 | shape = predictor(np.uint8(face), rec) 23 | # left eye, right eye, nose, left mouth, right mouth 24 | order = [36, 45, 30, 48, 54] 25 | for j in order: 26 | x = shape.part(j).x 27 | y = shape.part(j).y 28 | eye_center = ((shape.part(36).x + shape.part(45).x) * 1. / 2, # 计算两眼的中心坐标 29 | (shape.part(36).y + shape.part(45).y) * 1. / 2) 30 | dx = (shape.part(45).x - shape.part(36).x) 31 | dy = (shape.part(45).y - shape.part(36).y) 32 | angle = math.atan2(dy, dx) * 180. / math.pi # 计算角度 33 | RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵 34 | # 进行仿射变换,即旋转 35 | RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1]) 36 | ,borderMode=cv2.BORDER_CONSTANT, borderValue=(125, 125, 125)) 37 | 38 | faces_aligned.append(RotImg) 39 | return faces_aligned 40 | 41 | 42 | def test( ): 43 | camera = cv2.VideoCapture(0) 44 | while (True): 45 | read, img = camera.read() 46 | # 定位图片中的人脸 47 | face_locations = face_recognition.face_locations(img) 48 | # 提取人脸区域的图片并保存 49 | src_faces = [] 50 | src_face_num = 0 51 | for (i, rect) in enumerate(face_locations): 52 | src_face_num = src_face_num + 1 53 | (x, y, w, h) = rect_to_bbox(rect) 54 | detect_face = img[y:y + h, x:x + w] 55 | detect_face = cv2.cvtColor(detect_face, cv2.COLOR_BGR2GRAY) 56 | src_faces.append(detect_face) 57 | cv2.imshow("face", detect_face) 58 | #用框框圈住人脸 59 | img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 60 | cv2.imshow("image", img) 61 | # 人脸对齐操作并保存 62 | faces_aligned = face_alignment(src_faces) 63 | face_num = 0 64 | for faces in faces_aligned: 65 | face_num = face_num + 1 66 | cv2.imshow("Align_face", faces) 67 | 68 | if cv2.waitKey(int(1000/12)) & 0xff == ord("q"): 69 | break 70 | camera.release() 71 | cv2.destroyAllWindows() 72 | 73 | 74 | if __name__ == '__main__': 75 | test( ) 76 | print(" SUCCEED !!! ") 77 | 78 | -------------------------------------------------------------------------------- /V2/face_data_collect.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | 4 | #开启摄像头,采集图像,并截取脸部存起来作为数据集 5 | def generate_data(): 6 | # opencv自带的人脸识别分类器 7 | face_cascade = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml') 8 | count = 0 # 计数,采取图像照片 9 | new_name = input('\n enter user id:') 10 | file_name = './data_collection/' + new_name 11 | if not os.path.exists(file_name): # 如果目录不存在 12 | os.mkdir(file_name)# 以新的名字创建新的目录 13 | # 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2 14 | camera = cv2.VideoCapture(0) 15 | while (True): 16 | ret, frame = camera.read()#获取图像 17 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化 18 | faces = face_cascade.detectMultiScale(gray, 1.3, 5,minSize=(60,60)) # 人脸检测 19 | for (x, y, w, h) in faces: 20 | img = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) 21 | f = cv2.resize(gray[y:y + h, x:x + w], (200, 200)) 22 | 23 | # cv2.imwrite(file_name + '/%s.jpg' % str(count), f) 24 | cv2.imshow("face", f) 25 | cv2.imwrite(file_name + '/%s.pgm' % str(count), f) 26 | count += 1 27 | 28 | cv2.imshow("camera", frame) 29 | if count >= 500: 30 | break 31 | if cv2.waitKey(int(1000 / 12)) & 0xff == ord("q"): 32 | break 33 | camera.release() 34 | cv2.destroyAllWindows() 35 | else: 36 | print("名称已存在") 37 | 38 | if __name__ == "__main__": 39 | generate_data() 40 | -------------------------------------------------------------------------------- /V2/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import cv2 3 | from PyQt5.QtCore import * 4 | from PyQt5.QtGui import * 5 | from PyQt5.QtWidgets import QFileDialog, QMainWindow 6 | from pyqt import * #引用界面文件 7 | import recognition 8 | from train_face import * 9 | 10 | 11 | class PyQtMainEntry(QMainWindow, Ui_MainWindow): 12 | def __init__(self): 13 | super().__init__() 14 | self.setupUi(self) 15 | self.camera = cv2.VideoCapture(0) # 0-调用笔记本内置摄像头,1-调用usb摄像头 16 | self.is_camera_opened = False # 摄像头有没有打开标记 17 | 18 | # 定时器:30ms捕获一帧 19 | self._timer = QtCore.QTimer(self) 20 | self._timer.timeout.connect(self._queryFrame) 21 | self._timer.setInterval(30) 22 | 23 | def btnOpenCamera_Clicked(self): 24 | ''' 25 | 打开和关闭摄像头 26 | ''' 27 | self.is_camera_opened = ~self.is_camera_opened 28 | if self.is_camera_opened:#摄像头开着呢 29 | self.camera = cv2.VideoCapture(0) 30 | self.pushButton.setText("Close Camera") 31 | self._timer.start() 32 | else: 33 | self.camera.release() 34 | self.pushButton.setText("Open Camera") 35 | self._timer.stop() 36 | 37 | 38 | def btnTrainData_Clicked(self): 39 | #调用训练数据模型 40 | self.printf('Training faces. It will take a few seconds. Wait ...') 41 | train_model(picture_path, 5) 42 | self.printf('Complete the training !') 43 | 44 | 45 | @QtCore.pyqtSlot() 46 | def _queryFrame(self): 47 | # 循环捕获图片 48 | self.frame = recognition.face_rec(self.camera) 49 | img_rows, img_cols, channels = self.frame.shape#输出图像形状 50 | bytesPerLine = channels * img_cols 51 | cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB, self.frame)#转变成RGB颜色格式 52 | QImg = QImage(self.frame.data, img_cols, 53 | img_rows,bytesPerLine, QImage.Format_RGB888)#装变成qt颜色格式 54 | #根据形状适应大小,并输出在label上 55 | self.label.setPixmap(QPixmap.fromImage(QImg).scaled(self.label.size(), 56 | Qt.KeepAspectRatio, Qt.SmoothTransformation)) 57 | 58 | 59 | if __name__ == "__main__": 60 | app = QtWidgets.QApplication(sys.argv) 61 | window = PyQtMainEntry() 62 | window.show() 63 | sys.exit(app.exec_()) 64 | -------------------------------------------------------------------------------- /V2/pace_names.txt: -------------------------------------------------------------------------------- 1 | a b mengwen_xu y -------------------------------------------------------------------------------- /V2/pyqt.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'untitled.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.13.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | 10 | from PyQt5 import QtCore, QtGui, QtWidgets 11 | 12 | 13 | class Ui_MainWindow(object): 14 | def setupUi(self, MainWindow): 15 | MainWindow.setObjectName("MainWindow") 16 | MainWindow.resize(547, 530) 17 | self.centralwidget = QtWidgets.QWidget(MainWindow) 18 | self.centralwidget.setObjectName("centralwidget") 19 | self.label = QtWidgets.QLabel(self.centralwidget) 20 | self.label.setGeometry(QtCore.QRect(20, 30, 480, 360)) 21 | self.label.setObjectName("label") 22 | self.pushButton = QtWidgets.QPushButton(self.centralwidget) 23 | self.pushButton.setGeometry(QtCore.QRect(40, 420, 81, 21)) 24 | self.pushButton.setObjectName("pushButton") 25 | self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget) 26 | self.textBrowser.setGeometry(QtCore.QRect(240, 430, 291, 41)) 27 | self.textBrowser.setObjectName("textBrowser") 28 | self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget) 29 | self.pushButton_3.setGeometry(QtCore.QRect(40, 450, 81, 21)) 30 | self.pushButton_3.setObjectName("pushButton_3") 31 | self.label_2 = QtWidgets.QLabel(self.centralwidget) 32 | self.label_2.setGeometry(QtCore.QRect(240, 410, 61, 16)) 33 | self.label_2.setObjectName("label_2") 34 | self.label_3 = QtWidgets.QLabel(self.centralwidget) 35 | self.label_3.setGeometry(QtCore.QRect(160, 0, 221, 21)) 36 | font = QtGui.QFont() 37 | font.setFamily("华文行楷") 38 | font.setPointSize(14) 39 | self.label_3.setFont(font) 40 | self.label_3.setObjectName("label_3") 41 | MainWindow.setCentralWidget(self.centralwidget) 42 | self.menubar = QtWidgets.QMenuBar(MainWindow) 43 | self.menubar.setGeometry(QtCore.QRect(0, 0, 547, 23)) 44 | self.menubar.setObjectName("menubar") 45 | MainWindow.setMenuBar(self.menubar) 46 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 47 | self.statusbar.setObjectName("statusbar") 48 | MainWindow.setStatusBar(self.statusbar) 49 | 50 | self.retranslateUi(MainWindow) 51 | self.pushButton.clicked.connect(MainWindow.btnOpenCamera_Clicked) 52 | self.pushButton_3.clicked.connect(MainWindow.btnTrainData_Clicked) 53 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 54 | 55 | def printf(self, mypstr): 56 | # 自定义类print函数, 借用c语言 57 | # printf 58 | # Mypstr:是待显示的字符串 59 | self.textBrowser.append(mypstr) # 在指定的区域显示提示信息 60 | self.cursor = self.textBrowser.textCursor() 61 | self.textBrowser.moveCursor(self.cursor.End) # 光标移到最后,这样就会自动显示出来 62 | QtWidgets.QApplication.processEvents() # 一定加上这个功能,不然有卡顿 63 | 64 | def retranslateUi(self, MainWindow): 65 | _translate = QtCore.QCoreApplication.translate 66 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 67 | self.label.setText(_translate("MainWindow", "捕获帧")) 68 | self.pushButton.setText(_translate("MainWindow", "Open Camera")) 69 | self.pushButton_3.setText(_translate("MainWindow", "训练模型")) 70 | self.label_2.setText(_translate("MainWindow", "信息输出:")) 71 | self.label_3.setText(_translate("MainWindow", "北京工业大学-许梦文")) 72 | -------------------------------------------------------------------------------- /V2/recognition.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import face_data_collect 4 | import dlib 5 | import face_recognition 6 | import detect_face_recognition as dfr 7 | def rect_to_bbox(rect): 8 | """获得人脸矩形的坐标信息""" 9 | # print(rect) 10 | x = rect[3] 11 | y = rect[0] 12 | w = rect[1] - x 13 | h = rect[2] - y 14 | return (x, y, w, h) 15 | 16 | recognizer = cv2.face.LBPHFaceRecognizer_create() 17 | recognizer.read('trainer.yml') 18 | face_cascade = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml') 19 | font = cv2.FONT_HERSHEY_SIMPLEX 20 | 21 | idnum = 0 22 | 23 | # cam = cv2.VideoCapture(0) 24 | # minW = 0.1*cam.get(3)#图像宽度 25 | # minH = 0.1*cam.get(4)#图像高度 26 | 27 | def face_rec(camera): 28 | # 下面读取摄像头图像,用矩形标识检测到脸部和训练后结果比对,打印出对应标签所对应名字 29 | 30 | with open('pace_names.txt', 'r') as f: 31 | face_names = f.read() 32 | names = face_names.split() 33 | # 34 | # minW = 0.1 * camera.get(3) # 图像宽度 35 | # minH = 0.1 * camera.get(4) # 图像高度 36 | # print(minH,minW) 37 | 38 | while(True): 39 | read, img = camera.read() 40 | img = np.fliplr(img).copy() 41 | 42 | # face_locations = face_recognition.face_locations(img) # 定位图片中的人脸 43 | # src_faces = [] 44 | # src_face_num = 0 45 | # for (i, rect) in enumerate(face_locations): 46 | # src_face_num = src_face_num + 1 47 | # (x, y, w, h) = rect_to_bbox(rect)#读取单个人脸的初始坐标与宽度,高度 48 | # detect_face = img[y:y + h, x:x + w]#截取出人脸部分 49 | # detect_face = cv2.cvtColor(detect_face, cv2.COLOR_BGR2GRAY)#灰度化 50 | # src_faces.append(detect_face) 51 | # # cv2.imshow("face", detect_face) 52 | # # 用框框圈住人脸,注意位置偏移 53 | # img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 54 | # # cv2.imshow("image", img) 55 | # # 人脸对齐操作并保存 56 | # faces_aligned = dfr.face_alignment(src_faces) 57 | # face_num = 0 58 | # for roi_gray in faces_aligned: 59 | # face_num = face_num + 1 60 | # # cv2.imshow("Align_face", roi_gray) 61 | 62 | # #harr方法检测人脸 63 | #由于读取的摄像头大小为640x480,所以设置人脸最小为60x60 64 | faces = face_cascade.detectMultiScale(img, 1.3, 5,minSize=(60,60)) 65 | for (x, y, w, h) in faces: 66 | img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 67 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 68 | roi_gray = gray[y:y + h,x:x + w]#注意别弄错了位置 69 | 70 | try: 71 | roi_gray = cv2.resize(roi_gray, (200,200), interpolation=cv2.INTER_LINEAR) 72 | params = recognizer.predict(roi_gray) 73 | print("name:%s,Confidence:%.2f" % (names[params[0]], params[1])) 74 | if params[1] < 70:#低于50以下是好的识别参考值,高于80的参考值都会认为是低的置信度评分 75 | cv2.putText(img, names[params[0]],(x,y-20),cv2.FONT_HERSHEY_SIMPLEX, 1,255,2) 76 | cv2.putText(img, "Confidence:"+str((int)(params[1])), (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2) 77 | except: 78 | continue 79 | 80 | if cv2.waitKey(int(1000/12)): 81 | break 82 | return img 83 | 84 | 85 | 86 | if __name__ == "__main__": 87 | camera = cv2.VideoCapture(0) 88 | face_rec(camera) 89 | 90 | 91 | -------------------------------------------------------------------------------- /V2/train_face.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | import cv2 4 | import pyqt 5 | picture_path = 'data_collection'# 人脸数据路径 6 | recognizer = cv2.face.LBPHFaceRecognizer_create()#cv中自带的识别模型 7 | detector = cv2.CascadeClassifier('.\opencv_module\haarcascade_frontalface_default.xml')#cv中的检测人脸文件 8 | face_names = [] 9 | 10 | 11 | 12 | 13 | #读取样本文件,并加载到一个列表里,返回值包括2部分,[文件列表,对应标签],标签用来对照姓名用。 14 | def read_image(path,sz=None): 15 | pr_img=[] #图像列表 16 | pr_flg=[] #对应标签 17 | pr_count=0 #初始化检测到的人数 18 | for dirname,dirnames,filenames in os.walk(path):#遍历当前程序目录 19 | # print("1",dirname,dirnames,filenames) 20 | for subdirname in dirnames: #遍历程序文件夹下的各个目录 21 | # print("2",subdirname, dirnames) 22 | subject_path=os.path.join(dirname,subdirname) 23 | #这时候subdirname是循环处理data_collection文件夹下的文件夹,这时如果有新的面孔加进来需要更新标签名字 24 | face_names.append(subdirname) 25 | for filename in os.listdir(subject_path): #遍历文件夹下文件 26 | try: 27 | filepath=os.path.join(subject_path,filename) 28 | im=cv2.imread(filepath,cv2.IMREAD_GRAYSCALE) #读取文件下PGM文件 29 | if im.shape!=(200,200): #判断像素是否200 30 | im=cv2.resize(im,(200,200)) 31 | pr_img.append(np.asarray(im,dtype=np.uint8)) #添加图像 32 | pr_flg.append(pr_count)#添加标签 33 | except: 34 | print("io error") 35 | pr_count+=1 #另一个人的标签 36 | 37 | with open('pace_names.txt', 'w') as f: #把名字写入文件 38 | f.write(' '.join(face_names)) #每个元素间加一个空格转换为字符串 39 | return [pr_img, pr_flg] 40 | 41 | 42 | def train_model(path, epoch=5): 43 | print('Training faces. It will take a few seconds. Wait ...') 44 | faces, ids = read_image(path) 45 | if os.path.exists('trainer.yml'):#是否存在文件 46 | A = recognizer.read('trainer.yml') #读取模型参数 47 | for s in range(1, epoch): 48 | print('Training ... %dth' % s) 49 | recognizer.train(faces, np.array(ids)) #训练模型 50 | 51 | recognizer.write('trainer.yml') #保存模型参数 52 | print('Complete the training !') 53 | 54 | 55 | if __name__ == "__main__": 56 | train_model(picture_path, 10) -------------------------------------------------------------------------------- /V2/xx.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /数字图像处理.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mengwen-Xu/Face_Rec/ffbe27da82452ac6f31f4e37de5f36159de0d531/数字图像处理.pdf --------------------------------------------------------------------------------