在第一篇文章中已经完成了人脸实时监测和识别,在这篇文章中我们使用PyQt5库搭建GUI界面,与之前的程序结合构建人脸识别监测系统,大家可以根据自己的熟悉程度选择不同的框架,python客户端主要就是tkinterpyqt5,熟悉前后端框架的也可以用html+css+js+django/flask之类的解决。

本项目采用PyQt库作为UI界面的编写。

一、QT常用控件

在这里介绍几个本次项目用到的控件

1.QLabel标签控件

用于显示文本或图像,不提供用户交互功能,标签的视觉外观可以以各种方式配置。

setText(const QString &text) 设置显示文本
void setAlignment(Qt::Alignment) 设置文本显示位置
void setFont(const QFont &) 设置字体
void setPixmap(const QPixmap &) 设置图片
void setMovie(QMovie *movie) 设置动图
使用方法

QLabel *label = new QLabel(this);                   //创建Qlabel对象
label->setGeometry(50, 50, 200, 30);            //设置位置
label->setText("我是标签");                      //设置显示文本
label->setAlignment(Qt::AlignCenter);           //设置字体居中显示
QFont font = QFont("宋体", 15);
label->setFont(font);                           //设置字体
label->setStyleSheet("QLabel{color:red; background-color:blue}");   //设置字体颜色和背景色

2.QPushButton按钮控件

Qt提供的按钮控件,是Qt中常用到的控件,继承自QAbstractButton类

setText(const QString &text) 设置显示文本

setFlat(bool) 设置为扁平状,true为扁平状

isFlat() 判断是否为扁平状

setIcon(const QIcon &icon) 设置图片

setMenu(QMenu* menu) 设置菜单

使用方法

QPushButton *btn = new QPushButton(this);   //在当前界面创建按钮
btn->setText("我是非扁平状");                 //设置按钮显示文本
btn->setGeometry(150, 100, 100, 50);        //设置显示位置

3.QLineEdit输入控件

一个单行文本编辑器,允许用户通过一系列有用的编辑功能输入和编辑单行纯文本,包括撤消和重做、剪切和粘贴以及拖放

void setText(const QString &text) 设置显示文本
QString text() const 获取文本内容
void setEchoMode(EchoMode) 设置输出模式
void setPlaceholderText(const QString &) 设置占位提示符
void setClearButtonEnabled(bool enable) 设置清空按钮
void setMaxLength(int) 设置文本最大长度
void setCompleter(QCompleter *completer) 设置自动补全

使用方法

QLineEdit *le = new QLineEdit(this);            //创建QLineEdit对象
le->setGeometry(100, 70, 200, 30);                //设置显示位置
le->setText("我是文本输入框");                    //设置显示文本
qDebug() << le->text();                            //控制台打印文本

4.QCheckBox输入控件

一个选项按钮,可以打开(选中)或关闭(未选中)。复选框通常用于表示应用程序中可以启用或禁用而不影响其他功能的功能。可以实现不同类型的行为。提供了多选多的选择模式

setText(const QString &text) 设置显示文本
setChecked(bool) 未开启三态模式设置选中状态,默认为未选中,true为选中
isChecked() 判断是否选中
setTristate(bool y = true) true为开启三态模式
setCheckState(Qt::CheckState state) 开启三态模式后设置选中状态
使用方法

QCheckBox *checkBox1 = new QCheckBox(this);             //创建QCheckBox对象
checkBox1->move(100, 50);                               //设置位置
checkBox1->setText("语文");                              //设置显示文本

QCheckBox *checkBox2 = new QCheckBox(this);
checkBox2->move(100, 100);
checkBox2->setText("数学");
checkBox2->setChecked(true);                            //设置选中状态,默认为未选中

QCheckBox *checkBox3 = new QCheckBox(this);
checkBox3->move(100, 150);
checkBox3->setText("英语");

checkBox3->setTristate(true);                           //开启三态选择模式
checkBox3->setCheckState(Qt::PartiallyChecked);         //设置选中状态

5.QTimer类

QTimer类提供了重复和单次触发信号的定时器

QTimer类为定时器提供了一个高级别的编程接口。很容易使用:首先,创建一个QTimer,连接timeout()信号到适当的槽函数,并调用start(),然后在恒定的时间间隔会发射timeout()信号

6.QBasicTimer类

一个很快的、轻量级的定时器类,它主要被Qt内部使用。这个类的使用非常简单。一般我们只需要创建一个该类的对象,然后调用它的start() 方法即可。start()方法的具体声明如下:

void QBasicTimer::start(int msec, QObject *object)
void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)

其中,msec参数表示定时器的时间间隔,以毫秒为单位,object参数表示接受定时器到期事件的对象

