基于pyqt+OpenCV设计的用户密码或人脸识别登录GUI程序设计

开发环境:

  • Windows7 64位
  • python3.7
  • pyqt5
  • pycharm
  • OpenCV3.4
  • QT Designer
  • PyUIC

目录

 功能介绍

程序代码

软件截图


 功能介绍

该程序主要在pycharm中开发,导入至pycharm里的外部工具有QT Designer和PyUIC。其中QT Designer用于GUI布局,PyUIC用于将ui文件转换为.py可执行文件。完整的程序包可点击资料包下载。在这里简单介绍程序的执行步骤或功能,并附上相关截图。

首先启动程序,进入登录界面,包括用户名密码登录方式和人脸识别登录方式。关于用户名登录方式,用户名来自人脸识别信息录入的人名,密码是存储在一个password.txt文本中。这种登录方式会有用户名不存在提示、密码错误提示,若登录成功,则会弹出“请编写主程序的对话框”,当然读者也可以编写自定义程序。

而关于人脸识别登录,有两个按钮:“人脸信息录入按钮”和“人脸识别登录”按钮。进入“人脸信息录入按钮”后,要求输入用户名,然后点击“确认”按钮,进行人脸数据采集、人脸模型训练、最后弹出“人脸信息录入成功”消息框。

温馨提示:

输入的用户名将保存在user_names.txt文本中,并以逗号隔开。人脸数据采集,小编设置的为150张图片。

点击“人脸识别登录”按钮,则会弹出人脸识别窗口,并在人脸框的左上角显示识别到的人物所对应的序号(由于OpenCV显示汉字比较麻烦,所以这里选择人名所对应的序号作为识别结果),在人脸框的左下角显示识别结果的置信度。

人脸识别程序设计:

如果识别置信度大于60%,则为识别成功,并退出人脸识别界面,弹出“欢迎您:人名”对话框。如果识别不出来,则等待10秒左右退出识别界面,并弹出“人脸识别失败”对话框。

注意:

登录界面的布局设计是在QT Designer中完成,在转成.py文件后,需要对程序作一些修改和补充,以满足实际开发需求,比如:类申明中,object需要改成QWidget,否则不能弹出QMessageBox消息对话框。

程序代码

下面给出完整的程序,主要由三个程序组成:login.py、faces_input_frame.py和face_recognize.py。

# -*- coding: utf-8 -*-
#login.py程序
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox,QWidget
from faces_input_frame import Ui_Dialog
import os


