自学内容网 自学内容网

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

目录

实现思路

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.")
        return

    while True:
        ret, frame = cap.read()
        if not ret:
            messagebox.showerror("Error", "Failed to read frame.")
            break

        gray = 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 = False
            for 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 = True
                    break

            if 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'):
            break

    cap.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")
            return

        password_window.destroy()
        start_face_enrollment()

    Button(password_window, text="Confirm", command=confirm_password).pack()

def start_face_enrollment():
    global cap
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        messagebox.showerror("Error", "Could not open camera.")
        return

    frame_window = Toplevel(root)
    frame_window.title("Face Enrollment")
    frame_window.geometry("600x400")

    Label(frame_window, text="Name").pack()
    global name_entry
    name_entry = Entry(frame_window)
    name_entry.pack()

    Label(frame_window, text="ID").pack()
    global id_entry
    id_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.")
        return

    gray = 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.")
            break
        cv2.imshow("Face Capture", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

def 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.

 


原文地址:https://blog.csdn.net/DDDDWJDDDD/article/details/142495561

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!