当前位置: 首页 > news >正文

打卡软件——人脸识别综合实现

目录

实现思路

1. 导入所需库

2. 加载人脸检测模型

3. 初始化存储结构

4. 特征提取函数

5. 打卡功能

6. 人脸录入功能

7. 开始人脸录入

8. 捕捉人脸

9. 显示摄像头画面

10. 数据保存

11. 主页面设置

12. 创建主窗口

整体代码

实现效果

结语


实现思路

这段代码实现了一个简单的人脸识别系统,主要分为人脸录入和打卡两大功能。以下是代码的详细实现思路:

1. 导入所需库

  • cv2:用于图像处理,提供视频捕捉和图像操作功能。
  • dlib:用于人脸检测和特征点提取。
  • numpy:用于数组操作,方便进行数学计算。
  • pickle:用于保存和加载人脸数据。
  • tkinter:用于创建用户界面,包括窗口和按钮。
  • scipy.spatial.distance:用于计算余弦相似度,帮助判断人脸是否匹配。

2. 加载人脸检测模型

  • predictor_path:指定特征点检测模型的路径。
  • detector:使用dlib的正面人脸检测器。
  • predictor:加载68个特征点的人脸标记预测器。

3. 初始化存储结构

  • face_data:使用字典存储录入的人脸信息,包括姓名、ID和提取的特征。

4. 特征提取函数

  • extract_face_features:接收人脸区域和灰度图像,使用predictor提取68个特征点的坐标,并将其转换为一维数组返回。该特征用于后续的人脸匹配。

5. 打卡功能

  • check_in
    • 使用cv2.VideoCapture(0)打开摄像头。
    • 进入一个循环,不断读取视频帧。
    • 将帧转换为灰度图像,并检测人脸。
    • 对每个检测到的人脸,提取其特征并用矩形框标记。
    • 遍历存储的人脸数据,计算每个人脸特征与存储特征的余弦相似度,判断是否匹配。
    • 若匹配,显示姓名和ID;否则,显示“未识别”。
    • 按下“q”键退出循环,释放摄像头并关闭窗口。

6. 人脸录入功能

  • enroll_face
    • 创建一个新窗口,要求用户输入密码。
    • 确认密码正确后,调用start_face_enrollment函数开始录入人脸。

7. 开始人脸录入

  • start_face_enrollment
    • 再次打开摄像头,并创建录入窗口,要求用户输入姓名和ID。
    • 提供“捕捉人脸”按钮,点击后调用capture_face函数。

8. 捕捉人脸

  • capture_face
    • 读取摄像头帧并进行人脸检测。
    • 若检测到人脸,提取特征并存储至face_data字典中,使用姓名和ID作为键,特征作为值。
    • 提示用户录入成功并保存数据。
    • 释放摄像头,关闭窗口并返回主页面。

9. 显示摄像头画面

  • show_camera
    • 持续读取摄像头帧,显示实时画面。
    • 按下“q”键退出显示。

10. 数据保存

  • save_data
    • 使用pickle将face_data字典保存到本地文件face_data.pkl,方便下次加载。

11. 主页面设置

  • main_page
    • 清空当前窗口,设置主窗口的尺寸和标题。
    • 提供“录入人脸”和“打卡”按钮,分别调用相应功能。

12. 创建主窗口

  • 使用Tk()创建主窗口,并设置标题和初始大小。
  • 通过调用main_page()初始化界面并进入主循环。

整体代码