class Ui_Form(QWidget):  #将object改为QWidget,才能弹出消息对话框
    def __init__(self):
        super(Ui_Form,self).__init__() #用户添加代码
    def setupUi(self, Form):
        self.form=Form  #用户添加代码
        Form.setObjectName("Form")
        Form.setMinimumSize(QtCore.QSize(329, 230))
        Form.setMaximumSize(QtCore.QSize(400, 230))
        Form.setStyleSheet("")
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(63, 43, 64, 16))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(63, 80, 48, 16))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.lineEdit_2 = QtWidgets.QLineEdit(Form)
        self.lineEdit_2.setGeometry(QtCore.QRect(121, 80, 133, 20))
        self.lineEdit_2.setEchoMode(QtWidgets.QLineEdit.Password)
        self.lineEdit_2.setCursorPosition(0)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(70, 150, 75, 23))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(170, 150, 75, 23))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setObjectName("pushButton_2")
        self.checkBox = QtWidgets.QCheckBox(Form)
        self.checkBox.setGeometry(QtCore.QRect(63, 110, 151, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.checkBox.setFont(font)
        self.checkBox.setObjectName("checkBox")
        self.lineEdit_3 = QtWidgets.QLineEdit(Form)
        self.lineEdit_3.setGeometry(QtCore.QRect(121, 41, 133, 20))
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.pushButton_face_pass = QtWidgets.QPushButton(Form)
        self.pushButton_face_pass.setGeometry(QtCore.QRect(279, 100, 104, 41))
        self.pushButton_face_pass.setMaximumSize(QtCore.QSize(16777215, 16777213))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.pushButton_face_pass.setFont(font)
        self.pushButton_face_pass.setObjectName("pushButton_face_pass")
        self.pushButton_face_input = QtWidgets.QPushButton(Form)
        self.pushButton_face_input.setGeometry(QtCore.QRect(280, 31, 104, 41))
        self.pushButton_face_input.setMaximumSize(QtCore.QSize(16777215, 16777213))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.pushButton_face_input.setFont(font)
        self.pushButton_face_input.setObjectName("pushButton_face_input")

        self.retranslateUi(Form)
        self.pushButton.clicked.connect(self.close)
        self.pushButton_2.clicked.connect(self.open)
        self.pushButton_face_input.clicked.connect(self.faceinput)
        self.pushButton_face_pass.clicked.connect(self.facepass)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label.setText(_translate("Form", "用户名:"))
        self.label_2.setText(_translate("Form", "密码:"))
        self.pushButton.setText(_translate("Form", "取消"))
        self.pushButton_2.setText(_translate("Form", "确认"))
        self.checkBox.setText(_translate("Form", "记住用户名和密码"))
        self.pushButton_face_pass.setText(_translate("Form", "人脸识别登录"))
        self.pushButton_face_input.setText(_translate("Form", "人脸信息录入"))

    def open(self):
        #--------判断用户是否存在--------------
        fl = open('user_names.txt', 'r+')
        pre_name = fl.read()
        names = pre_name.split(',')
        fl.close()
        if self.lineEdit_3.text() in names:
            fl = open('password.txt', 'r+')
            password= fl.read()
            if self.lineEdit_2.text() ==password:
                reply=QMessageBox.information(self,'提示','请编写主程序',QMessageBox.Close)
            else:
                reply=QMessageBox.information(self,'提示','密码错误',QMessageBox.Close)


        else:
            reply=QMessageBox.information(self,'提示','用户不存在',QMessageBox.Close)


    def close(self, event):
        self.close()
    def faceinput(self,event):
        self.form.hide()
        Form1=QtWidgets.QDialog()
        ui=Ui_Dialog()
        ui.setupUi(Form1)
        Form1.show()
        Form1.exec_()
        self.form.show()   #子窗口关闭后,主窗口显示


    def facepass(self,event):
        import face_recognize
        get_name=face_recognize.recognize_face()#返回识别的人名
        if get_name=="unknown":
            reply = QMessageBox.information(self, '提示', '人脸识别失败', QMessageBox.Close)
        else:
            reply = QMessageBox.information(self, '提示', "欢迎您:"+get_name, QMessageBox.Ok)
            print("编写其他程序")


if __name__=="__main__":
    import sys
    app=QtWidgets.QApplication(sys.argv)
    widget=QtWidgets.QWidget()
    ui=Ui_Form()
    ui.setupUi(widget)
    widget.show()
    sys.exit(app.exec_())
# -*- coding: utf-8 -*-
#faces_input_frame.py程序
# Form implementation generated from reading ui file 'faces_input_frame.ui'
#
# Created by: PyQt5 UI code generator 5.12.2
#
# WARNING! All changes made in this file will be lost!
import face_recognize
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox,QWidget
class Ui_Dialog(QWidget):
    def setupUi(self, Dialog):
        self.form=Dialog #用户添加代码
        Dialog.setObjectName("Dialog")
        Dialog.resize(315, 104)
        Dialog.setMinimumSize(QtCore.QSize(315, 104))
        Dialog.setMaximumSize(QtCore.QSize(315, 104))
        Dialog.setAutoFillBackground(False)
        self.Button_Enter = QtWidgets.QPushButton(Dialog)
        self.Button_Enter.setGeometry(QtCore.QRect(221, 21, 75, 27))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.Button_Enter.setFont(font)
        self.Button_Enter.setObjectName("Button_Enter")
        self.Button_Exit=QtWidgets.QPushButton(Dialog)
        self.Button_Exit.setGeometry(QtCore.QRect(221, 54, 75, 27))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.Button_Exit.setFont(font)
        self.Button_Exit.setObjectName("Button_Exit")
        self.face_name=QtWidgets.QLabel(Dialog)
        self.face_name.setGeometry(QtCore.QRect(40, 20, 131, 16))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.face_name.setFont(font)
        self.face_name.setObjectName("face_name")
        self.face_name_frame=QtWidgets.QLineEdit(Dialog)
        self.face_name_frame.setGeometry(QtCore.QRect(30, 40, 167, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.face_name_frame.setFont(font)
        self.face_name_frame.setText("")
        self.face_name_frame.setObjectName("face_name_frame")

        self.retranslateUi(Dialog)
        self.Button_Enter.clicked.connect(self.Enter)
        self.Button_Exit.clicked.connect(self.ext)
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.Button_Enter.setText(_translate("Dialog", "确认"))
        self.Button_Exit.setText(_translate("Dialog", "退出"))
        self.face_name.setText(_translate("Dialog", "请输入您的姓名:"))

    def Enter(self):
        fl = open('user_names.txt','a+')
        if self.face_name_frame.text()=="":
            #输入为空时
            reply = QMessageBox.information(self, '提示', '请输入有效用户名', QMessageBox.Ok)
        else:
            fl.write(self.face_name_frame.text()+',')
            fl.close()

            reply = QMessageBox.information(self, '提示', '正在采集人脸数据', QMessageBox.Ok)
            face_recognize.Collect_faces()
            reply = QMessageBox.information(self, '提示', '正在训练数据', QMessageBox.Ok)
            face_recognize.Training_faces()
            reply = QMessageBox.information(self, '提示', '人脸信息录入成功', QMessageBox.Ok)


    def ext(self,event):
        self.form.close()


if __name__ == "__main__":
    import sys
    app=QtWidgets.QApplication(sys.argv)
    Dialog=QtWidgets.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())
# -*- coding: utf-8 -*-
#face_recognize.py程序
def Collect_faces():
    import cv2
    import os
    # 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2

    cap = cv2.VideoCapture(0)

    face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

    fl = open('user_names.txt', 'r+')
    pre_name=fl.read()
    name = pre_name.split(',')
    face_id=len(name) - 2#去掉逗号及以零开始的序号,表示某人的一些列照片
    fl.close()
    #face_id = input('\n enter user id:')  #输入序号,表示某人的一些列照片

    print('\n Initializing face capture. Look at the camera and wait ...')

    count = 0

    while True:

        # 从摄像头读取图片

        sucess, img = cap.read()

        # 转为灰度图片

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # 检测人脸

        faces = face_detector.detectMultiScale(gray, 1.3, 5)

        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + w), (255, 0, 0))
            count += 1

            # 保存图像,从原始照片中截取人脸尺寸
            cv2.imwrite("Facedata/User." +str(face_id) + '.' + str(count) + '.jpg', gray[y: y + h, x: x + w])

            cv2.imshow('image', img)

        # 保持画面的持续。

        k = cv2.waitKey(1)

        if k == 27:  # 通过esc键退出摄像
            break

        elif count >=150:  # 得到150个样本后退出摄像
            break

    # 关闭摄像头
    cap.release()
    cv2.destroyAllWindows()

def Training_faces():
    import numpy as np
    from PIL import Image
    import os
    import cv2
    # 人脸数据路径
    path = 'Facedata'

    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)]  # join函数的作用?
        faceSamples = []
        ids = []
        for imagePath in imagePaths:
            PIL_img = Image.open(imagePath).convert('L')  # convert it to grayscale
            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('Training faces. It will take a few seconds. Wait ...')
    faces, ids = getImagesAndLabels(path)
    recognizer.train(faces, np.array(ids))

    recognizer.write(r'face_trainer\trainer.yml')
    print("{0} faces trained. Exiting Program".format(len(np.unique(ids))))

