Python | 人脸识别系统 — 用户操作

news2024/11/25 3:05:35

本博客为人脸识别系统的摄像头画面展示代码解释

人脸识别系统博客汇总:人脸识别系统-博客索引

项目GitHub地址:

注意:阅读本博客前请先参考以下博客

工具安装、环境配置:人脸识别系统-简介

UI界面设计:人脸识别系统-UI界面设计

UI事件处理:人脸识别系统-UI事件处理

人脸识别:人脸识别系统-人脸识别

活体检测:人脸识别系统-活体检测

阅读完本博客后可以继续阅读:

摄像头画面展示:人脸识别系统-摄像头画面展示

用户端逻辑:

  • 人脸识别:Python | 人脸识别系统 — 人脸识别
  • 活体检测:Python | 人脸识别系统 — 活体检测
  • 背景模糊:Python | 人脸识别系统 — 背景模糊
  • 姿态检测:Python | 人脸识别系统 — 姿态检测
  • 人脸比对:Python | 人脸识别系统 — 人脸比对

管理员端逻辑:

  • 管理员操作:
  • 用户操作:

一、用户登录

        1、登录逻辑

        信息核验(数据库) -> 静默活体检测 -> 交互活体检测 -> 人脸识别 

        一旦用户超过三次没有登录成功(活体检测/人脸识别不成功),系统将当前用户进行锁定。用户需要通过管理员进行解锁。

    # 登录标志
    USER_LOGIN_MSG_FLAG = False # 用户信息核验成功标志
    USER_LOGIN_FLAG = False # 用户登录成功标志

    ... ...


    # 用户登录
    def user_login(self):
        if not self.cap.isOpened():
            QMessageBox.information(self, "提示", self.tr("请先打开摄像头"))
        else:
            global USER_LOGIN_FLAG
            if not USER_LOGIN_FLAG:
                QApplication.processEvents()
                login = LoginWindow(self) # 创建信息核验界面对象
                login.exec_() 
                global USER_LOGIN_MSG_FLAG
                global USER_LOGIN_NAME
                if USER_LOGIN_MSG_FLAG:
                    # 登录信息成功,进行活体检测
                    QMessageBox.about(self, '提示', '登录成功,进行活体检测')
                    if self.detect_face():
                        # 活体检测成功,进行人脸识别
                        global ENCODING_TEMP
                        face_encoding = FaceEncodingUtil.decoding_FaceStr(ENCODING_TEMP)
                        if self.recognize_instant_face(face_encoding):
                            QMessageBox.about(self, '提示', '登陆成功')
                            self.save_record(USER_LOGIN_NAME, '使用摄像头进行登录') # 使用excel表格进行保存
                            USER_LOGIN_FLAG = True
                        else:
                            QMessageBox.about(self, '提示', '人脸识别失败,请重新登录')
                            if USER_LOGIN_NAME != "":
                                UserSqlUtil.add_name_warn(USER_LOGIN_NAME)
                            USER_LOGIN_MSG_FLAG = False
                    else:
                        QMessageBox.about(self, '提示', '活体检测失败,请重新登录')
                        if USER_LOGIN_NAME != "":
                            UserSqlUtil.add_name_warn(USER_LOGIN_NAME)
                        USER_LOGIN_MSG_FLAG = False
                login.destroy()
            else:
                QMessageBox.about(self, '提示', '用户已经登录')

        2、信息核验

        用户点击 [用户登录] 按钮,主界面弹出信息核验界面,要求用户输入账号、密码。点击确认后,系统访问数据库,判断输入信息是否正确。

        信息核验界面相关代码:

# 用户登录界面
class LoginWindow(QDialog, LoginMsgUi):
    def __init__(self, parent=None):
        super(LoginWindow, self).__init__(parent)
        self.setupUi(self)

        self.minimize_button.clicked.connect(self.showMinimized)
        self.close_button.clicked.connect(self.cancel_login)

        self.confirm_button.clicked.connect(self.search_user)
        self.cancel_button.clicked.connect(self.cancel_login)

    # 点击确认,搜索用户
    def search_user(self):
        input_name = self.name_lineEdit.text()
        input_password = self.password_lineEdit.text()

        if input_name == "":
            QMessageBox.about(self, '提示', '姓名不能为空')
        elif input_password == "":
            QMessageBox.about(self, '提示', '密码不能为空')
        else:
            row = UserSqlUtil.search_by_name("\"" + input_name + "\"")
            if row:
                result = row[0]
                password = result[1]
                if input_password != password:
                    QMessageBox.about(self, '提示', '密码输入错误')
                else:
                    global USER_LOGIN_MSG_FLAG
                    count = UserSqlUtil.search_count_warn("\"" + input_name + "\"")
                    if count >= 3:
                        QMessageBox.about(self, '警告', '该账号目前已被锁定')
                        USER_LOGIN_MSG_FLAG = False
                    else:
                        global ENCODING_TEMP
                        global USER_LOGIN_NAME
                        USER_LOGIN_MSG_FLAG = True
                        ENCODING_TEMP = result[5]
                        USER_LOGIN_NAME = input_name
                    self.close_window()
            else:
                QMessageBox.about(self, '提示', '该用户不存在')

    # 点击取消按钮
    def cancel_login(self):
        global USER_LOGIN_MSG_FLAG
        USER_LOGIN_MSG_FLAG = False
        self.close_window()

    # 关闭窗口
    def close_window(self):
        self.name_lineEdit.setPlaceholderText("请输入姓名")
        self.password_lineEdit.setPlaceholderText("请输入密码")
        self.close()

        数据库表结构(user表)

        数据库代码

# -*- coding: utf-8 -*-
import pymysql


def init_conn():
    conn = pymysql.connect(
        host="127.0.0.1",  # 数据库的IP地址
        user="root",  # 数据库用户名称
        password="root",  # 数据库用户密码
        db="contest",  # 数据库名称
        port=3306,  # 数据库端口名称
        charset="utf8"  # 数据库的编码方式
    )
    return conn


def execute_with_bool(sql_str, args=()):
    conn = init_conn()
    cursor = conn.cursor()
    try:
        cursor.execute(sql_str, args)
        conn.commit()
        return True
    except Exception as e:
        conn.rollback()
        print(e)
        return False
    finally:
        cursor.close()


def execute_with_list(sql_str):
    conn = init_conn()
    cursor = conn.cursor()
    results = []
    try:
        cursor.execute(sql_str)
        results = cursor.fetchall()
    except Exception as e:
        conn.rollback()
        print(e)
    finally:
        cursor.close()
    return results


def insert_data(name, password, age, sex, more, face_encoding):
    return execute_with_bool(
        "insert into user(name,password,age,sex,more,face_encoding) values(%s,%s,%s,%s,%s,%s)",
        (name, password, age, sex, more, face_encoding))


def update_by_name(name, password, age, sex, more, face_encoding):
    return execute_with_bool(
        "update user set name=%s,password=%s,age=%s,sex=%s,more=%s,face_encoding=%s where name = %s",
        (name, password, age, sex, more, face_encoding, name))


def update_by_name_without_encoding(name, age, sex, more):
    return execute_with_bool("update user set name=%s,age=%s,sex=%s,more=%s where name = %s",
                             (name, age, sex, more, name))


def search_all_msg():
    return execute_with_list("select * from user")


def search_by_name(name):
    return execute_with_list("select * from user where name = " + name)


def search_count_name(name):
    return execute_with_list("select count(*) from user where name = " + name)[0][0]


def delete_by_name(name):
    return execute_with_bool("delete from user where name = %s", name)


def search_count_warn(name):
    return execute_with_list("select count(*) from warn where name = " + name)[0][0]


def add_name_warn(name):
    return execute_with_bool("insert into warn(name) values(%s)", name)

        3、活体检测

活体检测函数 detect_face() 详见博客:

      4、人脸识别

人脸识别函数 recognize_instant_face() 详见博客:

人脸识别使用的是函数 recognize_instant_face(),其中需要参数face_encoding,为1*128的矩阵。当我们从数据库取出当前登录用户的人脸编码时,为字符串类型,需要进行转换。编写工具类FaceEncodingUtil,调用编写的方法 decoding_FaceStr 进行转换。其工具类方法如下:

# -*- coding: utf-8 -*-
import numpy


def decoding_FaceStr(encoding_str):
    # 将字符串转为numpy ndarray类型,即矩阵
    # 转换成一个list
    decoding_list = encoding_str.strip(' ').split(',')
    # 将list中str转换为float
    decoding_float = list(map(float, decoding_list))
    face_encoding = numpy.array(decoding_float)
    return face_encoding

二、用户注册

        1、判断器

        摄像头截取当前人脸 -> 信息填写 -> 面部信息编码 -> 信息保存(数据库)

        摄像头截取当前人脸照片,使用当前时间点作为照片名保存到photo目录下,面部信息编码成功后删除照片。

    signal_register = pyqtSignal()  # 用户注册 界面信号

    ... ...

    # 用户注册
    def user_register(self):
        isCapOpened_flag = self.cap.isOpened()
        if not isCapOpened_flag:
            QMessageBox.information(self, "提示", self.tr("请先打开摄像头!"))
        else:
            ret, frame = self.cap.read()
            frame_location = face_recognition.face_locations(frame)
            if len(frame_location) == 0:
                QMessageBox.information(self, "提示", self.tr("没有检测到人脸,请重新拍摄!"))
            else:
                QMessageBox.information(self, "提示", self.tr("拍照成功!"))

                global PHOTO_FOLDER_PATH
                global SHOT_TEMP_NAME
                SHOT_TEMP_NAME = datetime.now().strftime("%Y%m%d%H%M%S")
                self.show_image.save(PHOTO_FOLDER_PATH + SHOT_TEMP_NAME + ".jpg")
                self.send_signal_register()

    # 发射信号 打开注册用户界面
    def send_signal_register(self):
        self.signal_register.emit()

        2、逻辑编写

        用户点击 [用户注册] 按钮,主界面弹出信息填写界面,要求用户输入账号、密码等信息。点击确认后,系统判断输入信息格式是否正确。