import cv2
import dlib
import numpy as np
import pickle
from tkinter import *
from tkinter import messagebox
from scipy.spatial.distance import cosine# 加载人脸特征点检测模型
predictor_path = "./model/shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)# 存储人脸信息的字典
face_data = {}# 提取特征函数
def extract_face_features(face, gray_image):landmarks = predictor(gray_image, face)features = np.array([landmarks.part(i).x for i in range(68)] + [landmarks.part(i).y for i in range(68)])return features# 打卡功能
def check_in():cap = cv2.VideoCapture(0)if not cap.isOpened():messagebox.showerror("Error", "Could not open camera.")returnwhile True:ret, frame = cap.read()if not ret:messagebox.showerror("Error", "Failed to read frame.")breakgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = detector(gray)for face in faces:x = face.left()y = face.top()cv2.rectangle(frame, (x, y), (face.right(), face.bottom()), (0, 255, 0), 2)face_features = extract_face_features(face, gray)recognized = Falsefor stored_face_id, data in face_data.items():stored_features = data['features']if cosine(stored_features, face_features) < 0.5:  # 使用余弦相似度,阈值可调cv2.putText(frame, f"Name: {data['name']}, ID: {data['id']}", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)recognized = Truebreakif not recognized:cv2.putText(frame, "Not recognized", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)cv2.imshow("Check In", frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()cv2.destroyAllWindows()# 录入人脸功能
def enroll_face():password_window = Toplevel(root)password_window.title("Enter Password")password_window.geometry("300x150")Label(password_window, text="Password").pack()password_entry = Entry(password_window, show='*')password_entry.pack()def confirm_password():if password_entry.get() != "2004":messagebox.showerror("Error", "Incorrect password")returnpassword_window.destroy()start_face_enrollment()Button(password_window, text="Confirm", command=confirm_password).pack()def start_face_enrollment():global capcap = cv2.VideoCapture(0)if not cap.isOpened():messagebox.showerror("Error", "Could not open camera.")returnframe_window = Toplevel(root)frame_window.title("Face Enrollment")frame_window.geometry("600x400")Label(frame_window, text="Name").pack()global name_entryname_entry = Entry(frame_window)name_entry.pack()Label(frame_window, text="ID").pack()global id_entryid_entry = Entry(frame_window)id_entry.pack()Button(frame_window, text="Capture Face", command=lambda: capture_face(frame_window)).pack()# 显示摄像头画面show_camera()def capture_face(frame_window):ret, frame = cap.read()if not ret:messagebox.showerror("Error", "Failed to read frame.")returngray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = detector(gray)if len(faces) > 0:face = faces[0]x = face.left()y = face.top()# 提取特征并存储人脸信息features = extract_face_features(face, gray)name = name_entry.get()person_id = id_entry.get()# 确保不覆盖现有信息face_data[f"{name}_{person_id}"] = {'name': name, 'id': person_id, 'features': features}messagebox.showinfo("Success", "Face enrolled successfully!")save_data()cap.release()cv2.destroyAllWindows()main_page()else:messagebox.showerror("Error", "No face detected")def show_camera():while True:ret, frame = cap.read()if not ret:messagebox.showerror("Error", "Failed to read frame.")breakcv2.imshow("Face Capture", frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakdef save_data():with open('face_data.pkl', 'wb') as f:pickle.dump(face_data, f)def main_page():for widget in root.winfo_children():widget.destroy()root.geometry("300x200")Label(root, text="Face Recognition System").pack()Button(root, text="Enroll Face", command=enroll_face).pack()Button(root, text="Check In", command=check_in).pack()# 创建主窗口
root = Tk()
root.title("Face Recognition System")
root.geometry("300x200")main_page()
root.mainloop()

实现效果

 

结语

        整段代码通过Tkinter提供的GUI实现了人脸的录入和识别功能,结合dlib的人脸检测和特征提取能力,构成了一个基本的人脸识别系统。用户可以通过简单的操作进行人脸的录入和打卡,系统将根据录入的信息进行识别。

        但是说实话还是有很多的BUG和设计缺陷,我会继续的修改,所以在不久的时间内我会更新人脸识别打卡系统2.0.

 


http://www.mrgr.cn/news/35226.html

相关文章:

  • Thinkphp6视图介绍
  • 生成式GPT商品推荐:精准满足用户需求
  • uniapp如何i18n国际化
  • 【计算机网络】设备网卡NIC的工作内容有哪些呢?
  • 实习冲刺练习 第二十二天
  • Python 占位语句 pass
  • Python NumPy学习指南:从入门到精通
  • 应用层 III(电子邮件)【★★】
  • Vue(16)——Vue3.3新特性
  • 最小花费爬楼梯(动态规划)问题
  • 工业一体机实现接口与模块选配
  • 【后端开发】JavaEE初阶—线程安全问题与加锁原理(超详解)
  • 3270.求出数字答案题解
  • Winform—事件多播和事件联机响应
  • 【Python百日进阶-Web开发-FastAPI】Day805 - FastAPI的请求体
  • golang学习笔记14-函数(三):系统函数
  • Python语句: For 循环的详细讲解
  • CCIE证书有用吗?CCIE含金量解读!
  • js实现多行文本控件textarea,根据文本内容自适应窗口全部显示
  • C++ SLT标准模板简介
  • iframe和父页面使用message通信,支持跨域
  • 负载均衡--TLS安全策略(四)
  • Java反射机制入门:解锁运行时类信息的秘密
  • 【解决虚拟机NAT联网】收藏这份教程就不用再辛苦找了
  • Avalonia的第三方UI库Material.Avalonia详细教程
  • Dify部署及初步测试