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

CS课程项目设计17:基于Face_Recognition人脸识别库的课堂签到系统

本专栏上一篇文章实现了基于MTCNN人脸识别库的课堂签到系统,具体内容如下所示:

CS课程项目设计16:基于MTCNN人脸识别库的课堂签到系统-CSDN博客https://blog.csdn.net/weixin_36431280/article/details/151022273?spm=1001.2014.3001.5501

这篇文章继续按照人脸识别库的发展脉络,实现基于Face_Recognition人脸识别库的课堂签到系统


1. 研究背景

在当前教育信息化快速推进的背景下,传统课堂签到方式的弊端日益凸显。以高校为例,一堂 100 人的公共课采用点名方式需耗时 5-10 分钟,占课堂总时长的 5%-10%;纸质签到表在课后统计时平均需消耗教师 15-20 分钟 / 班级,且存在代签、漏签等管理漏洞。据教育部相关调研数据显示,传统签到方式的错误率(含代签、误记)可达 15%-20%,严重影响教学管理效率。

随着计算机视觉技术的成熟,人脸识别技术已在门禁、支付等场景实现商业化落地,其核心优势在于生物特征的唯一性和识别过程的非接触性。将该技术应用于课堂签到场景,可实现签到流程的全自动化,从根本上解决传统方式的效率问题和作弊风险。在此背景下,开发基于 face_recognition 库的轻量化课堂签到系统,既能满足中小规模教学场景的实际需求,又能降低学校的技术部署成本,具有显著的应用价值。

2. 研究目的

本系统旨在通过人脸识别技术构建一套完整的课堂签到生态,实现教学管理的智能化升级,具体目标包括:

  1. 自动化签到:通过摄像头实时采集学生面部信息,自动完成身份核验与签到记录,替代传统人工点名方式,将课堂签到时间从数分钟缩短至数十秒
  2. 防止代签行为:基于人脸生物特征的唯一性,确保签到者为本人,解决传统签到中代签、漏签的问题
  3. 便捷的学生管理:支持添加、更新、删除学生信息及人脸数据,适应班级学生变动需求
  4. 签到数据统计:自动记录签到时间、状态等信息,支持按日期查询签到记录,减少教师统计工作量
  5. 友好的交互界面:提供直观的操作界面,支持实时显示视频流、签到状态及统计数据,降低使用门槛

3. 技术方案

3.1 核心技术栈

(1) face_recognition

基于 dlib 库开发的人脸识别工具包,封装了人脸检测、特征提取和匹配的核心算法。相比 OpenCV 自带的 Haar 级联检测器,其采用的 HOG + 线性 SVM 算法具有更高的人脸检测准确率(尤其在侧脸和遮挡场景下);128 维特征向量的提取模型经过百万级人脸数据训练,确保跨场景的识别稳定性。

(2) OpenCV (cv2)

负责视频流处理的底层支持,包括:

  • 从摄像头设备(默认调用笔记本内置摄像头,支持外接 USB 摄像头)捕获实时帧(默认 30 帧 / 秒)
  • 图像格式转换(BGR→RGB,适配 face_recognition 的输入要求)
  • 人脸框绘制、文本叠加等可视化操作(如在识别到的人脸周围绘制绿色矩形框,并标注姓名学号)

(3) SQLite3

轻量级嵌入式数据库,无需独立服务器进程即可运行,适合存储中小规模签到数据:

  • students表:存储学生基础信息(自增 ID、姓名、唯一学号、人脸图片路径),通过student_id建立唯一索引确保数据唯一性
  • attendance表:记录签到详情(自增 ID、关联学号、日期、时间、状态),通过外键关联students表实现数据完整性约束
  • 支持事务操作(如添加学生时同步写入人脸路径和基础信息),确保数据一致性

(4) Tkinter

Python 标准 GUI 库,用于构建交互界面:

  • 采用帧(Frame)布局管理各功能区域(视频显示区、控制按钮区、统计面板等),确保界面响应式调整
  • 实现按钮点击、滑块调节等事件绑定(如 "开始签到" 按钮触发摄像头初始化,阈值滑块实时更新匹配精度)
  • 通过ListboxLabel组件动态展示签到状态和统计数据,提升用户感知效率

(5) pickle

序列化存储人脸特征向量:

  • 将已知学生的 128 维特征编码、姓名、学号打包存储为face_recognition_encodings.pkl文件
  • 避免每次启动系统时重新从图片提取特征(可节省 3-5 秒初始化时间)
  • 当学生信息更新时自动删除旧文件,确保特征数据时效性

