160-基于Flask的人脸识别校园考勤系统

基于 Django + dlib 的人脸识别校园考勤系统:从零到上线实践指南

本文完整分享一个基于 Django、dlib、face-recognition、OpenCV 的人脸识别校园考勤系统的设计与实现。文章涵盖目录结构、技术栈、关键代码、数据模型、业务流程、部署上线与可视化展示占位,开箱即用并便于二次开发。

— 联系方式:码界筑梦坊各大平台同名

目录

  • 项目概览与特性
  • 目录结构
  • 技术栈与环境
  • 业务与数据建模
  • 核心流程设计
  • 关键代码剖析
  • 路由与页面
  • 可视化展示
  • 本地开发与部署
  • 常见问题与排查
  • 演进与优化方向
  • 致谢

项目概览与特性

  • 学生/教师/管理员三类用户,基于会话的登录注册与信息完善。
  • 课程与节次管理,教师发布考勤时间窗,学生在窗口内完成“人脸签到”。
  • 人脸注册与识别:支持上传图片或摄像头拍照,提取面部编码并进行相似度比对。
  • 结果落库:识别日志与考勤记录入库,可扩展统计分析与可视化。

目录结构(精简)

djangoProject/
  djangoProject/
    settings.py        # 配置(MySQL、静态/媒体、上下文处理器)
    urls.py            # 全局路由,挂载 myApp
  myApp/
    models.py          # 用户、学院、专业、课程、节次、选课、请假、考勤、人脸相关模型
    views.py           # 登录注册、信息完善、课程/选课、人脸录入/签到、教师端发布考勤
    urls.py            # 业务路由
    face.py            # 人脸编码与识别流程(dlib + 欧氏距离阈值)
    templates/         # 前端模板(登录、录入、签到、课程等)
  utils/
    ways.py            # 基础工具(base64 转二进制等)
    getPublicData.py   # 公共数据查询封装
    getChartData.py    # 可视化数据准备(示例)
    *.dat              # dlib 人脸关键点/特征模型文件
  static/              # 前端静态资源(可替换为 CDN)
  media/faces/         # 用户人脸图片持久化目录
  requirements.txt     # 依赖(Django、dlib、face-recognition、opencv 等)
  manage.py

技术栈与环境

  • 后端框架:Django 3.1.14(会话登录、模板渲染、ORM、消息系统)
  • 数据库:MySQL(PyMySQL 驱动)
  • 人脸相关:
    • dlib(68 关键点 + ResNet 人脸特征)
    • face-recognition(封装的人脸编码/比对 API,可用于注册时提编码)
    • OpenCV(图像转灰度等基础处理)
  • 科学计算:NumPy、Pillow
  • 可视化:ECharts/Matplotlib/WordCloud(项目内已含 getChartData.pywordCloud.py 示例)
  • UI:SimpleUI(管理端优化)、本地静态资源模板

环境要求(Windows 示例):

  • Python 3.8+(建议)
  • MySQL 5.7+/8.0+
  • CMake 与 VS Build Tools(用于编译 dlib,或使用预构建 wheel)

业务与数据建模

  • 用户与角色:User(user_type=student|teacher|admin);学生/教师与用户一对一,包含扩展信息。
  • 课程体系:CourseCourseSession(节次/上课时间与签到时间窗)。
  • 选课记录:Enrollment(避免超额与重复选课)。
  • 人脸相关:
    • FaceEnrollmentRecord 保存用户的人脸图片路径与编码(二进制)
    • FaceRecognition 保存一次识别的结果(成功/失败、时间、关联节次)
    • Attendance 考勤记录,关联学生与节次

核心流程设计

  1. 人脸注册
    • 上传图片或前端拍照 base64 → 后端解析并保存到 media/faces/ → 通过 face-recognition/dlib 提取 128D 面部编码 → 写入 FaceEnrollmentRecord
  2. 发布考勤
    • 教师对课程发布 CourseSession,含上课时间与签到起止时间。
  3. 人脸签到
    • 学生上传签到图片 → dlib/face-recognition 提取编码 → 与库中自身编码做相似度比对(欧氏距离阈值 0.6)→ 成功则写入 FaceRecognition 并生成 Attendance

关键代码剖析(节选)

数据库配置与模板上下文处理器(djangoProject/settings.py):

INSTALLED_APPS = [
    'simpleui', 'django.contrib.admin', 'django.contrib.auth',
    'django.contrib.contenttypes', 'django.contrib.sessions',
    'django.contrib.messages', 'django.contrib.staticfiles',
    'myApp'
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'design_160_face',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306'
    }
}

TEMPLATES[0]['OPTIONS']['context_processors'] += [
    'myApp.context_processors.user_data',
]

核心模型(myApp/models.py)节选:

class CourseSession(models.Model):
    course = models.ForeignKey(Course, on_delete=models.CASCADE)
    session_time = models.DateTimeField()
    sign_in_start_time = models.DateTimeField()
    sign_in_end_time = models.DateTimeField()

    def is_sign_in_in_time(self, current_time):
        return self.sign_in_start_time <= current_time <= self.sign_in_end_time