7.QProgressBar类

提供了一个水平或垂直的进度条,可以使用setMinimum()和setMaximum指定最小和最大步数

void setMaximum(int maximum) 设置最大值
void setMinimum(int minimum) 设置最小值
void setRange(int minimum, int maximum) 设置范围,最大、最小值
void setValue(int value) 设置当前值
void reset() 重置
void setOrientation(Qt::Orientation) 设置方向,垂直,水平
void setAlignment(Qt::Alignment alignment) 设置对齐方式,居中,左、右
void setTextVisible(bool visible) 设置进度条文本是否显示
void setInvertedAppearance(bool invert) 设置正、反
void setFormat(const QString &format) 设置文本显示格式

二.人脸识别主页面代码实现

首先实现在QT界面中打开摄像头并将摄像头图像显示在QT控件内,通过下面这段代码,首先实现了摄像头的初始化,并在face_rec()函数中实现了基于 Haar 功能的级联分类器的对象检测,在主函数通过定时器用于控制摄像头的显示帧率

   def camera_init(self):
        # 打开设置摄像头对象
        self.cap = cv2.VideoCapture()
        self.CAM_NUM = 0
        self.__flag_work = 0
        self.x = 0
        self.count = 0
        self.cap.set(4, 951)  # set Width
        self.cap.set(3, 761)  # set Height    

    # 显示人脸识别视频界面
    def face_rec(self):
        if self.timer_camera.isActive() == False:
            flag = self.cap.open(self.CAM_NUM)
            if flag == False:
                msg = QtWidgets.QMessageBox.warning(self, u"Warning", u"请检测相机与电脑是否连接正确",
                                                    buttons=QtWidgets.QMessageBox.Ok,
                                                    defaultButton=QtWidgets.QMessageBox.Ok)
            else:
                self.timer_camera.start(30)
        else:
            self.timer_camera.stop()
            self.cap.release()


     def show_camera(self):
        flag, self.image = self.cap.read()
        gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.2,
            minNeighbors=5,
            minSize=(20, 20)
        )
        for (x, y, w, h) in faces:
            cv2.rectangle(self.image, (x, y), (x + w, y + h), (255, 0, 0), 2)
            roi_gray = gray[y:y + h, x:x + w]
            roi_color = self.image[y:y + h, x:x + w]

        # 将视频显示在了label上
        show = cv2.resize(self.image, (960, 720))
        show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
        showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)
        self.lab_face.setPixmap(QtGui.QPixmap.fromImage(showImage))

将训练好的人脸数据存放在datafile文件中,主页代码的作用主要是通过PyQt5库搭建主界面,首先创建了一个label对象,显示文本为”欢迎使用人脸识别系统”,其次创建了两个按键,一个按键用于人脸识别,另一个按键用于管理员管理人脸数据。

# 创建主界面类
class Ui_Menu(QWidget):
    def __init__(self):
        super(Ui_Menu, self).__init__()
        # 创建label并设置文本内容
        self.label = QLabel('欢迎使用人脸识别系统', self)
        # 创建按键
        self.btn_ordinary = QPushButton('人脸识别', self)
        self.btn_admin = QPushButton('人脸注册', self)

        file = open("./datafile.txt", 'ab+')
        file.close()

        if os.path.getsize("./datafile.txt"):
            self.datafile = open("./datafile.txt", 'rb')
            global data
            data = pickle.load(self.datafile)
            self.datafile.close()
        print(data)

        # 初始化界面
        self.init_ui()

    def init_ui(self):
        # 设置窗口大小
        self.resize(1280, 800)
        # 设置label框的位置
        self.label.move(180, 240)

        # 设置按键框的位置和大小
        self.btn_ordinary.setGeometry(550, 420, 181, 61)
     self.btn_admin.setGeometry(550, 510, 181, 61)

        # 设置label样式(字体、大小、颜色等)
        self.label.setStyleSheet(
            "QLabel{color:rgb(0,0,0,255);"  # 字体颜色为黑色
            "font-size:82px;font-weight:bold;"  # 大小为70 加粗
            "font-family:Roman times;}")  # Roman times字体

        self.btn_ordinary.setStyleSheet(
            "QPushButton{color:rgb(0,0,0,255);"  # 字体颜色为黑色
            "font-size:30px;"  # 大小为30 
            "font-family:Roman times;}")  # Roman times字体

    self.btn_admin.setStyleSheet(
            "QPushButton{color:rgb(0,0,0,255);"  # 字体颜色为黑色
            "font-size:30px;"  # 大小为30 
            "font-family:Roman times;}")  # Roman times字体

        # 点击普通用户按钮事件
        self.btn_ordinary.clicked.connect(self.slot_btn_ordinary)
      # 点击管理员按钮事件
        self.btn_admin.clicked.connect(self.slot_btn_admin)

    # 点击普通用户按钮事件
    def slot_btn_ordinary(self):
        self.face_reco = Ui_face_reco()
        self.face_reco.show()
        self.hide()
    # 点击管理员按钮事件
    def slot_btn_admin(self):
        self.manager_face = Ui_manager_face()
        self.manager_face.show()
        self.hide()