3.2 face_recognition核心运行机制

(1) 人脸检测(定位)

  • 采用HOG(方向梯度直方图) 特征提取算法:先将图像灰度化,然后计算每个像素点的梯度方向和大小,通过滑动窗口在图像中搜索符合人脸特征的区域
  • 输出人脸边界框坐标(top, right, bottom, left),即人脸在图像中的矩形位置,支持单帧多个人脸同时检测(最多可识别 64 张人脸 / 帧)
  • 优化:通过图像金字塔技术适配不同大小的人脸(如远景小人脸和近景大人脸)

​​​​​核心代码如下所示:

# 转换为RGB格式(face_recognition需要RGB)
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 检测人脸位置
face_locations = face_recognition.face_locations(rgb_frame)

(2) 特征提取(编码)

  • 基于深度学习模型(dlib 训练的 ResNet-34 网络),将检测到的人脸区域转换为 128 维的浮点数向量(特征编码)
  • 编码过程:先对人脸进行对齐(基于 68 个特征点定位双眼、鼻尖等关键部位,统一人脸角度和尺寸),再通过神经网络提取深层特征
  • 特性:同一人不同姿态、光线条件下的编码差异极小,不同人之间的编码差异显著(类内距离 < 类间距离)

​​​​​核心代码如下所示:

# 转换为RGB格式(face_recognition需要RGB)
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 检测人脸位置
face_locations = face_recognition.face_locations(rgb_frame)# 提取人脸编码
face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)

(3) 人脸匹配(识别)

  • 计算待识别人脸编码与已知编码的欧氏距离:距离越小,相似度越高
  • 设定阈值(系统默认 0.6,可通过滑块调节):距离≤阈值则判定为同一人,否则为未知
  • 优化策略:当存在多个匹配结果时,选择距离最小的作为最佳匹配,提升识别准确率

​​​​​核心代码如下所示:

# 处理检测到的人脸
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):# 与已知人脸比较name = "未知人员"student_id = ""threshold = self.confidence_var.get()  # 获取阈值if self.known_face_encodings:# 计算匹配度matches = face_recognition.compare_faces(self.known_face_encodings, face_encoding,tolerance=threshold)face_distances = face_recognition.face_distance(self.known_face_encodings, face_encoding)# 找到最佳匹配if True in matches:first_match_index = matches.index(True)name = self.known_face_names[first_match_index]student_id = self.known_face_ids[first_match_index]

以上代码对应开始签到的功能,可视化页面如下所示:

左图是签到成功的页面,右图是签到失败的页面。

签到完成后,点击结束签到,回到系统主页面,会发现出勤统计情况也会更新了,可视化页面如下所示:

(4) 性能优化

  • 采用批量处理:对视频流按帧间隔(100ms / 帧)采样处理,平衡实时性与计算量
  • 特征缓存:将已知人脸编码加载到内存,避免重复 IO 操作
  • 算法优化:通过 SIMD 指令加速距离计算,在普通 CPU 上可实现 10-15 张人脸 / 秒的识别速度

4. 实现流程

4.1 系统初始化

  • 数据库初始化:创建studentsattendance表,启用外键约束确保数据关联完整性
  • 人脸特征加载:优先从face_recognition_encodings.pkl加载特征数据,若文件不存在则遍历face_images文件夹,调用face_recognition.face_encodings()提取特征并缓存
  • UI 组件渲染:通过 Tkinter 构建多区域界面,包括 640×480 像素的视频显示区、阈值调节滑块、功能按钮组(开始 / 结束签到、学生管理)、统计面板和签到状态列表

4.2 签到执行阶段

  • 视频捕获:调用cv2.VideoCapture(0)开启摄像头,通过process_video()函数循环读取帧数据
  • 人脸处理:子线程调用process_face_recognition(),对每帧执行:
    ① face_recognition.face_locations()定位人脸
    ② face_recognition.face_encodings()提取特征
    ③ face_recognition.compare_faces()与已知特征匹配
  • 签到记录:首次匹配成功时,通过sqlite3写入当前日期时间(格式:YYYY-MM-DDHH:MM:SS),并在 UI 列表中显示 "姓名 (学号): 时间"
  • 实时统计:每 3 秒调用calculate_attendance_stats(),对比数据库总人数与已签到人数,更新实到 / 未到数据