class FaceEnrollmentRecord(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    enrollment_time = models.DateTimeField(auto_now_add=True)
    image_path = models.CharField(max_length=255)
    face_encoding = models.BinaryField()

class Attendance(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    course_session = models.ForeignKey(CourseSession, on_delete=models.CASCADE)
    date = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=20, choices=(
        ('present', '出勤'), ('absent', '缺席'), ('late', '迟到'), ('excused', '请假'),
    ))

人脸识别流程(myApp/face.py):

import dlib, cv2, numpy as np
from io import BytesIO
from PIL import Image
from .models import Student, FaceRecognition, Attendance, CourseSession, FaceEnrollmentRecord

detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor('utils/shape_predictor_68_face_landmarks.dat')
facerec = dlib.face_recognition_model_v1('utils/dlib_face_recognition_resnet_model_v1.dat')

def get_face_encoding(image_data):
    img = Image.open(BytesIO(image_data))
    img = np.array(img)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = detector(gray)
    if len(faces) == 0:
        return None
    shape = sp(gray, faces[0])
    face_descriptor = facerec.compute_face_descriptor(img, shape)
    return np.array(face_descriptor)

def recognize_face(face_image, course_session):
    face_encoding = get_face_encoding(face_image)
    if face_encoding is None:
        return {"status": "failed", "message": "未检测到人脸"}
    for student in Student.objects.all():
        rec = FaceEnrollmentRecord.objects.filter(user=student.user).first()
        if not rec: continue
        stored = np.frombuffer(rec.face_encoding, dtype=np.float64)
        if np.linalg.norm(face_encoding - stored) < 0.6:
            fr = FaceRecognition(user=student.user, status='success', course_session=course_session)
            fr.save()
            attendance = fr.create_attendance()
            return {"status": "success", "message": "签到成功", "attendance_status": getattr(attendance, 'status', None)}
    return {"status": "failed", "message": "未匹配到已注册人脸"}

人脸注册与签到视图(myApp/views.py)节选:

def enroll_face(request):
    username = request.session.get('username')
    user = User.objects.get(username=username)
    if request.method == 'POST':
        form = FaceEnrollmentForm(request.POST, request.FILES)
        if form.is_valid():
            # 保存图片到 media/faces 并提取 face_encoding,写入 FaceEnrollmentRecord
            # ...(略,详见仓库源码)
            messages.success(request, "人脸录入成功")
            return redirect('/myApp/enroll_face/')
    else:
        form = FaceEnrollmentForm()
    return render(request, 'enroll_face.html', {'form': form})

def check_in(request, course_session_id):
    course_session = CourseSession.objects.get(id=course_session_id)
    if request.method == "POST":
        face_image = request.FILES.get("face_image")
        result = recognize_face(face_image.read(), course_session)
        messages.success(request, result.get('message')) if result['status']=='success' \
            else messages.error(request, result.get('message'))
        return redirect('check_in', course_session_id=course_session.id)
    return render(request, 'check_in.html', {'course_session': course_session})

路由与页面

全局入口(djangoProject/urls.py):

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.login, name='login'),
    path('myApp/', include('myApp.urls')),
]

业务路由(myApp/urls.py)包含:

  • 登录/注册/登出
  • 信息完善(学生/教师)
  • 课程列表/详情/选课/退课
  • 人脸录入与签到、查看考勤、教师端发布考勤时间

前端模板位于 myApp/templates/,可替换为任意 UI 组件库(Bootstrap、Tailwind、AntD)或前后端分离改造。

可视化展示

🐼 项目源码获取,码界筑梦坊各平台同名,博客底部含联系方式卡片,欢迎咨询!

基于Flask的人脸识别校园考勤系统

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本地开发与部署

  1. 安装依赖
pip install -r requirements.txt
# Windows 若 dlib 安装失败:
# 方式A:预编译 wheel(匹配 Python/平台版本);
# 方式B:安装 CMake 与 VS Build Tools 后再 pip 安装
  1. 数据库配置
  • djangoProject/settings.py 修改 DATABASES 为你的 MySQL 连接参数。
  • 创建数据库 design_160_face(或自行更名)。
  1. 初始化与运行
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver 0.0.0.0:8000
  1. 静态与媒体
  • STATICFILES_DIRS 指向 static/;媒体文件(人脸图片)保存在 media/,确保有写权限。
  1. 生产部署要点
  • 关闭 DEBUG,设置 ALLOWED_HOSTS
  • 使用 uWSGI/gunicorn + Nginx;媒体/静态走 Nginx
  • 分离人脸模型与图片存储,考虑对象存储(OSS/七牛/又拍等)
  • 加入 HTTPS,敏感接口限流与鉴权

常见问题与排查

  • dlib 安装失败:优先尝试预编译 wheel;否则安装 CMake/VS Build Tools 后重试。
  • 无法检测到人脸:保证图像清晰、正脸、光照均匀;建议仅一张人脸入镜。
  • MySQL 连接失败:检查端口/用户权限/pymysql 安装。
  • 迁移冲突:清理 migrations 异常文件,或用 --fake/--fake-initial 处理历史。
  • URL 细节:注意路由参数格式,如 path('course/<int:course_id>/enroll/', ...)
  • 性能:大量比对时预加载编码到内存,并做索引或缓存;必要时改 ANN(近似最近邻)。

演进与优化方向

  • 鉴权升级:Django Auth 与权限系统完善;或切换 JWT 并前后端分离。
  • 活体检测与防攻击:加入眨眼检测、光流/深度/纹理反欺诈模块。
  • 相似度策略:欧氏距离阈值自适应/课程内 Top-K;或训练度量学习模型。
  • 特征管理:编码归一化、版本化、批量重提取与滚动更新。
  • 任务异步化:识别日志与统计写入 Celery,前端轮询或 WebSocket 推送。

致谢

  • dlib、face-recognition、OpenCV、Django 及其生态。

— 联系方式:码界筑梦坊各大平台同名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码界筑梦坊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值