打卡软件——人脸识别综合实现
目录
实现思路
这段代码实现了一个简单的人脸识别系统,主要分为人脸录入和打卡两大功能。以下是代码的详细实现思路:
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
,方便下次加载。
- 使用pickle将
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)!