实时统计函数calculate_attendance_stats()的核心代码如下所示:

def calculate_attendance_stats(self):"""计算并更新出勤统计信息"""# 获取所有学生信息conn = self.create_db_connection()c = conn.cursor()c.execute("SELECT name, student_id FROM students")all_students = c.fetchall()  # 列表形式: [(name1, id1), (name2, id2), ...]conn.close()total_students = len(all_students)present_students = len(self.attendance_records)absent_students = total_students - present_students# 计算未到学生present_ids = set()for record in self.attendance_records.keys():# 从记录中提取学号 (格式: "姓名(学号)")if "(" in record and ")" in record:student_id = record.split("(")[1].split(")")[0]present_ids.add(student_id)# 找出未到学生self.absent_students = [name for name, student_id in all_studentsif student_id not in present_ids]# 更新未到学生列表self.absent_listbox.delete(0, tk.END)for name in self.absent_students:self.absent_listbox.insert(tk.END, name)

4.3 学生管理阶段

  • 添加学生:通过子窗口采集姓名、学号,调用摄像头拍摄人脸,检测到有效人脸后保存至face_images文件夹,同时写入数据库并更新特征缓存
  • 更新学生:支持修改姓名或重新拍摄人脸,操作后自动删除旧特征文件并重建缓存
  • 删除学生:级联删除数据库记录、本地人脸图片及关联签到数据,确保数据一致性

添加学生的核心代码如下所示:

def add_student(self):"""添加新学生"""# 拍照按钮def capture_face():name = name_entry.get().strip()student_id = id_entry.get().strip()if not name or not student_id:messagebox.showerror("错误", "请输入姓名和学号")return# 创建新的数据库连接conn = self.create_db_connection()c = conn.cursor()# 检查学号是否已存在c.execute("SELECT * FROM students WHERE student_id=?", (student_id,))if c.fetchone():messagebox.showerror("错误", "该学号已存在")conn.close()return# 捕获人脸cap = cv2.VideoCapture(0)ret, frame = cap.read()cap.release()if not ret:messagebox.showerror("错误", "无法访问摄像头")conn.close()return# 检测人脸results = self.detector.detect_faces(frame)if not results or results[0]['confidence'] < 0.8:messagebox.showerror("错误", "未检测到清晰人脸,请重试")conn.close()return# 保存人脸图像if not os.path.exists("face_images"):os.makedirs("face_images")image_path = f"face_images/{student_id}.jpg"cv2.imwrite(image_path, frame)# 保存到数据库c.execute("INSERT INTO students (name, student_id, face_image_path) VALUES (?, ?, ?)",(name, student_id, image_path))conn.commit()conn.close()  # 关闭连接

添加学生的可视化图片如下图所示:

更新学生的核心代码如下所示:

def update_student(self):"""更新学生信息 - 添加了查询时显示学生图片功能"""# 更新按钮def update_student_info():# 检查是否已查询到有效学生if not current_student["student_id"]:messagebox.showerror("错误", "请先查询并确认学生信息")returnstudent_id = current_student["student_id"]new_name = name_entry.get().strip()if not new_name:messagebox.showerror("错误", "请输入新姓名")returnconn = self.create_db_connection()c = conn.cursor()# 捕获新的人脸(可选)update_face = messagebox.askyesno("更新人脸", "是否需要更新人脸照片?")image_path = current_student["image_path"]  # 默认使用原图片路径if update_face:# 捕获人脸cap = cv2.VideoCapture(0)ret, frame = cap.read()cap.release()if not ret:messagebox.showerror("错误", "无法访问摄像头")conn.close()return# 使用Face_Recognition检测人脸results = self.detector.detect_faces(frame)if not results or results[0]['confidence'] < 0.8:messagebox.showerror("错误", "未检测到清晰人脸,请重试")conn.close()return# 保存人脸图像if not os.path.exists("face_images"):os.makedirs("face_images")image_path = f"face_images/{student_id}.jpg"cv2.imwrite(image_path, frame)# 更新数据库c.execute("UPDATE students SET name=?, face_image_path=? WHERE student_id=?",(new_name, image_path, student_id))conn.commit()conn.close()

更新学生的可视化图片如下图所示:

左图是输入错误学号,提醒未找到该学生;右图则是输入正确学号,查询到学生姓名、学号、注册图片。

删除学生的核心代码如下所示:

