news 2026/7/2 4:31:58

基于 ResNet50 迁移学习实现人脸考勤系统(完整 Kaggle Notebook 工程)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 ResNet50 迁移学习实现人脸考勤系统(完整 Kaggle Notebook 工程)

目录

摘要

一、项目整体架构与设计思路

1.1 系统模块拆分

1.2 技术选型优势

二、环境初始化与数据集解析

2.1 环境依赖与中文绘图配置

2.2 数据集结构解析

2.3 全局常量定义

三、人脸预处理:OpenCV 人脸裁剪与数据增强

3.1 人脸检测裁剪函数extract_face

3.2 训练数据增强生成器

四、基于 ResNet50 迁移学习的人脸分类模型

4.1 模型搭建核心思路

4.2 模型参数分析

4.3 模型训练过程与曲线解读

训练可视化曲线分析

4.4 全数据集精度测试

五、人脸考勤业务逻辑实现(工程化核心)

5.1 考勤全局变量

5.2 考勤状态判定函数

5.3 核心签到函数face_sign_in

5.4 全员考勤模拟测试

六、考勤报表自动导出与模型保存

6.1 明细表 + 汇总表生成

6.2 多格式文件导出

6.3 报表效果展示

七、系统现存局限与优化拓展方案

7.1 当前项目短板

7.2 进阶优化方向

八、项目总结

摘要

本文完整落地一套人脸检测 + 迁移学习人脸识别 + 智能考勤统计 + 报表导出全链路系统,依托 5 Celebrity Faces 小型名人人脸数据集,采用 ResNet50 迁移学习完成 5 分类人脸识别,识别准确率达 98.92%;配套实现上下班签到逻辑、迟到 / 早退判定、去重签到、Excel/CSV 多格式考勤报表自动导出,全部代码可在 Kaggle Notebook 一键运行,适合人工智能图像分类、计算机视觉工程化落地学习参考。

关键词:ResNet50;迁移学习;人脸识别;OpenCV 人脸裁剪;TensorFlow;人脸考勤系统;图像分类

一、项目整体架构与设计思路

1.1 系统模块拆分

整套工程分为 6 大解耦模块,分层清晰、可独立复用:

  1. 环境与数据集加载模块:Kaggle 数据集路径读取、人员分类解析、全局参数定义
  2. 图像预处理模块:OpenCV Haar 级联人脸裁剪、数据增强、ResNet 官方标准化预处理
  3. 迁移学习模型构建模块:冻结预训练 ResNet50 主干 + 自定义分类头搭建人脸分类网络
  4. 模型训练与评估模块:15 轮迭代训练、训练曲线可视化、全数据集精度测试
  5. 人脸识别推理模块:单图人脸预测、置信度阈值过滤陌生人、批量精度验证
  6. 智能考勤业务模块:上下班签到、重复签到拦截、考勤状态判定、报表自动生成导出

1.2 技术选型优势

  • 迁移学习:小样本场景下复用 ImageNet 预训练视觉特征,仅微调少量参数,收敛速度快、泛化能力强;总参数量 2411 万,可训练参数仅 52 万,训练成本极低
  • 双阶段人脸处理:先 OpenCV 裁剪人脸过滤背景干扰,再送入 ResNet 分类,大幅降低无关像素对识别结果的影响
  • 轻量化工程落地:无复杂 GUI 依赖,纯 Python 脚本实现完整考勤业务,自动输出标准化报表,可快速迁移至企业人脸打卡场景
  • 完备可视化:训练准确率 / 损失曲线、中文绘图支持,训练过程直观可观测

二、环境初始化与数据集解析

2.1 环境依赖与中文绘图配置

工程依赖OpenCV、TensorFlow/Keras、Pandas、Matplotlib,Kaggle Linux 环境预装基础库,仅需安装 Noto 中文字体解决绘图中文乱码问题:

# 安装开源中文字体 !apt-get update -qq && apt-get install -y -qq fonts-noto-cjk # 加载字体,全局绘图中文渲染 from matplotlib.font_manager import FontProperties font = FontProperties(fname="/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", size=12) plt.rcParams['axes.unicode_minus'] = False