# 用户注册界面
class RegisterWindow(QMainWindow, RegisterMsgUi):
    def __init__(self, parent=None):
        super(RegisterWindow, self).__init__(parent)
        self.setupUi(self)

        self.minimize_button.clicked.connect(self.showMinimized)
        self.close_button.clicked.connect(self.close_window)
        self.cancel_button.clicked.connect(self.delete_shot)
        self.confirm_button.clicked.connect(self.fill_information)

    # 填写信息
    def fill_information(self):
        flag = 0
        name = self.name_lineEdit.text()
        password = self.password_lineEdit.text()
        age = self.age_lineEdit.text()
        sex = self.sex_lineEdit.text()
        more_infor = self.more_lineEdit.text()

        if self.judge_name_conflict(name):
            if name != '':
                # 输入密码
                if password != '':
                    # 输入年龄
                    if age == '':
                        age = '未知'
                    elif not str.isdigit(age):
                        flag = 1
                        QMessageBox.about(self, '提示', '请输入正确的年龄格式')
                    # 输入性别
                    if sex == '':
                        sex = '未知'
                    elif sex != '男' and sex != '女':
                        flag = 1
                        QMessageBox.about(self, '提示', '请输入正确的性别格式')
                        sex = '未知'
                    # 输入更多信息
                    if more_infor == '':
                        more_infor = '未知'

                    global PHOTO_FOLDER_PATH
                    global SHOT_TEMP_NAME
                    if flag == 0:
                        # 计算脸部数据并保存到数据库
                        QApplication.processEvents()
                        register_encoding = self.analyse_encoding(SHOT_TEMP_NAME)
                        if self.save_database(name, password, age, sex, more_infor, register_encoding):
                            QMessageBox.about(self, '提示', '完成注册')
                        else:
                            QMessageBox.about(self, '提示', '注册失败')
                        self.delete_shot()

                    elif flag == 1:
                        QMessageBox.about(self, '提示', '注册失败')
                else:
                    QMessageBox.about(self, '提示', '请输入密码')
            else:
                QMessageBox.about(self, '提示', '请输入姓名')
        else:
            QMessageBox.about(self, '提示', '用户' + name + '已经注册过')

    # 保存注册信息
    @staticmethod
    def save_database(name, password, age, sex, more, face_encoding):
        return UserSqlUtil.insert_data(name, password, age, sex, more, face_encoding)

    # 判断姓名是否冲突
    @staticmethod
    def judge_name_conflict(name):
        count = UserSqlUtil.search_count_name("\"" + name + "\"")
        if count != 0:
            return False
        else:
            return True

    # 分析截图
    @staticmethod
    def analyse_encoding(name):
        global PHOTO_FOLDER_PATH
        photo_path = PHOTO_FOLDER_PATH + name + ".jpg"
        register_images = face_recognition.load_image_file(photo_path)
        register_encoding = face_recognition.face_encodings(register_images)[0]
        return FaceEncodingUtil.encoding_FaceStr(register_encoding)

    # 删除截图
    def delete_shot(self):
        global PHOTO_FOLDER_PATH
        global SHOT_TEMP_NAME
        delete_shot_path = PHOTO_FOLDER_PATH + SHOT_TEMP_NAME + ".jpg"
        os.remove(delete_shot_path)
        SHOT_TEMP_NAME = ""
        self.close_window()

    # 关闭窗口
    def close_window(self):
        lineText = [self.age_lineEdit, self.sex_lineEdit, self.name_lineEdit, self.more_lineEdit]
        line = 0
        for lineEdit in lineText:
            lineEdit.setPlaceholderText(str(line))
            if 3 >= line >= 0:
                lineEdit.setPlaceholderText("请输入信息")
            line = line + 1
        self.close()

进行数据库保存的时候,面部编码数据为为1*128的矩阵,需要通过工具类FaceEncodingUtil的方法 encoding_FaceStr 进行转换。其工具类方法如下:

# -*- coding: utf-8 -*-
import numpy


def encoding_FaceStr(image_face_encoding):
    # 将numpy array类型转化为列表
    encoding__array_list = image_face_encoding.tolist()
    # 将列表里的元素转化为字符串
    encoding_str_list = [str(i) for i in encoding__array_list]
    # 拼接列表里的字符串
    encoding_str = ','.join(encoding_str_list)
    return encoding_str

三、用户登出

        用户登出操作比较简单,将全局标志 USER_LOGIN_FLAG 设置为False即可。

        判断器代码如下:

    # 用户登出
    def user_logout(self):
        global USER_LOGIN_FLAG
        global USER_LOGIN_NAME
        if not USER_LOGIN_FLAG:
            QMessageBox.about(self, '提示', '请先登录')
        else:
            USER_LOGIN_FLAG = False
            QMessageBox.about(self, '提示', '退出成功')
            self.save_record(USER_LOGIN_NAME, '退出登录') # 记录到excel表格中

四、Excel表格记录

        将用户登录、登出的操作时间、设备、用户名等信息保存到系统excel表格中。可以通过管理员身份登录系统,导出系统的excel表格进行查看。导出excel表格的代码在管理员端编写。

        保存信息到excel表格的代码如下:

    # 将记录保存到excel中
    @staticmethod
    def save_record(name, record):
        global DATA_FOLDER_PATH
        local_path = DATA_FOLDER_PATH + 'history.xls'

        old_book = xlrd.open_workbook(local_path)
        new_book = copy(old_book)

        sheet2 = new_book.get_sheet(0)
        sheet0 = old_book.sheet_by_index(0)
        n_rows = sheet0.nrows

        str_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        sheet2.write(n_rows + 1, 0, str_time)
        sheet2.write(n_rows + 1, 1, '摄像头')
        sheet2.write(n_rows + 1, 2, name)
        sheet2.write(n_rows + 1, 3, record)

        new_book.save('new_book.xls')
        os.remove(local_path)
        os.rename('new_book.xls', local_path)

        

