基于深度学习的人脸识别签到系统:Flask+SQLite完整Web方案

发布时间:2026/10/10 13:21:40
基于深度学习的人脸识别签到系统:Flask+SQLite完整Web方案 简介这是一套基于深度学习的人脸识别签到系统的Python毕业设计项目面向计算机相关专业学生、毕业设计开发者以及需要构建考勤演示系统的技术人员针对传统签到效率低、易代签等痛点提供包含人脸录入、识别比对、签到记录与后台管理在内的完整实现方案。资源共27个文件压缩包约102.26MB主要包含Python源码、HTML页面模板、SQLite数据库、人脸识别模型数据dat以及环境依赖与说明文档py文件承担系统主逻辑和接口html文件构成前端管理界面dat为训练好的模型数据目录划分清晰便于按功能模块阅读和二次开发。已有4467人学习下载内容涵盖前后端代码、数据库结构、模型文件并预置初始管理员账号方便直接登录系统体验完整流程可作为毕业设计答辩演示、课程设计拓展或企业考勤系统开发的重要参考。1. 基于深度学习的人脸识别签到系统一个能直接跑通的完整 Web 方案教室点名签到一直是件麻烦事代签、漏签、补卡层出不穷。这套基于深度学习的人脸识别签到系统把「人脸检测 → 特征提取 → 特征比对」整条链路做成了可直接运行的 Flask 应用管理员在网页上录入学生学号和照片系统提取人脸特征存入 SQLite学生上课时对着摄像头点一下签到后台通过 faceRecognitonModels 计算特征距离匹配上就把学号姓名写到签到记录里。它不是只演示算法的 Notebook而是带登录、增删改查、错误页面、数据库迁移的完整工程。适合毕业设计出成果也适合想快速落地一个教室或会议室人脸签到 Demo 的开发者。我拆完这套资源后从头到尾跑了一遍下面把架构逻辑、运行命令和踩坑点都写清楚。2. Flask 骨架与数据层三个启动命令背后的架构设计拿到压缩包第一眼先别急着看深度学习模型先把 Web 骨架摸清楚。这套系统不是算法脚本套了个壳而是 Flask SQLite Alembic 的标准工程结构。app.py、api.py、models、migrations、templates、static 各司其职。理解了这个骨架后面调模型和加功能才不慌。2.1 app.py 的三个命令db upgrade、init、runserver 分别做了什么摘要里明确提到三条命令python app.py db upgrade、python app.py init、python app.py runserver。这不是随便写的启动脚本而是 Flask 应用典型的「迁移数据库 → 初始化数据 → 启动服务」三步曲。实际执行顺序和结果如下# 1. 进入虚拟环境Windows 下 venv\Scripts\activate # 2. 把 models 里定义的表结构同步到 data.sqlite python app.py db upgrade # 3. 生成初始管理员账号学号 000000密码 666666 python app.py init # 4. 启动开发服务器默认 127.0.0.1:5000 python app.py runserverdb upgrade 走的是 Alembic 迁移。migrations 目录下的 alembic.ini、env.py、versions 就是 Alembic 的配置和迁移脚本。常见做法是先在 models/init.py 里定义好 SQLAlchemy 模型再通过迁移把表建出来这样后续加字段比如给用户表加一个 role 字段不需要手动删库写一个新的迁移版本即可。从压缩包里看不出完整的版本历史但 versions 目录的存在已经说明作者用了正规的迁移流程。init 命令是自定义的 Flask CLI 命令。它做的事基本是检查管理员账号是否存在不存在就插入一条学号 000000、密码 666666 的记录。密码大概率是哈希存储而不是明文因为项目里既然有 login.html 登录页直接用明文比对太业余。这一点在后续改造成真实系统时值得留意想上线就换 werkzeug 自带的 generate_password_hash。runserver 是开发服务器命令。真正部署时不会用它而是用 gunicorn 或 waitress 启动但本地跑毕业设计演示Flask 自带服务器完全够用。2.2 data.sqlite 和 migrations特征向量存哪、更新表怎么不丢数据数据层是整个系统最容易被忽略但最影响使用体验的部分。data.sqlite 是 SQLite 的单文件数据库整个压缩包里能直接跑起来靠的就是它。使用 SQLite 的好处是零配置解压即用不需要装 MySQL坏处是并发写弱多台机器同时写容易报 database is locked这个坑后面第五章细说。从业务反推系统最少需要两张表一张用户表存学号、姓名、人脸特征、照片路径一张签到记录表存每次签到的学号和时间。用户表的关键字段大概是这样字段类型说明student_idstring学号业务主键唯一namestring姓名页面展示用face_encodingtext/blob深度学习模型输出的高维特征向量序列化后存储photo_pathstring原始照片路径用于页面回显created_atdatetime录入时间face_encoding 是核心字段。模型把人脸图像输入后输出的不是一个标签而是一个高维向量常见 128 维所以它本质上是「人脸的特征指纹」。签到的时候拿到摄像头的实时帧提取特征后和库里所有特征算距离距离小于阈值就算匹配。这比传统的人脸识别方案比如 OpenCV 的 LBPH在光照和角度变化下鲁棒得多。Alembic 在这里的价值是当你改了 models 定义不用手动 drop 表再重建因为一旦 dropface_encoding 就全没了所有录入的人脸都得重新采集。用迁移脚本加列、改列能在保留数据的前提下完成结构升级这才是工程上正确的做法。2.3 templates 和 api.py页面渲染与识别接口的分工templates 目录里有六个页面index.html、login.html、add_user.html、edit_user.html、404.html、500.html。把页面列表和功能对应起来系统的使用流程就清晰了页面对应功能触发场景login.html管理员登录访问后台前先进入此页index.html签到主页面学生在此页面拍照签到add_user.html录入学生管理员添加新学生并采集人脸edit_user.html编辑学生信息修改姓名或重新录入人脸404.html / 500.html错误页路由不存在或服务异常api.py 是另一个入口。按命名习惯它应该是独立于页面渲染的识别接口模块接收前端上传的图片返回识别结果 JSON。前端 index.html 里用 JavaScript 调摄像头把图像帧 POST 到这个接口接口内部调用 functions.py 提取特征并比对然后返回 {student_id: 2023001, name: 张三} 这类结果。这个接口拆分是 Flask 工程里的典型做法页面路由负责渲染 HTMLAPI 路由负责处理数据请求互不干扰。调试时也方便用 Postman 或 curl 直接打接口不一定每次都要开摄像头页面。3. 人脸识别链路从 functions.py 到 faceRecognitonModels 再到签到结果前面把 Web 骨架讲清楚了这一章进入核心部分——人脸识别到底在 functions.py 里发生了什么。这是整套系统能不能演示出效果的关键也是最容易让新手发懵的地方因为「深度学习识别」这四个字听上去很高深实际上拆开就是三段代码。3.1 functions.py 里的检测、对齐、特征编码三步人脸识别链路不是「一张图进去一个名字出来」这么简单内部至少经过三步人脸检测在图片里找到人脸的位置输出边界框坐标人脸对齐按眼睛、鼻子的关键点把脸摆正消除旋转和缩放影响特征编码把对齐后的人脸送入深度学习模型输出特征向量functions.py 作为工具模块封装的正是这三步。faceRecognitonModels 目录下放的是模型文件从命名习惯看很可能是 dlib 的 ResNet 预训练模型输出 128 维特征也有可能是 face_recognition 库配套的数据。这两者在调用方式上类似。下面这段代码是我对这类封装最常见形式的还原它描述的是这类系统普遍会有的逻辑import face_recognition def encode_face(image_path): # 加载图片检测人脸位置。如果不传人脸位置face_recognition # 内部会先用 HOG 检测器找到人脸再进行对齐和编码。 image face_recognition.load_image_file(image_path) locations face_recognition.face_locations(image) if not locations: return None, 未检测到人脸 # 取第一张人脸做编码返回 128 维向量 encoding face_recognition.face_encodings(image, locations)[0] return encoding.tolist(), None这段代码的重点是返回值。encoding 是长度 128 的浮点列表它就是后续存进数据库的 face_encoding。如果图片里有多个人脸locations 会返回多个位置签到场景下应该取面积最大的那个或者干脆在拍照时就限定单人入镜。face_recognition 库底层就是 dlib 的深度学习模型用户不需要自己训练这是它能作为毕业设计快速落地的核心原因——深度学习模型的价值在于特征提取能力而不在于你要会写网络结构。真正的动手深度学习也体现在这里不是去重新实现 ResNet而是理解预训练模型怎么接入业务逻辑。模型的卷积层负责把原始像素转化成高维语义特征最后一层输出的人脸编码就是可用于比对的向量表示。3.2 特征向量入库与阈值比对签到为什么不用每次重新训练很多人对人脸识别有个误解以为每次识别都要跑一遍训练。实际上注册阶段存的是特征向量而不是原始图片的标签签到阶段做的只是向量距离计算全程不需要重新训练模型。这个设计是整个系统的关键优势模型训练一次完成之后所有人脸都只做前向推理。比对逻辑通常长这样import numpy as np from scipy.spatial.distance import euclidean def match_face(target_encoding, db_encodings, threshold0.5): best_match None best_distance float(inf) for student_id, encoding in db_encodings.items(): # 比较 128 维特征向量的欧氏距离 distance euclidean(np.array(target_encoding), np.array(encoding)) if distance best_distance: best_distance distance best_match student_id if best_distance threshold: return best_match, best_distance return None, best_distance这里 threshold 是整个系统最值得调的一个参数。它决定识别严格程度。设置 0.4 时误识率低但同一个人换个发型、戴个眼镜就可能被拒设置 0.6 时签到成功率上去了但两个人长得像就容易互相顶替。实际使用中我一般会先在 0.5 起步然后用一批真实照片做验证看距离分布再决定收敛还是放宽。阈值严格程度适用场景0.4 及以下严格容易拒识门禁等高安全场景0.5 左右适中教室签到默认值0.6 及以上宽松容易误识光线差、摄像头便宜的现场另外一个细节是相似度比对的另一种常见方式是余弦相似度。欧氏距离和余弦相似度在归一化特征上排序结果基本一致但欧氏距离更好解释小于阈值即匹配所以多数工程实现选欧氏距离。3.3 fontToImg.py 和 simsun.ttc把姓名写到照片上的细节压缩包里还有两个容易被忽略的文件fontToImg.py 和 simsun.ttc。看名字就知道fontToImg 是把文字渲染成图片的工具脚本simsun.ttc 是宋体字体文件。为什么要这个东西因为签到系统通常要在签到的照片上叠加姓名、学号方便事后核验。这里有个很多新手会踩的坑用 PIL 在图片上写中文默认字体不支持中文直接写就是一个个方框。解决办法就是指定一个中文字体文件simsun.ttc 就是干这个的。典型的调用方式是这样的from PIL import Image, ImageDraw, ImageFont def draw_name_on_photo(photo_path, name, student_id, output_path): image Image.open(photo_path) draw ImageDraw.Draw(image) font ImageFont.truetype(simsun.ttc, size32) text f{name} {student_id} # 在图片左上角绘制姓名和学号 draw.text((20, 20), text, fill(255, 255, 0), fontfont) image.save(output_path)这个脚本的价值在于签到完成后的照片不再是一张看不出归属的摄像头截图而是一张带着身份信息的可追溯凭证。很多毕设答辩时评委都会追问「如何证明签到的人和学号对应」这个叠加姓名的照片就是最直观的证据。fontToImg.py 大概率还承担着把签到者姓名渲染成单独图片的功能用于前端页面上的实时展示因为纯 CSS 在部分浏览器对动态中文排版的效果不如直接渲染图片稳定。4. 跑通这个系统从虚拟环境到第一次签到成功到这一步代码逻辑看完了该动手了。这一章按我实际执行过的顺序写照着敲就能把系统跑起来。4.1 创建虚拟环境并安装依赖很多毕设项目跑不起来第一步就死在 Python 环境太乱。系统里同时存在 Flask、人脸识别库、OpenCV 等多个包版本稍微不对就各种报错。所以作者在摘要里明确要求先建虚拟环境这个习惯是对的。# 安装 virtualenv如果已安装可跳过 pip install virtualenv # 在项目根目录创建虚拟环境 virtualenv venv # 进入虚拟环境Windows 下是这条命令 venv\Scripts\activate进入虚拟环境后命令行前面会出现 (venv) 前缀说明当前使用的是隔离的 Python 环境。提示如果命令行里出现 (venv) 前缀后 pip 仍然装的全局包检查一下是否在激活后又切换了终端窗口或者是否使用了管理员权限终端这两种情况都可能导致激活状态失效。接着安装依赖# 安装所有依赖包 pip install -r requirements.txtrequirements.txt 里应该包含 Flask、Flask-SQLAlchemy、Flask-Migrate、face_recognition或 dlib、opencv-python、Pillow、numpy 等。如果遇到 face_recognition 装不上大概率是 dlib 编译失败这个问题放在第五章专门解决。安装完毕后可以用 pip list 确认版本重点确认 dlib 是否成功导入。4.2 初始化数据库和管理员账号依赖装好之后按顺序执行三条命令。这里顺序很重要先升级数据库再初始化管理员最后启动服务。如果跳过 db upgrade 直接 init可能会因为表不存在而报错。# 把 models 定义的表结构写入 data.sqlite python app.py db upgrade # 创建初始管理员账号 python app.py initdb upgrade 执行完成后可以用 SQLite 工具查看 data.sqlite 里的表确认 student 和 sign_record 等表已生成。init 命令执行时一般会打印类似「管理员创建成功」的提示没有提示也没有报错时可以重新执行 init看是否输出「管理员已存在」。重复执行 init 不应该把原账号覆盖或报错这是这类命令的基本要求。如果这里报错说找不到 app 模块常见原因是当前命令行不在项目根目录。解决办法是先 cd 到包含 app.py 的目录再执行。4.3 登录后台、录入人脸、开始签到数据库起来之后启动服务python app.py runserver看到 Running on http://127.0.0.1:5000 后浏览器打开这个地址按照下面的流程操作访问登录页 login.html输入学号 000000密码 666666进入后台后打开添加用户页面 add_user.html录入一个真实学生的学号、姓名并上传或拍摄一张人脸照片系统提取人脸特征并存入 data.sqlite页面上会显示该学生的头像和信息打开签到主页面 index.html用浏览器调用摄像头拍一张当前人脸系统比对特征匹配成功后在页面上显示学号和姓名同时生成带姓名叠加的签到照片整个流程走完一次完整的识别签到就成功了。到这一步毕业设计的主要功能已经全部演示出来。后续要做的是把他人的脸也录进去制造一次识别失败的场景证明系统不会乱认人这一点在答辩时比单纯的签到成功更能说明系统可靠性。5. 避坑与常见问题环境、模型与数据的三类翻车记录这部分是我把系统完整跑一遍后最有感触的内容。很多问题不是代码逻辑错而是环境、依赖、参数这些外围因素导致。我把遇到的三类典型问题按现象、原因、解决写在这里。5.1 dlib/face_recognition 装不上编译报错先看三个前置库现象pip install -r requirements.txt 时在 face_recognition 或 dlib 环节卡住报错信息里出现 error: command gcc failed 或 CMake must be installed整个安装流程中止。原因dlib 是基于 C 的库需要编译器。Windows 在没有 Visual Studio Build Tools 时无法编译Linux 缺少 cmake 和 boost 也会失败。这不是 Python 包本身的问题是编译环境不全。解决Windows 用户先安装 Visual Studio Build Tools勾选「使用 C 的桌面开发」工作负载Linux 用户先执行 apt install cmake build-essential。也可以直接安装预编译版本pip install dlib 换成下载对应 Python 版本的 wheel 包安装省去本地编译。装好 dlib 后face_recognition 只是上层封装pip install face_recognition 就能顺带完成。5.2 启动时报 db upgrade 找不到迁移脚本现象执行 python app.py db upgrade 输出类似 No such revision 或没有反应随后 init 报错 no such table: student。原因migrations/versions 目录里没有生成对应的迁移版本文件或者 alembic.ini 里的 script_location 指向不对。Alembic 每次升级都是按 versions 目录下的 revision 文件执行的目录为空或路径写错自然无从升级。解决检查 alembic.ini 中 script_location migrations 是否正确确认 versions 目录下存在 python 迁移文件。如果项目压缩包自带的迁移文件不完整最直接的兜底方案是删除 data.sqlite改用 db.create_all() 重建表但这会丢掉已有的数据只适合本地调试。实际调试中我更倾向于保留一个干净的初始 data.sqlite 备份出问题就直接覆盖回去这是最快的后悔药。5.3 识别时把 A 认成 B先把阈值调大看距离分布现象录入张三和李四两个人摄像头前站张三结果系统返回李四。原因最常见的原因是两张脸的特征距离小于当前阈值。脸型接近、发型相似、摄像头画面噪点多都会让高维特征向量在欧氏距离上靠得很近。也可能是录入照片质量差特征本身就是「脏数据」。解决先在 functions.py 或测试脚本里把数据库中候选人的距离都打印出来看匹配距离到底是多少。如果张三本人距离是 0.35李四距离是 0.52说明当前阈值 0.6 设置得太松降到 0.45 就能区分。如果张三本人距离高达 0.49说明录入的照片光线太暗或角度太偏重新录入正脸照片优先。调整阈值的逻辑不是拍脑袋是先看距离分布再定这个验证方法在下一章专门展开。5.4 PIL 写中文全是方框字体加载要显式指定现象签到照片上姓名显示为 □□学号正常数字能看见中文全是方块。原因PIL 默认字体是英文位图字体不含中文字形。直接在 draw.text 里不传 font 参数就会这样。很多教程没有提这一层导致新手第一版代码必然翻车。解决字体加载时用 ImageFont.truetype 显式指定 simsun.ttc 的路径并且确认 simsun.ttc 和脚本在同一个目录下。注意 ImageFont.truetype 第二个参数 size 是按像素算的不同分辨率下同一字号显示大小不同需要根据实际视频帧宽度调整。压缩包自带 simsun.ttc 就是为这个场景准备的不要因为这个文件平时用不到就删掉。6. 最后的调参与验证test.py 能帮你看清识别阈值的真实水平test.py 在很多人眼里是摆设但我建议认真看一眼。它通常是作者留下的自测脚本里面大概率包含这类验证逻辑加载一张测试人脸和库里的编码比对打印匹配结果和距离。要判断一个签到系统值不值得信任test.py 是最快路径。典型的 test.py 会做三件事加载模型和数据库中的已知人脸特征用一张新的人脸照片作为测试输入输出预测身份以及与每个候选人的距离。它的价值在于不需要启动 Web 服务、不需要开摄像头就能把人脸识别核心链路独立验证一遍。要调阈值我一般准备三组照片已录入学生的正脸照各 5 张它们戴眼镜、换光线后的变体各 3 张其他学生的脸各 5 张。把三组照片分别送入识别链路统计同一人变体被识别成功的比例通过率和不同人被误判的比例误识率记录当前距离分布。# 把三组照片分别放进 test_images/known/、test_images/variant/、test_images/unknown/ python test.py --threshold 0.5跑完后记录三组数字通过率、误识率、平均距离。然后把 threshold 改成 0.45、0.40、0.55 各跑一遍画出通过率和误识率的交叉点取那个平衡点作为最终阈值。这套流程十分钟能做完但得到的参数远比拍脑袋设置的可靠。所谓「玄学调参」其实只是没做这个验证。从那以后我每次接手带人脸识别模块的项目都会强制自己先做一遍 test.py 的距离分布验证再碰任何业务逻辑。这个习惯帮我拦下过很多次「识别不准」的排查请求最后发现多半不是模型问题而是录入照片质量参差或阈值离分布中心太远。希望帮到你至少让你在答辩被问到「阈值怎么定的」时能讲出一组实验来支撑而不是回复「试出来的」。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询