日志出现Noto Sans CJK JP not found为无害冗余匹配警告,不影响中文正常显示,生产环境可通过指定通用字体消除。

2.2 数据集结构解析

项目采用公开5 Celebrity Faces 名人人脸数据集,文件夹层级结构如下:

plaintext

/kaggle/input/datasets/dansbecker/5-celebrity-faces-dataset/train ├─ ben_afflek ├─ elton_john ├─ jerry_seinfeld ├─ madonna └─ mindy_kaling

数据集核心参数:

  1. 总样本:93 张人脸图片,代码自动按 8:2 切分,训练集 77 张、验证集 16 张;
  2. 分类数量:5 位独立名人,每个文件夹对应 1 个人脸类别;
  3. 标签机制:代码自动读取文件夹名称作为分类标签,生成「数字索引 - 人名」映射字典,后续可直接拓展多人脸数据集。

2.3 全局常量定义

IMG_SIZE = (160, 160) # 模型输入统一尺寸 BATCH_SIZE = 8 # 训练批次大小 EPOCHS = 15 # 训练迭代轮次 WORK_START_TIME = "09:00:00" # 上班基准时间 WORK_END_TIME = "18:00:00" # 下班基准时间

三、人脸预处理:OpenCV 人脸裁剪与数据增强

3.1 人脸检测裁剪函数extract_face

使用 OpenCV 内置正面人脸检测器,实现智能人脸截取兜底逻辑,解决无检测人脸时推理崩溃问题:

  1. 图片转灰度图,detectMultiScale检测所有人脸框
  2. 多人脸场景:选取面积最大人脸,避免局部五官干扰
  3. 无人脸场景:直接缩放原图作为兜底输入,保证推理不中断
  4. BGR 转 RGB、像素归一化至 0~1,统一输入格式与训练流程对齐
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') def extract_face(img_path, target_size=(160, 160)): img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4) if len(faces) == 0: img = cv2.resize(img, target_size) return (img[...,::-1] / 255.0).astype('float32') x, y, w, h = max(faces, key=lambda b: b[2]*b[3]) face = img[y:y+h, x:x+w] face = cv2.resize(face, target_size) return (face[...,::-1] / 255.0).astype('float32')

单图测试可正常裁剪人脸,过滤背景冗余信息,为后续分类降低学习难度。

3.2 训练数据增强生成器

使用ImageDataGenerator做在线数据增强,缓解小样本过拟合,同时接入 ResNet 官方预处理逻辑,替代简单像素归一化:

from tensorflow.keras.applications.resnet50 import preprocess_input train_datagen = ImageDataGenerator( preprocessing_function=preprocess_input, # ResNet专属标准化 rotation_range=10, # 随机小角度旋转 width_shift_range=0.1, # 水平偏移 height_shift_range=0.1, # 垂直偏移 horizontal_flip=True, # 水平翻转 validation_split=0.2 # 划分20%数据作为验证集 ) # 分别加载训练/验证集生成器 train_generator = train_datagen.flow_from_directory( dataset_path, target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='categorical', subset='training', shuffle=True ) val_generator = train_datagen.flow_from_directory( dataset_path, target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode='categorical', subset='validation', shuffle=False )

自动读取文件夹名作为分类标签,输出独热编码,适配多分类交叉熵损失函数。


四、基于 ResNet50 迁移学习的人脸分类模型

4.1 模型搭建核心思路

迁移学习分为两大模块:

  1. 冻结预训练主干:加载 ImageNet 预训练 ResNet50,移除顶层全连接分类层,冻结全部权重,仅作为通用视觉特征提取器;复用海量自然图像学到的轮廓、五官纹理特征。
  2. 自定义人脸分类头:全局平均池化压缩特征向量 → 256 维全连接层学习人脸专属特征 → Dropout (0.5) 抑制过拟合 → Softmax 输出 5 分类概率。 完整网络代码:
# 加载预训练ResNet50,去除顶层分类 base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(160,160,3)) base_model.trainable = False # 冻结主干权重 # 搭建完整人脸识别模型 model = models.Sequential([ base_model, layers.GlobalAveragePooling2D(), layers.Dense(256, activation='relu'), layers.Dropout(0.5), layers.Dense(5, activation='softmax') ]) # 模型编译 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) model.summary()

4.2 模型参数分析

表格

参数项数值说明
总参数量24,113,54191.99MB
可训练参数525,829仅分类头参与训练,训练速度快
不可训练参数23,587,712ResNet50 预训练主干,保留通用视觉特征

4.3 模型训练过程与曲线解读

执行 15 轮迭代训练,关键指标节选:

表格

Epoch训练准确率验证准确率训练损失验证损失
10.29870.68752.22910.8230
60.90911.00000.21100.1600
150.96100.93750.07930.1230

训练可视化曲线分析
  1. 准确率曲线:训练、验证准确率同步快速上升,前 6 轮验证集达到 100%,后期稳定在 93%~96% 区间;少量震荡源于数据集样本总量仅 93 张,验证集仅 16 张,单轮波动属于小样本正常现象。
  2. 损失曲线:训练与验证损失同步快速收敛至 0.2 以下,两条曲线无明显分离,Dropout 与数据增强有效抑制过拟合。

4.4 全数据集精度测试

推理函数recognize_face实现和训练完全对齐的预处理逻辑,设置置信度阈值 0.6 过滤陌生人,遍历全部 93 张样本做批量精度验证:

def recognize_face(img_path, threshold=0.6): img = cv2.resize(cv2.imread(img_path), IMG_SIZE) img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_input = preprocess_input(img_rgb) img_input = np.expand_dims(img_input, axis=0) pred = model.predict(img_input, verbose=0)[0] pred_idx = np.argmax(pred) confidence = pred[pred_idx] if confidence < threshold: return "陌生人", confidence return idx_to_name[pred_idx], confidence

批量遍历测试结果:

  • 总样本数:93
  • 识别正确数:92
  • 整体识别准确率:98.92%极高精度验证迁移学习在小样本人脸分类场景的优越性。

五、人脸考勤业务逻辑实现(工程化核心)

本项目区别于单纯图像分类 Demo,完整落地企业级考勤业务逻辑,包含签到去重、考勤状态判定、全流程记录。

5.1 考勤全局变量

from datetime import datetime today = datetime.now().strftime("%Y-%m-%d") attendance_records = [] # 存储每条签到明细 signed_in_set = set() # 上班签到去重集合 signed_out_set = set() # 下班签退去重集合

5.2 考勤状态判定函数

根据签到时间区分正常、迟到、早退三种状态:

def check_attendance_status(sign_time_str, sign_type="in"): if sign_type == "in": return "迟到" if sign_time_str > WORK_START_TIME else "正常" else: return "早退" if sign_time_str < WORK_END_TIME else "正常"

5.3 核心签到函数face_sign_in

串联人脸识别、陌生人拦截、重复签到校验、记录存储全流程:

  1. 调用人脸识别函数获取姓名与置信度,置信不足判定为陌生人,直接返回签到失败
  2. 生成当日唯一签到 Key,存入集合实现去重,同一人员当日无法重复签到 / 签退
  3. 获取当前系统时间,判定考勤状态
  4. 组装签到明细字典存入全局列表,返回签到结果提示
def face_sign_in(img_path, sign_type="in"): name, confidence = recognize_face(img_path) if name == "陌生人": return f"❌ 签到失败:未识别到有效人员(置信度:{confidence:.2f})" unique_key = f"{today}_{name}_{sign_type}" type_name = "上班签到" if sign_type == "in" else "下班签退" # 重复签到拦截 if sign_type == "in" and unique_key in signed_in_set: return f"⚠️ {name} 今日已完成上班签到,无需重复操作" if sign_type == "out" and unique_key in signed_out_set: return f"⚠️ {name} 今日已完成下班签退,无需重复操作" # 记录考勤信息 now_time = datetime.now().strftime("%H:%M:%S") status = check_attendance_status(now_time, sign_type) record = { "日期": today, "姓名": name, "签到类型": type_name, "签到时间": now_time, "考勤状态": status, "识别置信度": round(confidence, 4) } attendance_records.append(record) # 加入去重集合 if sign_type == "in": signed_in_set.add(unique_key) else: signed_out_set.add(unique_key) return f"✅ {name} {type_name}成功 | 时间:{now_time} | 状态:{status}"

5.4 全员考勤模拟测试

遍历 5 位人员图片,分别模拟上班签到、下班签退流程,输出日志:

人脸识别考勤项目开题报告

  • 上班签到:当前时间早于 9 点,全部判定为「正常」
  • 下班签退:当前时间早于 18 点,全部判定为「早退」
  • 同一人员重复调用签到函数会触发重复操作拦截提示

六、考勤报表自动导出与模型保存

6.1 明细表 + 汇总表生成

  1. 考勤明细表:将attendance_records列表转为 Pandas DataFrame,存储每一条签到原始记录,包含日期、姓名、签到时间、置信度、考勤状态全维度信息。
  2. 考勤汇总表:自动统计当日核心指标:应到人数、实到签到人数、缺勤人数、迟到人数、完成签退人数、早退人数。
# 明细表 df_detail = pd.DataFrame(attendance_records) # 汇总统计 total_person = 5 sign_in_count = len(signed_in_set) absent_count = total_person - sign_in_count late_count = len(df_detail[(df_detail["签到类型"]=="上班签到") & (df_detail["考勤状态"]=="迟到")]) early_leave_count = len(df_detail[(df_detail["签到类型"]=="下班签退") & (df_detail["考勤状态"]=="早退")]) summary_data = { "统计日期": [today], "应到人数": [total_person], "实到签到人数": [sign_in_count], "缺勤人数": [absent_count], "迟到人数": [late_count], "完成签退人数": [len(signed_out_set)], "早退人数": [early_leave_count] } df_summary = pd.DataFrame(summary_data)

6.2 多格式文件导出

兼容 Excel(双工作表)、CSV 通用格式,同时保存训练完成的人脸识别模型:

# 导出Excel(汇总+明细双工作表) excel_path = "人脸考勤系统报表.xlsx" with pd.ExcelWriter(excel_path, engine="openpyxl") as writer: df_summary.to_excel(writer, sheet_name="考勤汇总", index=False) df_detail.to_excel(writer, sheet_name="考勤明细", index=False) # 导出CSV df_detail.to_csv("考勤明细表.csv", index=False, encoding="utf-8-sig") df_summary.to_csv("考勤汇总表.csv", index=False, encoding="utf-8-sig") # 保存训练模型 model.save("人脸识别模型.h5")

最终输出 4 份可下载文件:Excel 综合报表、明细 CSV、汇总 CSV、h5 格式人脸识别模型。

保存 h5 文件会弹出版本警告,为 TensorFlow 官方提示,推荐生产环境替换为.keras格式存储模型。

6.3 报表效果展示

明细表共 10 条记录(5 人签到 + 5 人签退),每条记录附带识别置信度;汇总表当日 5 人全部签到签退,无缺勤、无迟到、全部早退,统计数据和签到日志完全匹配,数据一致性可靠。


七、系统现存局限与优化拓展方案

7.1 当前项目短板

  1. 人脸检测器限制:Haar 级联仅适配正面无遮挡人脸,侧脸、口罩遮挡、暗光场景检测失效,兜底逻辑会直接送入原图,降低识别精度。
  2. 数据集规模偏小:仅 93 张样本,验证集波动大,泛化能力受限,真实企业场景需扩充千人级人脸库。
  3. 考勤存储临时化:当前签到记录仅存储在内存列表,Notebook 会话关闭数据丢失,无持久化数据库支持。
  4. 单阈值识别:全局固定 0.6 置信度阈值,无法针对不同人员动态调整识别门槛。

7.2 进阶优化方向

  1. 人脸检测升级:替换 Haar 检测器为 MTCNN/RetinaFace,支持多角度、遮挡、弱光人脸检测,大幅提升复杂场景鲁棒性。
  2. 模型训练优化
    • 训练后半段解冻 ResNet50 底层网络,微调全部权重,提升人脸特征适配性;
    • 加入 L2 正则、早停策略EarlyStopping,进一步抑制震荡与过拟合。
  3. 工程化持久化
    • 接入 SQLite/MySQL 数据库存储每日考勤记录,支持跨会话数据查询;
    • 增加日期筛选函数,实现历史考勤汇总导出。
  4. 业务功能拓展
    • 增加陌生人抓拍存储、人员人脸库新增接口;
    • 接入摄像头实时流推理,实现实时打卡 GUI 界面;
    • 增加月度考勤统计、迟到早退频次可视化图表。
  5. 模型存储规范:将model.save("xxx.h5")替换为官方推荐格式model.save("人脸识别模型.keras")消除版本警告。

八、项目总结

本项目跳出传统仅做图像分类的 Demo 开发,以企业人脸考勤真实业务为目标,完成从数据集加载、人脸预处理、迁移学习模型训练、推理识别到考勤业务、自动报表导出的完整工程闭环。

  1. 技术价值:完整演示迁移学习在小样本视觉分类场景的落地方法,讲解 ResNet 特征提取 + 自定义分类头的搭建思路,训练曲线、精度测试环节可作为深度学习课程实践案例。
  2. 工程价值:代码分层解耦、业务逻辑完整,签到去重、考勤状态判定、多格式报表等模块可直接复用至实际人脸打卡系统,快速完成二次开发。
  3. 学习门槛低:全部代码兼容 Kaggle Notebook,无需本地 GPU 环境,复制即可运行,适合计算机视觉入门、人工智能工程化实践学习。

整套工程完整代码已拆分至 19 段 Notebook 单元,按照本文模块顺序依次执行即可复现全部训练、考勤、报表导出效果,同时预留充足拓展空间,可根据企业实际需求迭代优化。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 4:30:38

Java毕设项目:基于 SpringBoot 的智能云端日记记录与分享系统的设计与实现 基于 SpringBoot 的日常随笔云端同步管理系统 (源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/7/2 4:25:25

市面上有实力的海泡石工厂有哪些

海泡石作为一种具有特殊性能的非金属矿物&#xff0c;在多个领域都有广泛应用。市面上有不少有实力的海泡石工厂&#xff0c;以下为你详细介绍。远大云母&#xff1a;综合实力强劲远大云母厂在海泡石的专业生产上具有较高的水准。其专注于海泡石产品的研发与生产&#xff0c;在…

作者头像 李华
网站建设 2026/7/2 4:22:47

iPhone 18 Pro Max银灰色版本采用了一体化同色设计

苹果将在今年9月推出新一代旗舰手机「iPhone 18」系列&#xff0c;不出意外的话&#xff0c;7-8月也就是新机正式量产的阶段&#xff0c;与之相关的外观和配置信息通常也会在这个时候被进一步曝光&#xff0c;所以不少果粉也对此保持着高度关注。如今&#xff0c;海外爆料博主E…

作者头像 李华
网站建设 2026/7/2 4:16:06

【毕业设计】基于 SpringBoot 的校园拾遗寻物互助系统的设计与实现 基于 SpringBoot 的大学生失物登记认领系统(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/7/2 4:12:06

DeepSeek V4多智能体协同实战:从可运行到可上线的工程化落地

1. 项目概述&#xff1a;这不是一次简单的模型调用&#xff0c;而是一场多智能体协同作业的实战压力测试“用我的多Agent协同Skill实测DeepSeek V4”——这个标题里藏着三个关键动作&#xff1a;“我的”强调私有化、可定制的技能体系&#xff1b;“多Agent协同”不是单个大模型…

作者头像 李华
网站建设 2026/7/2 4:11:05

北京一灯大师深耕车灯专项,以标准化施工赋能本地合规改灯

深耕北京汽车灯光升级领域多年&#xff0c;作为本地专注车灯专项服务的门店&#xff0c;我们深知京城车主对于车灯改装的核心诉求。不同于综合类汽修门店多品类兼顾的经营模式&#xff0c;我们长期聚焦汽车灯光升级、大灯维修、灯罩翻新、电路调试、专车解码等细分服务&#xf…

作者头像 李华