阅读完本博客后可以继续阅读:

摄像头画面展示:人脸识别系统-摄像头画面展示

用户端逻辑:

  • 人脸识别:Python | 人脸识别系统 — 人脸识别
  • 活体检测:Python | 人脸识别系统 — 活体检测
  • 背景模糊:Python | 人脸识别系统 — 背景模糊
  • 姿态检测:Python | 人脸识别系统 — 姿态检测
  • 人脸比对:Python | 人脸识别系统 — 人脸比对

管理员端逻辑:

  • 管理员操作:
  • 用户操作:

注:以上代码仅为参考,若需要运行,请参考项目GitHub完整源代码: 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

错题汇总03

1.以下对二维数组a进行正确初始化的语句是 A int a[2][]{{0,1,2},{3,4,5}} B int a[][3]{{0,1,2},{3,4,5}} C int a[2][4]{{0,1,2},{3,4},{5}}; D int a[][3]{{0,,2},{},{3,4,5}} A数组列不能省略 C数组越界 D数组初始化每一行必须连续初始化 2.能把函数处理结果的二个数据…

msvcr110.dll丢失的解决方法-计算机中丢失msvcr110.dll怎么办?

看到您遇到了msvcr110.dll丢失的问题,这是由于您的计算机缺少必要的系统文件导致的。为了解决这个问题,您可以尝试以下几个步骤方法:就可以轻松解决msvcr110.dll丢失的问题。 msvcr110.dll修复方法一 重新安装Microsoft Visual C msvcr110.d…

windows安装node.js和vue3.x

目录 下载并安装node配置环境变量配置淘宝镜像源安装webpack全局打包工具安装cnpm安装vue-cli 3.xcnpm问题警告的解决办法 下载并安装node 1,下载nodejs 直接从node.js官网下载:https://nodejs.org/en/download 根据自己电脑的版本选择32位或者64位&…

建筑诊断用热像仪应用-flir T530红外热成像仪

建筑诊断用热像仪应用-flir T530红外热成像仪 建筑诊断领域热成像技术 隔热性能不良或隔热性能不足、潮气、建筑物外表面裂缝及不达标工程往往使住宅用建筑及商用建筑业主蒙受巨大的 经济损失。而红外热像仪却能够帮助您快速察觉有待改进的能效问题 建筑诊断用热像仪应用|带电…

两分钟成为 ChatGPT 国内高手【不要再拿ChatGPT当百度用了】

不要再问ChatGPT那些问百度的问题了,有更进阶的用法 更高效的编写prompts,以便ChatGPT给出更精准的回答 但是需要注意的是:国内现在根本没有GPT-4使用,但凡是说有GPT-4的都是骗子。 GPT 可以写文章,可以写诗&#x…

全方位揭秘!大数据从0到1的完美落地之运行流程和分片机制

一个完整的MapReduce程序在分布式运行时有三类实例进程: MRAppMaster: 负责整个程序的过程调度及状态协调MapTask: 负责Map阶段的整个数据处理流程ReduceTask: 负责Reduce阶段的整个数据处理流程 当一个作业提交后(mr程序启动),大概流程如下&#xff1…

TouchGFX开发(2)----触摸屏幕组件点亮LED

TouchGFX开发.1----安装软件 概述创建 TouchGFX 项目添加图片组件添加按钮interactions 设置生成代码打开文件配置LED触摸点亮LED演示效果 概述 了解如何使用 TouchGFX 配置屏幕,添加触摸按钮,并通过按钮控制板载 LED 的状态。 创建 TouchGFX 项目 打…

详解map、set、multimap、multiset的使用

✍作者:阿润菜菜 📖专栏:C 目录 前言set、multiset的使用1. set2. multiset3. 什么时候应该使用multiset而不是set map、multimap的使用1.map2.multimap3.什么时候应该使用multimap而不是map 前言 map、set、multimap、multiset是C STL中的四…

如何把握未来增长话语权,全链路数字化运营有解

