OpenCv综合应用——人脸识别

一、利用PySimpleGUI构建窗口界面

1.1、 PySimpleGUI 的安装

python 复制代码
pip install pysimplegui

1.2、构建主界面

python 复制代码
import PySimpleGUI as psg

from face_gui.face_gather import face_gather
from face_gui.face_videos import face_video
from face_gui.face_tuopens import face_tuopen


def face_gui():
    # 创建一个布局组件
    layout = [
        [psg.Text('员工编号', size=(6, 1), font=('微软雅黑', 12)), psg.InputText(key='num', size=(20, 1))],
        [psg.Text('员工姓名', size=(6, 1), font=('微软雅黑', 12)), psg.InputText(key='name', size=(20, 1))],
        [psg.Text(key='nsg')],
        [psg.Text(key='msg')],
        [psg.Button('人脸采集'), psg.Button('打卡'), psg.Button('选择图片'), psg.Button('退出')],
        [psg.Image(key='video', size=(640, 480))]  # 添加摄像头显示区域
    ]
    # 创建一个窗口
    window = psg.Window('人脸识别系统', layout, icon='../images/hq.ico')

    while True:
        # 读取窗口信息,返回窗口数据和事件
        event, values = window.read()
        if event == psg.WIN_CLOSED or event == '退出':
            break
        if event == "人脸采集":
            # 获取编号和姓名
            ygid = values['num']
            name = values['name']
            window['msg'].update(f'编号:{ygid},姓名:{name}')
            face_video(values)  # 传递 values 字典
            # psg.popup('人脸采集成功')
        if event == "打卡":
            # 获取编号和姓名
            # ygid = values['num']
            # name = values['name']
            # window['nsg'].update("正在验证身份信息")
            # window['msg'].update(f'编号:{ygid},姓名:{name}')
            face_gather()
            # psg.popup('打卡成功')
        if event == "选择图片":
            # 调用图片选择功能
            face_tuopen()

    # 关闭窗口,释放资源
    window.close()

1.3、实现人脸信息采集

python 复制代码
import cv2
import PySimpleGUI as psg

from face_gui.face_mysql import add


def face_video(values):
    # 开启摄像头
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    if not cap.isOpened():
        print("摄像头打开失败")
        return

    # 创建摄像头窗口的布局
    camera_layout = [
        [psg.Image(key='video', size=(640, 480))],
        [psg.Button('识别'), psg.Button('关闭摄像头')]
    ]

    # 创建摄像头窗口
    camera_window = psg.Window('信息采集', camera_layout, icon='../images/hq.ico')

    while True:
        # 读取摄像头窗口信息,返回窗口数据和事件
        event, _ = camera_window.read(timeout=10)
        if event == psg.WIN_CLOSED or event == '关闭摄像头':
            break

        # 读取数据帧
        ret, frame = cap.read()
        if ret:
            # 把数据帧转换成btepy数据类型
            imgbytes = cv2.imencode('.png', frame)[1].tobytes()
            camera_window['video'].update(data=imgbytes)

        if event == '识别':
            # 获取编号和姓名
            num = values['num']
            name = values['name']
            iss = cv2.imwrite(f"../face_train_images/{num}.png", frame)
            if iss:
                isadd = add(name, num)
                if isadd:
                    psg.popup('添加成功')
            else:
                psg.popup('添加失败')
            # psg.popup('识别完成')

    # 关闭摄像头窗口,释放资源
    camera_window.close()
    cap.release()

1.4、实现人脸识别

python 复制代码
import os

import cv2
import PySimpleGUI as psg
import face_recognition
import numpy as np

from face_gui.face_mysql import select


def face_gather():
    # 开启摄像头像
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    if not cap.isOpened():
        print("摄像头没有开启")
        return
    # 创建布局
    layout = [
        [psg.Image(key="video")],
        [psg.Button("验证"), psg.Button("关闭")]
    ]
    # 创建窗口
    camera_window = psg.Window("验证", layout)
    # 循环
    while True:
        event, value = camera_window.read(timeout=10)
        # 读取视频
        ret, frame = cap.read()
        if event in (None, "关闭"):
            # 终止循环
            break
        if ret:
            imttype = cv2.imencode(".png", frame)[1].tobytes()
            camera_window["video"].update(imttype)
        if event == "验证":
            # 查找人脸库
            list_dir = os.listdir("../face_train_images")
            if len(list_dir) > 0:
                for i in list_dir:
                    print(i)
                    # 读取一个图片对象
                    img = cv2.imread(f"../face_train_images/{i}")
                    if img is None:
                        print("没有读取图片")
                        break
                    else:
                        # 获取已知图片的特征变量
                        en1 = face_recognition.face_encodings(img)[0]
                        # 获取需要检测图片的特征变量
                        en2 = face_recognition.face_encodings(frame)[0]
                        # 计算欧几里得距离
                        rs = np.linalg.norm(en1 - en2)
                        print(rs)
                        if rs < 0.6:
                            b = i.split(".")[0]
                            select(b)
                            psg.popup("打卡成功")
                            # 查到此人,终止循环
                            break
                        else:
                            psg.popup("人脸库没有此人")
                            break

    cap.release()
    camera_window.close()

1.5、文件上传

python 复制代码
import io
import PySimpleGUI as psg
from PIL import Image


