Opencv

面部智能识别这项技术还是比较复杂的,要想彻底理解并付诸实践,得有一套扎实的理论架构和强大的技术工具。首先要提到的就是OpenCV,它可以说是集大成者,另外,Dlib也是不可忽视的,尤其以精准性闻名。这两者几乎是现代计算机视觉处理,特别是人脸相关应用的基础平台。如果你深入了解它们是如何从复杂的图像数据中识别出人脸的,你会看到一些挺有意思的技术细节。比如,OpenCV常用的做法是通过Haar级联这种效率极高的分类器来快速检测面部区域,能迅速从画面中找出潜在的面孔。而Dlib的做法就有点不同,它更注重从面部特征的角度出发,使用像方向梯度直方图这种描述子来提取面部的细节信息,获得这些特征之后,接下来就是身份识别的过程,通常会用支持向量机等分类器来判断身份。其实,这些看似独立的技术,通过巧妙的结合,最终就支撑起了一个精准的人脸识别系统。

Haar级联分类器

Haar图像特征最初是通过对矩形区域进行分析来开发的,它通过计算不同区域之间的灰度对比,能够捕捉到描述物体形态的关键信息。在人脸识别任务中,Haar特征的一个突出特点就是它能够有效抓取面部的关键结构,比如眼睛、鼻子、嘴巴等位置的亮度差异。正是依靠这种独特的亮度对比模式,分类器才能高效地区分出人脸目标,哪怕背景复杂杂乱。 Haar特征大致可以分为三种类型:边缘特征、线性特征和中心特征。而Haar特征值则是通过计算图像中不同区域的灰度变化来得出的。具体来说,它是通过计算白色矩形区域和黑色矩形区域的像素总和的差值,来表示图像在这些区域内的灰度差异。利用Haar特征,我们可以迅速从图像中提取出我们关心的区域(比如人脸),并进行进一步的检测。 

image.png

Haar级联分类器其实就是通过分析大量的训练样本来建造一堆简单的识别单元。它之所以能精准地锁定目标,主要就是因为它对Haar特征模式的理解和学习非常到位。为了让效果更好,系统还加上了自适应增强算法和逐级筛选的串联结构。 简单说,自适应增强算法的作用就是反复优化特征集合,调整每个阶段分类器的权重,让它越来越精确。而那种逐级筛选的串联结构就像是分步走的过程,让分类器一层一层地筛查目标,最终从一堆可能性中找出我们需要的那个。这种方式让Haar级联分类器在复杂的图像中也能快速又精准地识别出目标。 

image.png

Dlib库

Dlib,作为一个强大的C++库,并且提供Python接口,已经在机器学习和计算机视觉领域占据了重要地位。它不仅在学术研究中被广泛应用,在工业界的高要求部署场景中也同样表现不凡。Dlib的核心架构融合了图像计算和深度学习的精髓,凭借高效的算法和灵活的模块化设计,在视觉分析任务中展现出了非常优秀的性能,尤其是在精准识别人脸和面部特征方面。 Dlib通过集成方向梯度直方图(HOG)特征提取技术与支持向量机(SVM)分类策略,能够实现高效的人脸区域检测。这个库还提供了很多预训练模型,比如专门用于精确定位面部结构的68点或5点标注模型。这些模型能精准地捕捉面部的关键几何特征点,比如眼眶轮廓、鼻下点、嘴角连线和颚骨边界等,为后续的详细面部分析提供了坚实的基础

代码部分

主程序代码

from PyQt5 import QtCore
from control.mainWindow import MyWindow
import sys

#PyQt使用高分辨率
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)

#主函数
if __name__ == '__main__':
    app = QApplication(sys.argv)
    #实例化主界面
    myWin = MyWindow()
    #显示主界面
    myWin.show()
    sys.exit(app.exec_())

人脸记录部分代码

from view.checkinmodify import *
from PyQt5.QtWidgets import QWidget, QMessageBox, QAbstractItemView, QTableWidgetItem, QLabel, QDialog, QFileDialog
from model.connectsqlite import ConnectSqlite
import model.configuration
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from datetime import datetime
import os


