人臉識別模型訓練
簡單了解LBPH算法
(在OpenCV使用的三種識別算法中是精度比較高的)
cv2.face.LBPHFaceRecognizer_create()#使用LBPH算法訓練模型(注意OpenCV3中是createLBPHFaceRecognizer,這里因為樹莓派和Window使用的版本不一樣,所以到樹莓派上還會改代碼)
開始訓練模型
這里還是先訓練,畢竟真正的人臉識別開鎖,人臉的錄入並不是在要開鎖的時候當場錄入的,所以沒必要在開鎖的時候訓練模型,提前用單獨的代碼將模型訓練好,訓練好的數據存儲到trained`數據集中
檢測時直接讀取此文件夾中的數據
import numpy as np
from PIL import Image
import os
import cv2
def recon():
path = 'dataset'
recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml");
def getImagesAndLabels(path):
imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
faceSamples = []
ids = []
for imagePath in imagePaths:
PIL_img = Image.open(imagePath).convert('L')
img_numpy = np.array(PIL_img, 'uint8')
id = int(os.path.split(imagePath)[-1].split("_")[1])
faces = detector.detectMultiScale(img_numpy)
for (x, y, w, h) in faces:
faceSamples.append(img_numpy[y:y + h, x:x + w])
ids.append(id)
return faceSamples, ids
print("\n [INFO] Training faces. It will take a few seconds. Wait ...")
faces, ids = getImagesAndLabels(path)
recognizer.train(faces, np.array(ids))
recognizer.write('trained/trainer.yml')
print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))
人臉識別
import cv2
import numpy as np
import os
def recon_faces():
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trained/trainer.yml')
cascadePath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath);
font = cv2.FONT_HERSHEY_SIMPLEX
id = 0
t = 0
fp2 = open('names.txt','r+')
str2 = fp2.read()
names = str2.split(',')
print(names)
cam = cv2.VideoCapture(0)
minW = 0.1 * cam.get(3)
minH = 0.1 * cam.get(4)
while True:
t+=1
ret, img = cam.read()
img = cv2.flip(img, 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5,
minSize=(int(minW), int(minH)),
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
id, confidence = recognizer.predict(gray[y:y + h, x:x + w])
if (confidence <45):
id = names[id]
confidence = " {0}%".format(round(100 - confidence))
else:
id = "unknown"
confidence = " {0}%".format(round(100 - confidence))
cv2.putText(img, str(id), (x + 5, y - 5), font, 1, (255, 255, 255), 2)
cv2.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (255, 255, 0), 1)
cv2.imshow('camera', img)
k = cv2.waitKey(10) & 0xff
if k == 27:
break
elif t>200:
break
cam.release()
cv2.destroyAllWindows()
return id
#id = recon_faces()
#print(id)
置信度評分用來 衡量所識別人臉與原模型的差距,0 表示完全匹配。
整合進界面
使用Qt designer設計界面
拖控件,針對每個控件(比如Button)
寫信號槽函數(對應的響應事件)
界面布局
(1)使用容器container布局
使用verticallayout
進行豎式按鍵布局
(2)使用堆疊布局來實現不同界面的切換
QStackedWidget
使用QtDesigner進行界面的創建和布局
界面功能
(1)人臉錄入()
這里就只設置一個管理員(比如某個宿舍的舍管)
所以只需要一對賬號密碼(admin,fjnupass)
輸入學號,開始錄入
將學號存儲在文件中,用於人臉識別時的id和人臉匹配
錄入結束會彈出對話框,點擊OK,繼續進行模型的訓練,模型訓練結束彈出訓練結束對話框
(2)人臉識別開鎖
點擊按鈕,調用攝像頭運行識別代碼
識別成功,跳出成功和歡迎某某學號的對話框
設置一個超時時間(10s左右),超過就跳出是被失敗的對話框,
識別成功:彈出對話框顯示歡迎某某學號學生
(3)密碼鎖
輸入密碼開鎖(考慮人臉識別的精度問題)
直接使用一個LineEdit控件
取得輸入內容后和已存在密碼做一個對比(密碼預設為12345678)

(4)退出系統
self.exit.clicked.connect(self.click_exit)
def click_exit(self):
sys.exit(app.exec_())
界面代碼:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'face.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox,QWidget
from input_face_data import *
from train import *
from test import *
class Ui_MainWindow(QWidget):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(913, 684)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.frameheader = QtWidgets.QFrame(self.centralwidget)
self.frameheader.setGeometry(QtCore.QRect(120, 0, 521, 61))
self.frameheader.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frameheader.setFrameShadow(QtWidgets.QFrame.Raised)
self.frameheader.setObjectName("frameheader")
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
self.stackedWidget.setGeometry(QtCore.QRect(230, 70, 641, 541))
self.stackedWidget.setObjectName("stackedWidget")
self.page_4 = QtWidgets.QWidget()
self.page_4.setObjectName("page_4")
self.id = QtWidgets.QLineEdit(self.page_4)
self.id.setGeometry(QtCore.QRect(202, 200, 231, 31))
self.id.setObjectName("id")
self.pushButton = QtWidgets.QPushButton(self.page_4)
self.pushButton.setGeometry(QtCore.QRect(260, 270, 111, 41))
self.pushButton.setObjectName("pushButton")
self.label_4 = QtWidgets.QLabel(self.page_4)
self.label_4.setGeometry(QtCore.QRect(200, 160, 111, 21))
self.label_4.setObjectName("label_4")
self.stackedWidget.addWidget(self.page_4)
self.page = QtWidgets.QWidget()
self.page.setObjectName("page")
self.verticalLayoutWidget = QtWidgets.QWidget(self.page)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(20, 40, 118, 361))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.admin = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.admin.setObjectName("admin")
self.verticalLayout.addWidget(self.admin)
self.passwd = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.passwd.setObjectName("passwd")
self.verticalLayout.addWidget(self.passwd)
self.face = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.face.setObjectName("face")
self.verticalLayout.addWidget(self.face)
self.exit = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.exit.setObjectName("exit")
self.verticalLayout.addWidget(self.exit)
self.admin_pass = QtWidgets.QLabel(self.page)
self.admin_pass.setGeometry(QtCore.QRect(270, 210, 161, 21))
font = QtGui.QFont()
font.setPointSize(15)
self.admin_pass.setFont(font)
self.admin_pass.setObjectName("admin_pass")
self.admin_line_pass = QtWidgets.QLineEdit(self.page)
self.admin_line_pass.setGeometry(QtCore.QRect(270, 250, 351, 31))
self.admin_line_pass.setObjectName("admin_line_pass")
self.admin_name = QtWidgets.QLabel(self.page)
self.admin_name.setGeometry(QtCore.QRect(270, 120, 161, 21))
font = QtGui.QFont()
font.setPointSize(15)
self.admin_name.setFont(font)
self.admin_name.setObjectName("admin_name")
self.admin_line_name = QtWidgets.QLineEdit(self.page)
self.admin_line_name.setGeometry(QtCore.QRect(270, 160, 351, 31))
self.admin_line_name.setObjectName("admin_line_name")
self.login = QtWidgets.QPushButton(self.page)
self.login.setGeometry(QtCore.QRect(380, 320, 101, 41))
self.login.setObjectName("login")
self.stackedWidget.addWidget(self.page)
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.open = QtWidgets.QPushButton(self.page_2)
self.open.setGeometry(QtCore.QRect(230, 300, 291, 41))
self.open.setObjectName("open")
self.lineEdit = QtWidgets.QLineEdit(self.page_2)
self.lineEdit.setGeometry(QtCore.QRect(230, 220, 291, 31))
self.lineEdit.setObjectName("lin eEdit")
self.label_2 = QtWidgets.QLabel(self.page_2)
self.label_2.setGeometry(QtCore.QRect(230, 180, 131, 21))
self.label_2.setObjectName("label_2")
self.stackedWidget.addWidget(self.page_2)
self.page_3 = QtWidgets.QWidget()
self.page_3.setObjectName("page_3")
self.label_3 = QtWidgets.QLabel(self.page_3)
self.label_3.setGeometry(QtCore.QRect(60, 120, 541, 271))
font = QtGui.QFont()
font.setPointSize(25)
self.label_3.setFont(font)
self.label_3.setObjectName("label_3")
self.stackedWidget.addWidget(self.page_3)
self.return_2 = QtWidgets.QPushButton(self.centralwidget)
self.return_2.setGeometry(QtCore.QRect(90, 230, 75, 23))
self.return_2.setObjectName("return_2")
self.exit2 = QtWidgets.QPushButton(self.centralwidget)
self.exit2.setGeometry(QtCore.QRect(90, 320, 75, 23))
self.exit2.setObjectName("exit2")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(330, 10, 411, 41))
font = QtGui.QFont()
font.setPointSize(23)
font.setBold(True)
font.setItalic(False)
font.setWeight(75)
self.label.setFont(font)
self.label.setObjectName("label")
self.door = QtWidgets.QPushButton(self.centralwidget)
self.door.setGeometry(QtCore.QRect(90, 170, 75, 23))
self.door.setObjectName("door")
self.exit.clicked.connect(self.click_exit)
self.exit2.clicked.connect(self.click_exit)
self.door.clicked.connect(self.click_door)
self.return_2.clicked.connect(self.click_return_2)
self.passwd.clicked.connect(self.click_passwd)
self.pushButton.clicked.connect(self.click_pass)
self.admin.clicked.connect(self.click_admin)
self.login.clicked.connect(self.click_login)
self.open.clicked.connect(self.click_open)
self.face.clicked.connect(self.click_face)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 913, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.stackedWidget.setCurrentIndex(3)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "開鎖"))
self.label_4.setText(_translate("MainWindow", "請輸入密碼"))
self.admin.setText(_translate("MainWindow", "管理員(人臉錄入)"))
self.passwd.setText(_translate("MainWindow", "密碼開鎖"))
self.face.setText(_translate("MainWindow", "人臉識別開鎖"))
self.exit.setText(_translate("MainWindow", "退出系統"))
self.admin_pass.setText(_translate("MainWindow", "管理員密碼"))
self.admin_name.setText(_translate("MainWindow", "管理員名"))
self.login.setText(_translate("MainWindow", "登錄"))
self.open.setText(_translate("MainWindow", "錄入"))
self.label_2.setText(_translate("MainWindow", "請輸入要錄入的學號"))
self.label_3.setText(_translate("MainWindow", "歡迎,請點擊左側按鈕進入菜單頁面"))
self.return_2.setText(_translate("MainWindow", "返回首頁"))
self.exit2.setText(_translate("MainWindow", "退出"))
self.label.setText(_translate("MainWindow", "智能門禁人臉識別系統"))
self.door.setText(_translate("MainWindow", "進入菜單"))
def click_admin(self):
self.stackedWidget.setCurrentIndex(4)
def click_login(self):
if self.admin_line_name.text()=='admin' or self.admin_line_pass.text()=='fjnupass':
self.stackedWidget.setCurrentIndex(2)
r = QMessageBox.information(self, 'welcome', '請輸入學號,錄入對應人臉', QMessageBox.Ok)
else:
r = QMessageBox.information(self, 'warning', '用戶名或密碼錯誤', QMessageBox.Ok)
def click_door(self):
self.stackedWidget.setCurrentIndex(1)
def click_return_2(self):
self.stackedWidget.setCurrentIndex(3)
def click_exit(self):
sys.exit(app.exec_())
def click_passwd(self):
self.stackedWidget.setCurrentIndex(0)
def click_face(self):
s = recon_faces()
if(s!='unknown'):
QMessageBox.information(self,"Welcome","已經開門",QMessageBox.Ok)
else:
QMessageBox.information(self, "Warning", "未識別出", QMessageBox.Ok)
def click_open(self):
name = self.lineEdit.text()
fp = open('names.txt','a+')
# 將學號存儲到文件中
fp.write(name+',')
fp.close()
fp2 = open('names.txt','r+')
str = fp2.read()
names = str.split(',')
id = len(names)-2
QMessageBox.information(self, "!!", '開始錄入,請正式攝像頭,摘下眼睛', QMessageBox.Ok)
input_face_data(id)
QMessageBox.information(self,"!!",'人臉錄入結束,開始訓練',QMessageBox.Ok)
recon()
QMessageBox.information(self, "!!", '人臉識別模型訓練結束', QMessageBox.Ok)
# video_detc()
# def click_enterButton(self):
# pswd = "12345678"
# if self.admin_passwd.text()==pswd:
def click_pass(self):
if self.id.text()=='12345678':
r = QMessageBox.information(self, 'welcome', '歡迎回宿舍',QMessageBox.Ok)
self.stackedWidget.setCurrentIndex(3)
else:
r = QMessageBox.information(self, 'warning', '宿舍密碼錯誤', QMessageBox.Ok)
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
# import pics_ui_rc # 導入添加的資源(根據實際情況填寫文件名)
app = QApplication(sys.argv)
MainWindow = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())