def face_tuopen():
    # 创建layout
    layout = [
        [psg.Text('请选择一张图片或视频:')],
        [psg.Input(key='-FILE-', enable_events=True),
         psg.FileBrowse(
             file_types=(("Image and Video Files", "*.png;*.jpg;*.jpeg;*.gif;*.bmp;*.mp4;*.avi;*.mov;*.mkv"),))],
        [psg.Button('退出')],
        [psg.Image(key='-IMAGE-', size=(640, 480))]
    ]
    # 创建窗口
    window = psg.Window('文件处理', layout, size=(640, 480))
    while True:
        event, values = window.read()
        # 处理事件
        if event in (psg.WINDOW_CLOSED, '退出'):
            break
        elif event == '-FILE-':
            # 更新图片
            image_path = values['-FILE-']
            print(image_path)
            if image_path:
                try:
                    # 使用 Pillow 打开图像
                    image = Image.open(image_path)
                    # 调整图像大小以适应窗口
                    image.thumbnail((640, 480))
                    # 将图像转换为 Tkinter 可以使用的格式
                    bio = io.BytesIO()
                    image.save(bio, format='PNG')
                    window['-IMAGE-'].update(data=bio.getvalue())
                except Exception as e:
                    print(f"Error loading image: {e}")
                    psg.popup_error(f"无法加载图像: {e}")

    window.close()

1.6、数据库操作

python 复制代码
import pymysql


# 新增数据
def add(name, num):
    # 创建数据库连接
    con = pymysql.connect(
        host='localhost',  # 数据库地址
        port=3306,  # 数据库端口
        user='root',  # 用户名
        password='123456',  # 密码
        database='face',  # 数据库名称
        charset='utf8'
    )
    # 创建游标对象,包含了增删改查的函数
    cur = con.cursor()
    # 定义sql
    sql = "insert into user(user_name,user_num) value (%s,%s)"
    # 运行sql(增删改查sql的函数)
    cur.execute(sql, (name, num))
    # 执行增删改sql的函数,返回一个受影响行数的数值
    num = cur.rowcount
    # 提交
    con.commit()
    # 释放资源
    cur.close()
    con.close()
    if num > 0:
        print("新增成功")
        return True
    else:
        print("新增失败")
        return False


# 查询数据
def select(num):
    with pymysql.connect(
            host='localhost',  # 数据库地址
            port=3306,  # 数据库端口
            user='root',  # 用户名
            password='123456',  # 密码
            database='face',  # 数据库名称
            charset='utf8'  # 编码格式
    ) as db:
        with db.cursor() as cursor:
            sql = "select * from user where user_num=%s"
            try:
                cursor.execute(sql, (num,))
                # 获取所有记录列表
                results = cursor.fetchall()
                if results:
                    for row in results:
                        uesr_id = row[0]
                        uesr_name = row[1]
                        uesr_num = row[2]
                        print(f"uesr_id:{uesr_id}, uesr_name:{uesr_name}, uesr_num:{uesr_num}")
                else:
                    print("未找到匹配的记录")
            except Exception as e:
                print(f"Error: {e}")


# 删除数据
def delete(num):
    with pymysql.connect(
            host='localhost',  # 数据库地址
            port=3306,  # 数据库端口
            user='root',  # 用户名
            password='123456',  # 密码
            database='face',  # 数据库名称
            charset='utf8'
    ) as db:
        with db.cursor() as cursor:
            sql = "DELETE FROM user WHERE uesr_num=%s"
            try:
                cursor.execute(sql, (num,))
                # 提交数据
                db.commit()
                print("删除成功")
            except Exception as e:
                print(f"Error: {e}")
                db.rollback()
                print("删除失败")


# 修改数据
def update(name, num, new_name=None, new_num=None):
    with pymysql.connect(
            host='localhost',  # 数据库地址
            port=3306,  # 数据库端口
            user='root',  # 用户名
            password='123456',  # 密码
            database='face',  # 数据库名称
            charset='utf8'
    ) as db:
        with db.cursor() as cursor:
            # 动态生成 SQL 语句
            updates = []
            params = []
            if new_name is not None:
                updates.append("uesr_name=%s")
                params.append(new_name)
            if new_num is not None:
                updates.append("uesr_num=%s")
                params.append(new_num)

            if not updates:
                print("未提供任何更新内容")
                return

            sql = f"UPDATE user SET {', '.join(updates)} WHERE user_name=%s AND user_num=%s"
            params.extend([name, num])

            try:
                cursor.execute(sql, params)
                # 提交数据
                db.commit()
                print("更新成功")
            except Exception as e:
                print(f"Error: {e}")
                db.rollback()
                print("更新失败")

1.7、主函数调用

python 复制代码
from face_gui.face_gui_windows import face_gui

if __name__ == '__main__':
    face_gui()
相关推荐
寒笙LED14 分钟前
C++详细笔记(六)string库
开发语言·c++·笔记
IT书架20 分钟前
golang面试题
开发语言·后端·golang
初遇你时动了情38 分钟前
uniapp 城市选择插件
开发语言·javascript·uni-app
sp_fyf_202441 分钟前
【大语言模型】ACL2024论文-19 SportsMetrics: 融合文本和数值数据以理解大型语言模型中的信息融合
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理
CoderIsArt44 分钟前
基于 BP 神经网络整定的 PID 控制
人工智能·深度学习·神经网络
编程修仙1 小时前
Collections工具类
linux·windows·python
开源社1 小时前
一场开源视角的AI会议即将在南京举办
人工智能·开源
FreeIPCC1 小时前
谈一下开源生态对 AI人工智能大模型的促进作用
大数据·人工智能·机器人·开源
芝麻团坚果1 小时前
对subprocess启动的子进程使用VSCode python debugger
linux·ide·python·subprocess·vscode debugger
机器之心1 小时前
全球十亿级轨迹点驱动,首个轨迹基础大模型来了
人工智能·后端