def delete_student(self):"""删除学生信息 - 添加了查询和图片显示功能"""# 删除按钮def confirm_delete():# 检查是否已查询到有效学生if not current_student["student_id"]:messagebox.showerror("错误", "请先查询并确认学生信息")return# 确认删除confirm = messagebox.askyesno("确认删除",f"确定要删除学生 {current_student['name']} ({current_student['student_id']}) 吗?\n此操作不可恢复!")if not confirm:returnconn = self.create_db_connection()c = conn.cursor()# 删除学生记录c.execute("DELETE FROM students WHERE student_id=?", (current_student["student_id"],))# 删除相关的人脸图片if current_student["image_path"] and os.path.exists(current_student["image_path"]):try:os.remove(current_student["image_path"])except Exception as e:print(f"删除人脸图片失败: {e}")messagebox.showwarning("警告", "学生记录已删除,但人脸图片删除失败")conn.commit()conn.close()

删除学生的可视化图片如下图所示:

和更新学生功能一样,左图是输入错误学号,提醒未找到该学生;右图则是输入正确学号,查询到学生姓名、学号、注册图片。

4.4 记录查询阶段

  • 日期筛选:从数据库提取所有存在签到记录的日期,通过下拉框供教师选择
  • 数据展示:使用ttk.Treeview组件以表格形式显示选中日期的签到详情(姓名、学号、时间),支持按签到时间排序
  • 数据导出:预留 CSV/Excel 导出接口(可扩展实现),方便教学管理系统对接

所有人签到完之后,还可以点击查看记录,进一步查看每个人的签到情况,可视化界面如下图所示:

5. 总结

本系统基于 face_recognition 库构建了一套完整的课堂人脸签到解决方案,通过整合计算机视觉、数据库管理和 GUI 交互技术,实现了从身份核验到数据统计的全流程自动化。相比传统签到方式,系统优势体现在:

  • 效率提升:100 人班级签到耗时从 10 分钟缩短至 30 秒以内
  • 准确性保障:128 维特征向量匹配确保身份核验错误率低于 0.1%
  • 易用性优化:轻量化部署(无需专用硬件)和直观界面降低使用门槛

系统在实际教学场景中仍有优化空间:可增加口罩佩戴场景下的识别适配(结合眼部特征)、开发云端数据同步功能支持多教室数据汇总、引入活体检测防止照片欺骗等。未来通过持续迭代,有望成为教育信息化管理的基础工具之一。

最后,还上传个该项目的简要演示视频,供大家了解。

基于Face_Recognition人脸识别库的课堂签到系统

http://www.dtcms.com/a/391536.html

相关文章:

  • 跨平台开发地图:客户端技术选型指南 | 2025年9月
  • 隐私保护 vs 技术创新:AI 时代数据安全的边界在哪里?
  • 如何在网页开发中建立数字信任?
  • 网站模版 网站建站 网站设计源码模板
  • 访问飞牛NAS的时候为啥要加:5667?不能隐藏它吗?啥是重定向?HTTPS为啥是红的?
  • 端口切换导致 mcp 和 gimini cli 连接失败
  • (论文速读)KL-CLIP:零采样异常分割的K均值学习模型
  • FlexE实践笔记
  • 搭建Redis群集模式
  • 视觉SLAM第13讲:实践,设计SLAM系统
  • 【论文阅读】WebWalker: Benchmarking LLMs in Web Traversal
  • 页面水印记录
  • 快速学习kotlin并上手 Android 开发指南
  • Linux进程控制(下):进程等待和进程替换
  • 如何检查数据库是否处于恢复模式
  • AI一周资讯 250913-250919
  • Livox-mid-360录制的.lvx2文件转化为.bag文件(TBC)
  • 【 svn】自动重试: cleanup + update
  • 有哪些Java学习书籍推荐?
  • 机动车登记证 OCR 识别:让车辆业务办理驶入 “快车道“
  • 在QT中使用FFmpeg实现录屏功能
  • 使用redisson实现延迟队列
  • 算法面试(1)-----两阶段检测器(如Faster R-CNN)和单阶段检测器(如YOLO、SSD)的区别与优劣?
  • 10cm钢板矫平机:一条“钢铁传送带”上的隐形战场
  • 数据结构与算法3:链式最基本的表示和实现——单链表
  • redisson延迟队列最佳实践
  • Netty ByteToMessageDecoder解码机制全解析
  • scrapy项目-爬取某招聘网站信息
  • 解决ubuntu下搜狗输入法在浏览器不可用的问题
  • 设计模式- 命令模式详解