就在刚刚,锋哥的人脸识别 智能考勤系统(深度学习+OpenCV DNN+FastAPI+Vue3) 视频教程,发布了。质量杠杠的!https://www.bilibili.com/video/BV17Hut6NE98/
本课程主要结合AI编程 Cursor 实现一个 人脸识别 智能考勤系统。讲解内容包括需求分析,YuNet人脸识别库介绍,SFace人脸识别特征提取库介绍,新建后端Python项目,新建Vue前端项目,利用Cursor AI编程实现Plan沟通项目方案,Agent生成项目,Agent修复bug和完善功能。利用AI编程开发项目的完整过程是免费的。一共是8讲,是免费的。高清视频+源码+领取
扫描下方公众号【python222】回复:888,
可获取下载链接
👇👇👇
项目效果预览:
Cursor AI 生成的这个项目 架构和代码质量非常高。锋哥花了2天时间,录制了这个项目的架构以及所有功能模块的实现讲解。一共16讲。这个是属于VIP会员享受的。
欢迎加入锋哥的VIP,目前活动,购买Python+AI大模型 VIP,送Java+AI大模型+AI编程 VIP。
一、项目概述
SmartFace Attendance(智能人脸考勤系统) 是一套面向企业日常考勤管理的 Web 应用。系统通过摄像头采集人脸图像,利用深度学习模型完成人脸检测与特征比对,实现员工无接触式签到/签退;管理员可在后台完成组织架构维护、人脸库管理、考勤记录查询、请假/加班审批及数据统计分析。
1.1 核心功能模块
| 模块 | 说明 |
|---|
| 刷脸打卡 | 公开页面,无需登录,摄像头采集人脸后自动识别并签到/签退 |
| 首页看板 | 展示在职人数、今日出勤、迟到数、识别成功率及 ECharts 统计图表 |
| 员工管理 | 员工档案 CRUD,关联部门、岗位、班次 |
| 人脸库 | 录入/删除员工人脸,提取 128 维特征向量存入数据库 |
| 组织架构 | 部门、岗位、班次(上下班时间、迟到/早退容忍分钟)管理 |
| 考勤记录 | 按日期、员工查询签到/签退记录及考勤状态 |
| 请假/加班 |
申请录入与审批(待审批 → 已通过/已拒绝) |
| 识别日志 | 记录每次刷脸识别的相似度、成功与否、IP 地址 |
| 个人中心 | 管理员头像上传、资料修改、密码修改 |
二、业务逻辑
2.1 系统角色
2.2 人脸注册流程
管理员在「员工管理」中创建员工档案(工号、姓名、部门、岗位、班次等)。
在「人脸库」页面选择员工,上传/拍摄正面清晰照片。
后端使用 YuNet 检测最大人脸,
SFace 提取 128 维特征向量。
特征向量以 JSON 格式存入 t_face 表,图片保存至 D:/uploads30/faces/。
应用启动时及每次注册/删除后,将全部特征加载至内存底库,供 1:N 比对。
2.3 刷脸打卡流程
员工打开 /punch 公开打卡页,前端调用摄像头采集 Base64 图片。
调用 POST /api/v1/punch(免 JWT 认证)。
FaceService 保存抓拍图 → 提取特征 → 与内存底库批量余弦相似度比对。
最高相似度 ≥ 阈值(默认 0.363)则匹配成功,否则返回识别失败。
写入 t_recognition_log 识别日志。
AttendanceService 根据当日是否已有记录决定签到或签退:
2.4 考勤状态判定规则
| 场景 | 判定逻辑 |
|---|
| 签到 | 打卡时间 ≤ 班次上班时间 + 迟到容忍分钟 → 正常;否则迟到 |
| 签退 | 打卡时间 < 班次下班时间 - 早退容忍分钟 → 早退;结合签到状态可产生「迟到且早退」 |
| 无班次 | 默认状态为「正常」 |
2.5 请假/加班审批
2.6 业务流程图
人脸注册流程
刷脸打卡流程
管理员登录与鉴权流程
三、技术栈
3.1 前端(client)
| 类别 |
技术 | 版本 | 用途 |
|---|
| 框架 | Vue 3 | ^3.5 | 组件化 UI |
| 构建 | Vite | ^8.2 | 开发服务器与打包 |
| UI 库 | Element Plus | ^2.9 | 表格、表单、布局组件 |
| 路由 | Vue Router | ^4.5 | SPA 路由与登录守卫 |
| 状态
| Pinia | ^2.3 | 管理员登录态 |
| HTTP | Axios | ^1.7 | REST API 请求 |
| 图表 | ECharts | ^5.5 | 首页看板统计图表 |
| 日期 | dayjs | ^1.11 | 日期格式化 |
3.2 后端(server)
| 类别 |
技术 | 用途 |
|---|
| Web 框架 | FastAPI | REST API、自动文档、依赖注入 |
| ASGI 服务器 | Uvicorn | 应用运行 |
| ORM | SQLAlchemy 2.x | 数据库模型与查询 |
| 数据库驱动 | PyMySQL | 连接 MySQL |
| 配置 | Pydantic Settings | 读取 .env 环境变量 |
| 认证 | PyJWT + bcrypt | JWT 令牌与密码哈希 |
| 图像处理 | OpenCV (opencv-python) | 人脸检测与识别 |
| 数值计算 | NumPy | 特征向量运算 |
| 图像读写 | Pillow | 辅助图像处理 |
3.3 AI 模型
| 模型 | 文件 | 功能 |
|---|
| YuNet | face_detection_yunet_2023mar.onnx | 人脸检测,选取最大人脸 |
| SFace | face_recognition_sface_2021dec.onnx | 人脸对齐与 128 维特征提取 |
3.4 数据库与部署
| 项目 | 说明 |
|---|
| 数据库 | MySQL 8,库名 db_smart_attendance,默认端口 3308 |
| 字符集 | utf8mb4 |
| 文件存储 | D:/uploads30(头像、人脸、打卡抓拍、ONNX 模型) |
| 后端端口 | 8030(可配置) |
| 前端开发 | Vite 默认端口,代理至后端 API |
四、系统架构
4.1 总体架构
系统采用 前后端分离 架构:Vue 3 单页应用负责管理端 UI 与公开打卡页;FastAPI 提供 RESTful API;MySQL 持久化业务数据;OpenCV DNN 模块在服务端完成人脸 AI 推理。
4.2 技术分层架构
4.3 后端目录结构
server/
├── main.py # FastAPI 应用入口、CORS、静态文件挂载
├── requirements.txt # Python 依赖
├── sql/
│ └── db_smart_attendance.sql # 数据库初始化脚本
└── app/
├── api/v1/ # REST API 路由
│ ├── auth.py # 登录认证
│ ├── profile.py # 个人中心
│ ├── employee.py # 员工管理
│ ├── face.py # 人脸库
│ ├── punch.py # 刷脸打卡(公开)
│ ├── attendance.py # 考勤记录
│ ├── leave.py # 请假管理
│ ├── overtime.py # 加班管理
│ ├── stats.py # 首页统计
│ └── ...
├── core/ # 配置、安全、依赖注入
├── db/ # 数据库 Session
├── models/ # SQLAlchemy ORM 模型
├── schemas/ # Pydantic 请求/响应模型
├── services/ # 业务服务(人脸、考勤)
└── utils/ # 工具类(文件、CRUD)
4.4 前端目录结构
client/
├── src/
│ ├── views/ # 页面组件(Home、Employee、Punch 等)
│ ├── layout/ # MainLayout 主布局
│ ├── router/ # 路由与登录守卫
│ ├── store/ # Pinia 用户状态
│ ├── api/ # API 封装
│ └── utils/ # 请求拦截、日期、美颜等工具
├── vite.config.js # Vite 配置与 API 代理
└── package.json
4.5 API 接口一览
| 前缀 | 模块 | 鉴权 | 说明 |
|---|
/api/v1/auth | 认证 | 部分 | 登录、获取当前用户 |
/api/v1/profile | 个人中心 | JWT | 资料修改、密码修改 |
/api/v1/departments | 部门 |
JWT | 部门 CRUD |
/api/v1/positions | 岗位 | JWT | 岗位 CRUD |
/api/v1/shifts | 班次 | JWT | 班次 CRUD |
/api/v1/employees | 员工 | JWT | 员工 CRUD |
/api/v1/faces | 人脸库 | JWT | 人脸注册/删除/列表 |
/api/v1/attendance | 考勤 | JWT | 考勤记录查询 |
/api/v1/leaves | 请假 | JWT | 请假 CRUD 与审批 |
/api/v1/overtimes | 加班 | JWT | 加班 CRUD 与审批 |
/api/v1/recognition-logs | 识别日志 | JWT | 识别记录查询 |
/api/v1/stats | 统计 | JWT |
首页看板数据 |
/api/v1/upload | 上传 | JWT | 头像/图片上传 |
/api/v1/punch | 打卡 | 公开 | 刷脸签到/签退 |
4.6 数据库 ER 关系
五、数据库设计
5.1 t_admin(管理员表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id | INT | — | 否 | 主键ID,自增 |
| username |
VARCHAR | 50 | 否 | 登录账号,唯一 |
| password | VARCHAR | 255 | 否 | 登录密码 |
| nickname | VARCHAR | 50 | 是 | 昵称 |
| avatar | VARCHAR | 255 | 是 | 头像路径 |
| phone | VARCHAR | 20 |
是 | 手机号 |
| email | VARCHAR | 100 | 是 | 邮箱 |
| status | TINYINT | — | 否 | 状态:1启用 0禁用,默认1 |
| create_time | DATETIME | — | 否 | 创建时间,默认当前时间 |
| update_time | DATETIME | — | 否 | 更新时间,自动更新 |
索引:PRIMARY KEY (id),UNIQUE KEY uk_admin_username (username)
5.2 t_department(部门表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id | INT | — | 否 |
主键ID,自增 |
| name | VARCHAR | 100 | 否 | 部门名称 |
| code | VARCHAR | 50 | 否 | 部门编码,唯一 |
| leader | VARCHAR | 50 | 是 | 负责人 |
| phone | VARCHAR | 20 | 是 | 联系电话 |
|
sort_order | INT | — | 否 | 排序,默认0 |
| status | TINYINT | — | 否 | 状态:1启用 0禁用,默认1 |
| create_time | DATETIME | — | 否 | 创建时间 |
| update_time | DATETIME | — | 否 | 更新时间 |
索引:PRIMARY KEY (id
),UNIQUE KEY uk_dept_code (code)
5.3 t_position(岗位表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id | INT | — | 否 | 主键ID,自增 |
| name |
VARCHAR | 100 | 否 | 岗位名称 |
| code | VARCHAR | 50 | 否 | 岗位编码,唯一 |
| sort_order | INT | — | 否 | 排序,默认0 |
| status | TINYINT | — | 否 | 状态:1启用 0禁用,默认1 |
| create_time | DATETIME | — |
否 | 创建时间 |
| update_time | DATETIME | — | 否 | 更新时间 |
索引:PRIMARY KEY (id),UNIQUE KEY uk_position_code (code)
5.4 t_shift(班次表)
| 字段名 | 字段类型 | 长度 |
是否为空 | 备注 |
|---|
| id | INT | — | 否 | 主键ID,自增 |
| name | VARCHAR | 100 | 否 | 班次名称 |
| start_time | TIME | — | 否 | 上班时间 |
| end_time | TIME | — | 否 |
下班时间 |
| late_tolerance | INT | — | 否 | 迟到容忍分钟,默认10 |
| early_tolerance | INT | — | 否 | 早退容忍分钟,默认10 |
| status | TINYINT | — | 否 | 状态:1启用 0禁用,默认1 |
| create_time | DATETIME | — | 否 | 创建时间 |
|
update_time | DATETIME | — | 否 | 更新时间 |
索引:PRIMARY KEY (id)
5.5 t_employee(员工表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id | INT
| — | 否 | 主键ID,自增 |
| emp_no | VARCHAR | 50 | 否 | 工号,唯一 |
| name | VARCHAR | 50 | 否 | 姓名 |
| gender | TINYINT | — | 否 | 性别:1男 2女,默认1 |
| avatar | VARCHAR | 255 | 是 |
头像路径 |
| phone | VARCHAR | 20 | 是 | 手机号 |
| email | VARCHAR | 100 | 是 | 邮箱 |
| department_id | INT | — | 是 | 部门ID,关联 t_department.id |
| position_id | INT | — | 是 | 岗位ID,关联 t_position.id |
|
shift_id | INT | — | 是 | 班次ID,关联 t_shift.id |
| hire_date | DATE | — | 是 | 入职日期 |
| status | TINYINT | — | 否 | 状态:1在职 0离职,默认1 |
| create_time | DATETIME | — | 否 | 创建时间 |
| update_time | DATETIME |
— | 否 | 更新时间 |
索引:PRIMARY KEY (id),UNIQUE KEY uk_emp_no (emp_no),KEY idx_employee_dept (department_id),KEY idx_employee_shift (shift_id)
5.6 t_face(人脸库表)
| 字段名 | 字段类型 |
长度 | 是否为空 | 备注 |
|---|
| id | INT | — | 否 | 主键ID,自增 |
| employee_id | INT | — | 否 | 员工ID,关联 t_employee.id |
| image_path | VARCHAR | 255 | 否 | 人脸图片路径 |
| feature | JSON | — |
是 | 128维人脸特征向量 |
| quality_score | DECIMAL | 5,2 | 是 | 人脸质量分 |
| is_primary | TINYINT | — | 否 | 是否主脸:1是 0否,默认1 |
| create_time | DATETIME | — | 否 | 创建时间 |
| update_time | DATETIME | — | 否 | 更新时间 |
索引:PRIMARY KEY (id),KEY idx_face_employee (employee_id)
5.7 t_attendance(考勤记录表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id | INT | — |
否 | 主键ID,自增 |
| employee_id | INT | — | 否 | 员工ID,关联 t_employee.id |
| attendance_date | DATE | — | 否 | 考勤日期 |
| check_in_time | DATETIME | — | 是 | 签到时间 |
| check_out_time | DATETIME | — | 是 | 签退时间 |
|
check_in_image | VARCHAR | 255 | 是 | 签到抓拍图路径 |
| check_out_image | VARCHAR | 255 | 是 | 签退抓拍图路径 |
| status | VARCHAR | 20 | 否 | 考勤状态,默认「正常」 |
| work_hours | DECIMAL | 5,2 | 是 | 工时(小时) |
| similarity | DECIMAL |
5,4 | 是 | 识别相似度 |
| remark | VARCHAR | 255 | 是 | 备注 |
| create_time | DATETIME | — | 否 | 创建时间 |
| update_time | DATETIME | — | 否 | 更新时间 |
考勤状态枚举:正常、迟到、早退、迟到且早退、缺卡
索引
:PRIMARY KEY (id),UNIQUE KEY uk_attendance_emp_date (employee_id, attendance_date),KEY idx_attendance_date (attendance_date)
5.8 t_leave(请假表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id |
INT | — | 否 | 主键ID,自增 |
| employee_id | INT | — | 否 | 员工ID,关联 t_employee.id |
| leave_type | VARCHAR | 20 | 否 | 请假类型(事假/病假/年假等) |
| start_time | DATETIME | — | 否 | 开始时间 |
| end_time | DATETIME | — |
否 | 结束时间 |
| duration | DECIMAL | 5,2 | 否 | 时长(小时) |
| reason | VARCHAR | 500 | 是 | 请假原因 |
| status | VARCHAR | 20 | 否 | 审批状态,默认「待审批」 |
| approver_id | INT | — | 是 | 审批人ID,关联 t_admin.id |
|
approve_time | DATETIME | — | 是 | 审批时间 |
| create_time | DATETIME | — | 否 | 创建时间 |
| update_time | DATETIME | — | 否 | 更新时间 |
审批状态枚举:待审批、已通过、已拒绝
索引:PRIMARY KEY (id),KEY idx_leave_employee (
employee_id)
5.9 t_overtime(加班表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id | INT | — | 否 | 主键ID,自增 |
| employee_id | INT | — |
否 | 员工ID,关联 t_employee.id |
| start_time | DATETIME | — | 否 | 开始时间 |
| end_time | DATETIME | — | 否 | 结束时间 |
| duration | DECIMAL | 5,2 | 否 | 时长(小时) |
| reason | VARCHAR | 500 | 是 | 加班原因 |
|
status | VARCHAR | 20 | 否 | 审批状态,默认「待审批」 |
| approver_id | INT | — | 是 | 审批人ID,关联 t_admin.id |
| approve_time | DATETIME | — | 是 | 审批时间 |
| create_time | DATETIME | — | 否 | 创建时间 |
| update_time | DATETIME |
— | 否 | 更新时间 |
索引:PRIMARY KEY (id),KEY idx_overtime_employee (employee_id)
5.10 t_recognition_log(识别日志表)
| 字段名 | 字段类型 | 长度 | 是否为空 | 备注 |
|---|
| id |
INT | — | 否 | 主键ID,自增 |
| employee_id | INT | — | 是 | 识别到的员工ID,失败时为 NULL |
| similarity | DECIMAL | 5,4 | 是 | 相似度 |
| success | TINYINT | — | 否 | 是否成功:1是 0否,默认0 |
| image_path | VARCHAR | 255
| 是 | 抓拍图片路径 |
| ip_address | VARCHAR | 50 | 是 | 客户端 IP 地址 |
| create_time | DATETIME | — | 否 | 识别时间 |
索引:PRIMARY KEY (id),KEY idx_recognition_time (create_time)
六、关键技术说明
6.1 人脸识别引擎
FaceEngine 采用单例模式,应用生命周期内只加载一次 ONNX 模型。
检测阶段使用 OpenCV FaceDetectorYN(YuNet),输入尺寸自适应,置信度阈值 0.9。
识别阶段使用 FaceRecognizerSF(SFace),对齐裁剪后输出 128 维特征。
1:N 比对采用批量余弦相似度,阈值 FACE_THRESHOLD = 0.363(可在 .env 配置)。
6.2 内存人脸底库
6.3 安全机制
6.4 统一响应格式
{
"code": 200,
"msg": "操作成功",
"data": { }
}
七、部署架构
| 组件 |
默认配置 |
|---|
| MySQL | 127.0.0.1:3308,用户 root,密码 123456 |
| FastAPI | 0.0.0.0:8030 |
| 上传目录 | D:/uploads30 |
| JWT 有效期 | 24 小时 |