近年来,良品铺子、元气森林、蔚来等迅速成为市场中现象级的品牌,它们往往在很短时间内就发展成市场的生力军和消费者青睐的对象。 仔细研究背后,这些新生品牌的崛起,核心商业逻辑跟以往品牌大为不同,明显更“懂”新生…

基于微信小程序的酒店预定管理系统设计与实现

第1章 绪论 1 1.1开发背景与意义 1 1.2开发方法 1 1.3论文结构 1 2系统开发技术与环境 3 2.1 系统开发语言 3 2.2 系统开发工具 3 2.3 系统页面技术 3 2.4 系统数据库的选择 4 2.5 系统的运行环境 4 2.5.1 硬件环境 4 2.5.2 软件环境 4 3系统分析 5 3.1可行性分析 5 3.1.1 经济…

Java——和为S的连续正数序列

题目链接 牛客网在线oj题——和为S的连续正数序列 题目描述 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为…

用Jmeter进行接口自动化测试的工作流程你知道吗?

目录 测试流程 接口测试相关文档管理规范 接口测试要点 测试流程 在测试负责人接受到测试任务后,应该按照以下流程规范完成测试工作。 2.1 测试需求分析 产品开发负责人在完成某产品功能的接口文档编写后,在核对无误后下发给对应的接口测试负责人…

word@论文后期优化和完善工作@页眉页脚页码@配置并导出pdf

文章目录 论文结构例 目录操作页眉页脚页眉样式检查所有页面的页眉添加横线 页码从第二页(封面后的一页)开始用罗马数字标页码 word导出pdf等其他格式额外配置带独立书签和目录打印pdf 最后的优化 论文结构 一篇规范的论文应该大致包括以下部分: 标题页&#xff1…

JavaScript全解析——canvas 入门(下)

canvas 线段两端的样式 ●canvas 中, 是可以设置线段两端的样子的 ●我们先来画三个平行线 // 0. 获取到页面上的 canvas 标签元素节点 const canvasEle document.querySelector(#canvas)// 1. 获取当前这个画布的工具箱 const ctx canvasEle.getContext(2d)// 2. 开始绘制第…

webpack 5 实战(2)

二十一、babel-loader 使用 使用babel-loader对js文件进行处理,在lg.Webpack.js配置文件中配置js文件规则。 使用单独的插件进行转换 使用预设进行转换 使用babel.config.js配置文件进行babel配置 const path require(path) const CopyWebpackPlugin require(…

day12 IP协议与ethernet协议

目录 IP包头 IP网的意义 IP数据报的格式 IP数据报分片 以太网包头(链路层协议) IP包头 IP网的意义 当互联网上的主机进行通信时,就好像在一个网络上通信一样,看不见互联的各具体的网络异构细节; 如果在这种覆盖…

RabbitMQ 死信队列实现

// consumer处理成功后,通知broker删除队列中的消息,如果设置multipletrue,表示支持批量确认机制以减少网络流量 channel.basicAck(deliveryTag, multiple);// 拒绝deliveryTag对应的消息,第二个参数是否requeue,true则…

Inception模型实现孤立手语词的识别

实现孤立手语词的识别流程如下,在实际研究中,本章将着重研究第三阶段内容,也就是模型的设计与实现过程,目的是提高手语图像的识别准确率。 Inception模型实现 Inception模型是谷歌研究人员在2014年提出的一个深度卷…

网工Python:如何使用Netmiko的SCP函数进行文件传输?

在网络设备管理中,传输配置文件、镜像文件等是经常需要进行的操作。Netmiko是一个Python库,可用于与各种网络设备进行交互,提供了一些用于传输文件的函数,其中包括SCP(Secure Copy Protocol)函数。本文将介…

【软考备战·希赛网每日一练】2023年5月4日

文章目录 一、今日成绩二、错题总结第一题第二题第三题第四题三、知识查缺 题目及解析来源:2023年05月04日软件设计师每日一练 一、今日成绩 二、错题总结 第一题 解析: 修改Linux文件权限命令:chmod。 第二题 解析: 第三题 解析…