CS课程项目设计18:基于Insightface人脸识别库的课堂签到系统
本专栏上一篇文章实现了基于Face_Recognition人脸识别库的课堂签到系统,具体内容如下所示:
CS课程项目设计17:基于Face_Recognition人脸识别库的课堂签到系统-CSDN博客https://blog.csdn.net/weixin_36431280/article/details/151045242?spm=1001.2014.3001.5501这篇文章继续按照人脸识别库的发展脉络,实现基于Insightface人脸识别库的课堂签到系统。
1. 研究背景
随着计算机视觉技术的快速发展,人脸识别技术在身份验证、门禁管理、考勤签到等领域得到了广泛应用。在教育场景中,传统课堂签到方式(如点名、签到表)存在效率低下、易代签等问题,难以满足规模化教学管理的需求。
近年来,基于深度学习的人脸识别算法精度显著提升,为自动化签到系统提供了技术支撑。InsightFace 作为一款开源的深度学习人脸识别工具库,凭借其高效的推理速度和优异的识别精度,成为构建轻量化人脸识别应用的理想选择。在此背景下,开发基于 InsightFace 的课堂人脸签到系统,能够有效提升签到效率,减少人工干预,实现课堂考勤的智能化管理。
2. 研究目的
本系统旨在通过整合人脸识别与数据库技术,构建一套适用于课堂场景的智能化签到解决方案,具体实现目标如下:
2.1 签到效率提升
实现从摄像头启动到完成 50 人班级签到的全流程耗时≤3 分钟,较传统点名方式效率提升 70% 以上。系统支持多学生同时识别(单帧最多可识别 8 张人脸),适应课堂密集人群场景。
2.2 身份验证精准性
通过 InsightFace 的特征提取能力,将误识率(FAR)控制在 0.1% 以下,拒识率(FRR)≤1%。针对课堂常见的光照变化(如靠窗座位逆光)、姿态偏移(低头、侧头)等干扰因素,通过模型优化确保识别稳定性。
2.3 全流程自动化管理
实现 "学生信息录入→人脸采集→实时签到→数据统计→记录查询" 的全流程自动化。例如:教师添加新学生时,系统自动采集人脸图像并生成特征向量;签到结束后,自动生成 Excel 格式的出勤报表,包含学生姓名、学号、签到时间、缺勤标记等字段。
2.4 灵活的学生信息管理
支持批量导入学生信息(通过 CSV 文件),并提供单条信息的增删改功能。例如:转学生加入时,教师可通过 "添加学生" 功能拍摄人脸照片,系统自动关联学号并更新特征库;学生毕业时,删除操作可同步清理人脸图像文件与数据库记录。
2.5 可视化数据统计与追溯
实时展示签到进度(如 "50 人班级,已签到 38 人,未到 12 人"),并以列表形式区分实到 / 未到学生。历史记录支持按日期、班级筛选,教师可查询某学生的月度出勤趋势(如 "张三 3 月出勤率 85%"),数据留存时间≥1 年。
2.6 轻量化部署与易用性
无需 GPU 支持,可在普通教学电脑(i5 处理器 + 8G 内存)上稳定运行,安装包体积≤200MB。UI 界面采用向导式设计,教师通过 "开始签到"" 结束签到 " 两个核心按钮即可完成主要操作,学习成本≤10 分钟。
3. 技术方案
3.1 核心技术栈
(1) InsightFace
- 功能:提供端到端的人脸识别能力,包含人脸检测、关键点定位、特征提取三大模块。
- 优势:支持多模型选择(如
buffalo_l
高精度模型适合实验室场景,buffalo_s
轻量模型适合低配置设备),内置 CPU 推理优化(通过 ONNX Runtime 加速),单张人脸特征提取耗时≤100ms。 - 系统应用:在
get_face_encoding
方法中调用self.app.get()
实现从图像到特征向量的转换,通过face.embedding
获取 512 维特征。
(2) OpenCV (cv2)
负责视频帧捕获、图像格式转换、人脸框绘制等底层计算机视觉操作。
- 通过
cv2.VideoCapture(0)
调用本地摄像头,支持 640×480 分辨率实时采集; - 使用
cv2.cvtColor
实现 BGR(摄像头默认格式)与 RGB(InsightFace 输入格式)的转换; - 通过
cv2.rectangle
和cv2.putText
在视频帧上绘制人脸边界框与识别结果。
(3) SQLite3
轻量级嵌入式数据库,无需独立服务器进程即可运行,适合存储中小规模签到数据:
students
表:存储学生基础信息(自增 ID、姓名、唯一学号、人脸图片路径),通过student_id
建立唯一索引确保数据唯一性attendance
表:记录签到详情(自增 ID、关联学号、日期、时间、状态),通过外键关联students
表实现数据完整性约束- 支持事务操作(如添加学生时同步写入人脸路径和基础信息),确保数据一致性
3.2 InsightFace核心运行机制
InsightFace 的人脸识别流程基于深度学习模型的流水线处理,核心机制分为三个阶段:
(1) 人脸检测
- 模型:默认使用 RetinaFace 检测器,基于单阶段目标检测框架,支持多尺度人脸检测(最小可检测 64×64 像素人脸)。
- 过程:输入 RGB 图像后,模型通过特征金字塔网络(FPN)生成不同尺度的特征图,预测人脸边界框(bbox)、置信度(det_score)和 5 个关键点(左眼、右眼、鼻尖、左嘴角、右嘴角)。
- 系统应用:在
process_face_recognition
中过滤置信度低于阈值(默认 0.5)的检测结果,确保仅处理高质量人脸区域。
核心代码如下所示:
# 初始化InsightFace
self.face_app = self.init_insightface()
self.app = self.face_app # 添加这个属性,解决add_student和update_student中使用self.app的问题# 使用InsightFace检测人脸和提取特征
faces = self.face_app.get(frame)
(2) 人脸预处理与对齐
- 预处理:对检测到的人脸区域进行裁剪,统一调整为 112×112 像素,并进行亮度归一化(消除光照影响)。
- 对齐:基于检测到的 5 个关键点,通过仿射变换将人脸校正为标准姿态(双眼水平、鼻尖居中),确保不同姿态的同一人脸特征一致性。
- 系统隐藏逻辑:InsightFace 的
FaceAnalysis
类在get()
方法中自动完成对齐,无需额外编码实现。
核心代码如下所示:
# 获取人脸位置
bbox = face.bbox.astype(int)
x1, y1, x2, y2 = bbox[0], bbox[1], bbox[2], bbox[3]def get_face_encoding(self, img):"""提取人脸特征编码"""if self.face_app is None:return None# 使用InsightFace检测并提取特征faces = self.face_app.get(img)if faces:return faces[0].embedding # 返回第一个检测到的人脸的特征向量return None
(3) 特征提取与匹配
- 特征提取:使用基于 ArcFace 损失函数训练的 ResNet-50 骨干网络,将对齐后的人脸图像映射为 512 维的特征向量(embedding)。该向量具有判别性:同一人不同姿态的向量距离小,不同人向量距离大。
- 特征匹配:通过计算待识别人脸向量与已知人脸库向量的欧氏距离(阈值默认 1.0),距离小于阈值则判定为同一人。
- 系统实现:在
process_face_recognition
中遍历known_face_encodings
,找到最小距离对应的学生信息,完成身份识别。
核心代码如下所示:
# 获取人脸特征
encoding = face.embedding# 与已知人脸比较
name = "未知人员"
student_id = ""
min_distance = float('inf')
threshold = self.threshold_var.get()if self.known_face_encodings:# 计算与所有已知人脸的距离for i, known_encoding in enumerate(self.known_face_encodings):# 计算余弦距离distance = 1 - np.dot(encoding, known_encoding)if distance < min_distance and distance < threshold:min_distance = distancename = self.known_face_names[i]student_id = self.known_face_ids[i]
以上代码对应开始签到的功能,可视化页面如下所示:
左图是签到成功的页面,右图是签到失败的页面。
签到完成后,点击结束签到,回到系统主页面,会发现出勤统计情况也会更新了,可视化页面如下所示:
4. 实现流程
4.1 系统初始化
- 启动时初始化 InsightFace 分析器(
self.app = FaceAnalysis(providers=['CPUExecutionProvider'])
),配置为 CPU 推理模式并设置检测尺寸为 640×640。 - 调用
init_database
创建 SQLite 数据库及两张核心表,通过PRAGMA foreign_keys = ON
开启外键约束,确保数据一致性。 - 执行
load_known_faces
加载人脸特征:优先读取insightface_encodings.pkl
文件,若文件不存在则从数据库读取学生图像路径,逐一提取特征并序列化保存。
其中,初始化FaceAnalysis时,还可以选择不同的模型: buffalo_l, buffalo_s等
def init_insightface(self):"""初始化InsightFace模型"""try:# 初始化FaceAnalysisapp = FaceAnalysis(name='buffalo_l') # 可以选择不同的模型: buffalo_l, buffalo_s等app.prepare(ctx_id=0, det_size=(640, 640)) # ctx_id=0表示使用CPU,-1表示自动选择return appexcept Exception as e:messagebox.showerror("模型加载错误",f"无法初始化InsightFace模型: {str(e)}\n请确保已安装正确版本的insightface")self.root.after(100, self.root.quit)return None
4.2 UI 界面构建阶段
- 采用 "左视频、右控制" 的布局:左侧 640×480 区域实时显示摄像头画面及识别结果,右侧分为参数设置(置信度阈值调节)、控制按钮(签到启停)、学生管理(增删改查)、统计展示(实到 / 未到人数)四个功能区。
- 通过
matplotlib.rcParams
配置中文字体,确保cv2.putText
和 Tkinter 标签的中文正常显示。
4.3 签到执行阶段
- 点击 "开始签到" 后,系统启动摄像头(
cv2.VideoCapture(0)
),清空历史签到记录,初始化统计数据。 - 视频处理采用双线程机制:主线程通过
process_video
读取帧并更新 UI,子线程通过process_face_recognition
异步执行人脸识别。 - 识别流程:对每帧图像检测人脸→提取特征→与已知库匹配→绘制人脸框与姓名→对新识别学生记录签到时间(写入
attendance
表)→实时更新签到列表与统计数据。
4.4 学生管理阶段
- 添加学生:通过弹窗输入姓名和学号,调用摄像头拍摄人脸,检测到清晰人脸(置信度≥0.8)后保存图像至
face_images
目录,同步写入students
表,并删除特征缓存文件触发重新加载。 - 更新 / 删除学生:通过学号查询信息,支持修改姓名或重新拍摄人脸(更新操作),或彻底删除数据库记录与关联图像文件(删除操作),均同步更新特征库。
添加学生的核心代码如下所示:
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# 检测人脸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.5 数据持久化阶段
- 学生信息与签到记录以 SQLite 数据库文件(
attendance_insightface.db
)形式存储,支持离线访问。 - 人脸特征向量通过 Pickle 序列化,避免每次启动时重复提取,提升系统响应速度。
所有人签到完之后,还可以点击查看记录,进一步查看每个人的签到情况,可视化界面如下图所示:
5. 总结
基于 InsightFace 的课堂人脸签到系统通过整合高精度人脸识别技术与轻量化部署方案,有效解决了传统签到方式的效率低、易作弊、统计繁琐等问题。系统的核心价值体现在:
- 技术适配性:针对课堂场景优化 InsightFace 的参数配置(如调整距离阈值至 1.0),在保证识别精度的同时,实现普通 PC 上的实时运行。
- 操作便捷性:通过简洁的 UI 设计和自动化流程,降低教师使用门槛,无需专业技术背景即可快速上手。
- 数据可靠性:结合数据库与文件存储,确保学生信息与签到记录的完整留存,支持多维度查询与统计分析。
该系统不仅为课堂考勤提供了高效解决方案,其技术框架也可扩展至图书馆入馆登记、实验室门禁等教育场景,具有较强的实用价值与推广意义。
最后,还上传个该项目的简要演示视频,供大家了解。
基于InsightFace人脸识别库的课堂签到系统