class CheckInRecord(QWidget, Ui_CheckInRecordForm):

    def __init__(self, parent=None):
        super(CheckInRecord, self).__init__(parent)
        self.setupUi(self)
        # 连接 SQLite 数据库
        self.dbcon = ConnectSqlite(model.configuration.DATABASE_PATH)
        self.checkin_data = []
        self.pushButton_search.clicked.connect(self.search)
        self.pushButton_modify.clicked.connect(self.modify)
        self.pushButton_delete.clicked.connect(self.delete)
        self.pushButton_export.clicked.connect(self.export_to_txt)  # 连接导出按钮
        self.make_table()

    # 导出数据为 TXT 文件
    def export_to_txt(self):
        if len(self.checkin_data) == 0:
            reply = QMessageBox.warning(self, '提示', '没有可导出的数据!',
                                        QMessageBox.Yes, QMessageBox.Yes)
            return

        # 获取当前时间用于文件名
        current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
        default_filename = f"考勤记录报表_{current_time}.txt"

        # 打开文件保存对话框选择保存位置
        options = QFileDialog.Options()
        filepath, _ = QFileDialog.getSaveFileName(
            self,
            "保存考勤记录",
            default_filename,
            "Text Files (*.txt);;All Files (*)",
            options=options
        )

        if not filepath:  # 用户取消
            return

        try:
            with open(filepath, 'w', encoding='utf-8') as f:
                # 写入文件头
                f.write("考勤记录报表\n")
                f.write(f"导出时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write("=" * 60 + "\n\n")

                # 写入表头
                f.write(f"{'姓名':<15}{'学号':<20}{'考勤时间':<25}\n")
                f.write("-" * 60 + "\n")

                # 写入数据行
                for row in self.checkin_data:
                    name = row[1]
                    student_id = str(row[0])
                    checkin_time = row[2].split(".")[0]

                    f.write(f"{name:<15}{student_id:<20}{checkin_time:<25}\n")

                # 写入文件尾
                f.write("\n" + "=" * 60 + "\n")
                f.write(f"总记录数: {len(self.checkin_data)}")

            reply = QMessageBox.information(self, '成功', '报表导出成功!',
                                            QMessageBox.Yes, QMessageBox.Yes)

        except Exception as e:
            reply = QMessageBox.warning(self, '错误', f'导出失败: {str(e)}',
                                        QMessageBox.Yes, QMessageBox.Yes)

    # 搜索功能
    def search(self):
        print("search")
        search_str = self.lineEdit_search.text()
        row = 0
        search_result = None
        if search_str != '':
            # 遍历列表查找匹配数据
            for i in self.checkin_data:
                if search_str.lower() in str(i[1]).lower():
                    search_result = str(i[1])
                    self.tableWidget.setCurrentIndex(self.tableWidget.model().index(row, 1))
                if search_str.lower() in str(i[0]).lower():
                    search_result = str(i[0])
                    self.tableWidget.setCurrentIndex(self.tableWidget.model().index(row, 0))
                if search_str.lower() in str(i[2]).lower():
                    search_result = str(i[2])
                    self.tableWidget.setCurrentIndex(self.tableWidget.model().index(row, 2))
                row += 1
            if search_result == 0:
                reply = QMessageBox.warning(self, '错误', '未找到相关信息!',
                                            QMessageBox.Yes, QMessageBox.Yes)
        else:
            reply = QMessageBox.warning(self, '错误', '请输入搜索关键词',
                                        QMessageBox.Yes, QMessageBox.Yes)

    # 修改功能
    def modify(self):
        select = self.tableWidget.selectedItems()
        if len(select) != 0:
            row = self.tableWidget.selectedItems()[0].row()  # 获取选中的行
            column = self.tableWidget.selectedItems()[0].column()
            print(row, column)
            name = str(self.checkin_data[row][1])
            sid = str(self.checkin_data[row][0])
            checkin_time = str(self.checkin_data[row][2])
            id = self.checkin_data[row][-1]
            insert_list = [name, sid, checkin_time]
            dialog = CheckInModify(insert_list)
            dialog.exec_()
            modify_list = dialog.getInputs()
            modify_flag = modify_list[1]
            print("iddddd{}".format(id))
            result = self.dbcon.update_checkin_table(modify_list[0], id)
            if modify_flag:
                if result == 0:
                    self.make_table()
                    reply = QMessageBox.information(self, '成功', '修改成功!',
                                                    QMessageBox.Yes, QMessageBox.Yes)
                else:
                    reply = QMessageBox.warning(self, '错误', result,
                                                QMessageBox.Yes, QMessageBox.Yes)
        else:
            reply = QMessageBox.warning(self, '错误', '请选择需要修改的记录!',
                                        QMessageBox.Yes, QMessageBox.Yes)

    # 删除功能
    def delete(self):
        select = self.tableWidget.selectedItems()
        if len(select) != 0:
            row = self.tableWidget.selectedItems()[0].row()  # 获取选中的行
            column = self.tableWidget.selectedItems()[0].column()
            id = self.checkin_data[row][-1]
            result = self.dbcon.delete_checkin_table(id)
            if result == 0:
                self.make_table()
                reply = QMessageBox.information(self, '成功', '删除成功!',
                                                QMessageBox.Yes, QMessageBox.Yes)
            else:
                reply = QMessageBox.warning(self, '错误', result,
                                            QMessageBox.Yes, QMessageBox.Yes)
        else:
            reply = QMessageBox.warning(self, '错误', '请选择需要删除的数据!',
                                        QMessageBox.Yes, QMessageBox.Yes)

    # 显示数据库中的表格内容
    def make_table(self):
        # 清空表格
        self.tableWidget.clear()

        self.checkin_data = self.dbcon.return_all_checkin_record()
        data_show = []
        for row in self.checkin_data:
            name = row[1]
            student_id = str(row[0])
            checkin_time = row[2].split(".")[0]
            data_show.append([name, student_id, checkin_time])

        self.RowLength = 0
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setColumnWidth(0, 220)  # 设置第1列宽度
        self.tableWidget.setColumnWidth(1, 220)  # 设置第2列宽度
        self.tableWidget.setColumnWidth(2, 300)  # 设置第3列宽度

        self.tableWidget.setHorizontalHeaderLabels(["姓名", "学号", "进入时间"])
        self.tableWidget.setRowCount(self.RowLength)
        self.tableWidget.verticalHeader().setVisible(False)  # 隐藏垂直表头
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableWidget.raise_()

        for row_data in data_show:
            self.RowLength = self.RowLength + 1
            label = QLabel()
            self.tableWidget.verticalHeader().setDefaultSectionSize(40)
            self.tableWidget.setRowCount(self.RowLength)
            self.tableWidget.setItem(self.RowLength - 1, 0, QTableWidgetItem(row_data[0]))
            self.tableWidget.setItem(self.RowLength - 1, 1, QTableWidgetItem(row_data[1]))
            self.tableWidget.setItem(self.RowLength - 1, 2, QTableWidgetItem(row_data[2]))

            self.tableWidget.item(self.RowLength - 1, 0).setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.tableWidget.item(self.RowLength - 1, 1).setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.tableWidget.item(self.RowLength - 1, 2).setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    # 关闭窗口
    def close_all(self):
        self.close()


# 考勤记录修改对话框
class CheckInModify(QDialog, Ui_Dialog):

    def __init__(self, current_list, parent=None):
        super(CheckInModify, self).__init__(parent)
        self.setupUi(self)
        self.name = current_list[0]
        self.sid = current_list[1]
        self.checkin_time = current_list[2]
        self.lineEdit_sno.setText(self.sid)
        self.lineEdit_name.setText(self.name)
        print(self.checkin_time)
        self.modify_flag = False
        time1 = int(self.checkin_time.split(' ')[1].split(':')[0])
        time2 = int(self.checkin_time.split(' ')[1].split(':')[1])
        time1_format = str('{:0>2d}'.format(time1))
        time2_format = str('{:0>2d}'.format(time2))
        self.timeEdit_checkin.setTime(QTime.fromString(time1_format + ':' + time2_format))
        self.pushButton_add.clicked.connect(self.modify_return)

    def modify_return(self):
        self.modify_flag = True
        self.close()

    def getInputs(self):
        name = self.lineEdit_name.text()
        sid = self.lineEdit_sno.text()

        checkin_time = self.checkin_time.split(' ')[0] + " " + self.timeEdit_checkin.text()
        return [[name, sid, checkin_time], self.modify_flag]

人脸核验部分代码

点击基于人工智能的闸机人脸识别门禁系统查看全文

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