def recognize_face():
    #识别时间10秒;如果置信度大于60%,则识别成功并退出界面;否则至10秒后识别失败并退出
    import cv2
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.read('face_trainer/trainer.yml')
    cascadePath = "haarcascade_frontalface_default.xml"
    faceCascade = cv2.CascadeClassifier(cascadePath)
    font = cv2.FONT_HERSHEY_SIMPLEX
    idnum =None #初始化识别序号
    fl = open('user_names.txt', 'r+')
    pre_name = fl.read()
    names = pre_name.split(',')

    cam = cv2.VideoCapture(0)
    minW = 0.1 * cam.get(3)
    minH = 0.1 * cam.get(4)
    time=0
    while True:
        result = "unknown"   #初始化识别失败
        time+=1
        ret, img = cam.read()
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.2,
            minNeighbors=5,
            minSize=(int(minW), int(minH))
        )
        face_num=None  #初始化人脸序号

        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
            idnum, confidence = recognizer.predict(gray[y:y + h, x:x + w])
            if confidence>60: #60%的识别置信度
                face_num=idnum
                result= names[idnum]
                confidence = "{0}%".format(round(100 - confidence))
                cam.release()
                cv2.destroyAllWindows()  #退出摄像头
                return result
            else:
                confidence = "{0}%".format(round(100 - confidence))
            cv2.putText(img, str(face_num), (x + 5, y - 5), font, 1, (0, 0, 255), 1)
            cv2.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (0, 0, 0), 1)
        cv2.imshow('camera', img)#弹出摄像头与否
        k = cv2.waitKey(1)
        if k == 27:
            break
        elif time>100:  # 大约10秒识别时间
            break
    cam.release()
    cv2.destroyAllWindows()
    return result   #返回识别结果:人名或“unknown”

软件截图

基于pyqt+OpenCV设计的用户密码或人脸识别登录GUI程序设计_第1张图片

基于pyqt+OpenCV设计的用户密码或人脸识别登录GUI程序设计_第2张图片

基于pyqt+OpenCV设计的用户密码或人脸识别登录GUI程序设计_第3张图片

 欢迎关注微信公众号“Py生活”,学知识,享生活!

 

你可能感兴趣的:(Python机器学习,人脸识别,pyqt,OpenCV,python,GUI)