运行效果如下:

三.人脸识别页面代码实现

其次创建人脸识别窗口,在代码中首先创建控件,并初始化摄像头数据,创建定时器并初始化界面,然后调用人脸识别代码,运行人脸识别并将人脸识别的效果显示在label控件里

# 创建人脸识别通用户界面类
class Ui_face_reco(QWidget):
    def __init__(self):
        super(Ui_face_reco, self).__init__()

        # 创建控件
        self.lab_face = QLabel(self)
        self.btn_back = QPushButton(self)
        self.lab_body = QLabel(self)
        self.lab_ID = QLabel(self)
        self.lab_ID_E = QLabel(self)
        self.lab_SEX = QLabel(self)
        self.lab_SEX_E = QLabel(self)
        self.lab_PARENT = QLabel(self)
        self.lab_PARENT_E = QLabel(self)
        self.lab_T_F = QLabel(self)

        # 创建定时器
        self.timer_camera = QtCore.QTimer()
        self.user = []

        # 初始化摄像头数据
        self.camera_init()

        print(data)

        # 初始化界面
        self.init_ui()

        # 点击返回按键返回上一界面
        self.btn_back.clicked.connect(self.slot_btn_back)

        # 显示人脸识别视频界面
        self.face_rec()

        # 定时器函数
        self.timer_camera.timeout.connect(self.show_camera)

运行效果如下

可以准确检测到人脸并实现人脸识别的功能

四.人脸注册代码实现

在这一界面中主要是通过获取人脸样本实现录入人脸的功能,具体功能实现代码如下:

    # 录入人脸线程
    def thread_pic(self):
        print("线程出没!!!")
        print(self.Edit_ID.text())

        # 创建目录,将获取的人脸照片放入指定的文件夹
        self.file = "./Face_data/"

        while (True):
            ret, self.img = self.cap.read()
            # 垂直翻转视频图像
            # 灰度化处理
            gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
            faces = faceCascade2.detectMultiScale(gray, 1.3, 5)

            # 判断是否存在文件夹如果不存在则创建为文件夹
            self.folder = os.path.exists(self.file)
            if not self.folder:
                # makedirs 满权限创建文件时如果路径不存在会创建这个路径
                os.makedirs(self.file)
                os.chmod(self.file, 0o777)

            for (x, y, w, h) in faces:
                cv2.rectangle(self.img, (x, y), (x + w, y + h), (255, 0, 0), 2)
                self.count += 1
                # 将捕获的图像保存到指定的文件夹中
                bool = cv2.imwrite(self.file + "/User." + str(self.Edit_ID.text()) + '.' + str(self.count) + ".png",
                                   gray[y:y + h, x:x + w])

            # 取60张人脸样本,停止录像
            if self.count >= 60:
                print("OK!")
                break
        self.recognizer = cv2.face.LBPHFaceRecognizer_create()

创建录入人脸数据的主函数如下:

# 创建管理人脸数据界面类
class Ui_manager_face(QWidget):
    def __init__(self):
        super(Ui_manager_face, self).__init__()

        # 初始化 ID
        self.ID_num = ""
        self.lab_face = QLabel(self)

        # 初始化进度条定时器
        self.timer = QBasicTimer()
        self.step = 0

        # 创建数字按键

        # 创建容器存放数字键,使用栅格布局

        # 创建groupBox控件
        self.groupBox = QtWidgets.QGroupBox(self)

        # 创建lab_ID控件
        self.lab_ID = QLabel(self.groupBox)
        self.Edit_ID = QLineEdit(self.groupBox)
        self.btn_enter = QPushButton(self.groupBox)
        self.progressBar = QtWidgets.QProgressBar(self.groupBox)
        self.btn_back = QPushButton(self)

        # 创建定时器
        self.timer_camera = QtCore.QTimer()

        # 初始化摄像头数据
        self.camera_init()

        # 初始化界面
        self.init_ui()

        # 显示人脸识别视频界面
        self.face_rec()

        # 定时器函数
        self.timer_camera.timeout.connect(self.show_camera)

        # 点击按钮开启线程
        self.btn_enter.clicked.connect(self.slot_btn_enter)


在这里将照片录入,再回到人脸识别界面就可以进行人脸验证了