JDG人脸识别课堂管理系统全栈开发流程报告-软件工程
⭐️ 本报告的代码部分和程序设计参考了 计算机18-1班张宇哲(学号181002406)同学 在Gitee仓库发布的AI-Attendance,本文档基于软件工程的具体流程,从软件工程的角度细化的张同学的项目,不关注代码,只关注一套相对完整的软工流程。
❤️ 高润 + 姜宇晨 + 丁纪翔 ❤️ | 时间有限,还有诸多问题,欢迎指正!
可行性分析
随着在线教学的不断完善、信息技术的高速普及,人们对于使用信息技术进行在线课堂教学的要求越来越高。为了保证大学生课堂的出勤率及学生信息的管理,大部分学校选择采取签到的措施。而课堂签到一直以来是师生的痛点问题,手工方式签到费时费力。因此,师生迫切需要一个可行的、高效的签到系统。同时,传统的签到方式具有复杂、繁琐的特点,而使用人脸识别进行签到,是目前较好的解决方案。
项目背景
-
开发软件名称:JDG人脸识别课堂管理系统
-
项目开发者:
- 姜宇晨(1925102018)
- 高润(1925101007)
- 丁纪翔(1925102007)
-
用户:高校的学生和老师
-
软件开发动机:
大学里存在许多旷课现象,因为课堂学生人数越来越多,老师点名耗费的精力和时间也随之增加,老师为节约时间,只好采取抽样点名的方法,有时甚至不点名。在这种情况下,学生难免出现不自律、旷课的行为,影响了学生的学习成绩。现有的点名平台并不能避免同学之间代签到的现象,因此我们开发的JDG人脸识别课堂管理系统,只进行人脸识别签到,需要满足效率高、准确性强且无法作弊的需求。
项目组织
- 高润:可行性分析、需求分析与设计
- 姜宇晨:原型设计、软件开发
- 丁纪翔:测试调试、维护管理
现有系统的局限性
-
学习通
-
功能冗余,且没有人脸识别签到功能,定位签到虽然可以一定程度上减少学生不来教室就签到的可能性,但是会发生同学进行代签的情况
-
界面设计简陋,且功能不易寻找,这也是太多不必要的功能的存在带来的结果
-
-
QQ群接龙
- 方便快捷但无法确保学生真实出勤
要求与目标
对所建议系统的说明
- 用户添加
- 用户登录
- 学生可上传照片
- 管理员审核照片
- 老师创建课程,学生加入课程
- 老师发起签到
- 学生进行人脸识别签到
- 学生查看课程列表及自己的出勤情况
- 老师得到出勤情况的统计表
改进之处
- 界面简洁美观
- 没有冗余功能,方便快速进行签到
- 人脸识别提高了签到的真实性,一定程度上避免了学生在签到上作弊的情况
- 老师可以一键导出出勤情况表,方便老师进行存档记录
影响
- 减少老师点名耗费的时间,老师可将更多的时间用在课堂内容上
- 一定程度上减少学生旷课的情况,能提高学习成绩
- 提高学生签到的真实性,一定程度上避免学生之间互相代签到的情况
- 系统基于Chrome浏览器做适配,同时支持所有主流浏览器,不会对学生和老师的操作造成影响
局限性
- 缺乏实际课堂的测试
- 人脸识别的准确度还未进行调整优化,人脸识别模型可能出现过饱和和欠饱和的缺陷,导致同一个学生在不同时间签到的结果不同
- 功能简单,但无法进行课堂互动,如回答问题的加分等
技术可行性分析
技术基础
-
OpenCV, Dlib
人脸检测和识别的开源库 -
CNN, RNN, k-NN
人脸特征提取和分类算法
-
MySQL
数据存储的数据库 -
LayUI、Bootstrap
系统的前端框架,易用性强,简单易学
-
Spring Boot
系统的后端框架,使系统具有更好的可扩展性。使用到的依赖注入、面向对象方法都让整个程序更容易维护和扩展。 -
墨刀
项目原型设计
-
Apache Tomcat
系统的应用服务器 -
Nginx
开源、高性能、高可靠的 Web 和反向代理服务器,支持热部署
人员基础
项目组的三位成员都有一定的开发基础,对本项目的开发环境较为熟悉,具备研发该项目的能力。
投资及效益分析
支出
- 开发人员的研究经费
- 服务器租用费用
- 保障本系统运行与信息安全设备的使用费用
效益
- 开支缩减:本人脸识别课堂管理系统除了必要的功能外,尽可能减少不必要的功能,以减少能源损耗,降低错误的发生率,软件存在高度地可改进空间,提高了用户操作的效率;
- 价值提升:通过本系统的研发工作,项目组三位成员收获良多,不仅实现了系统的开发任务,还完成了一整套软件的开发流程。
结论
综上所述,该项目是可行的,可以按照计划进行项目开发。
需求分析
我们和老师、学生进行了交流对话,在调研阶段,设计了调查问卷,获取了需求,进而对需求进行分析与综合,得到了系统的解决方案和目标系统的详细逻辑模型。
需求获取
功能性需求
-
学生/老师/管理员的添加和登录
-
学生:照片提交、加入课程、人脸识别签到
-
老师:创建课程、发起签到、查看签到统计结果
-
管理员:审核学生照片、添加学生/老师账号
非功能性需求
性能需求
- 响应速度:要求每个页面在3秒内得到响应
- 数据库约束的完整性:数据库应当满足第三范式,即通过外键约束严格保证数据的完整性。对于带有外键约束的修改,必须在满足完整性的前提下进行修改
环境需求
- 签到平台需要连接网络
- 尽量使用chrome浏览器、Safari浏览器、火狐浏览器等主流浏览器
可靠性需求
- 人脸特征提取模型的精度不能设定过高,防止因妆容、光线等情况干扰识别的正确率
- 上传照片自动压缩,确保传输的速度和稳定性
安全性需求
- 服务器的安全性需要得到保证,避免学生和老师信息的泄露
- 为了防止密码泄露,不能使用明文存储和传输密码,应采用MD5加密方法进行加密
- 要求使用日志记录所有操作。日志按日存储,至少保存30天
- 为防止介质故障,需要对于数据库进行备份。至少在两个地方进行备份,每个月更新一次备份
用户界面需求
- 制作简洁、美观的用户界面,用户可以轻松找到功能,易用性很好
需求分析与建模
对所提需求进行分析与综合,具体描述了各个需求,制定了系统的解决方案,得到了目标系统的详细逻辑模型。
开发进度需求分析
根据可行性需求中提出的开发进度,我们制定了项目开发计划。
- 2021.11.05 项目提出
- 2021.11.06 完成可行性研究与撰写项目开发计划
- 2021.11.08 完成需求分析和结构化分析
- 2021.11.11 完成结构化设计与数据库结构设计
- 2021.11.13 软件编程实现了项目
- 2021.11.15 完成单元测试与集成测试
- 2021.11.17 编写用户手册与课程汇报
功能性分析
管理员
- 教师和学生账号的分配,进行学生、教师密码的管理
- 学生照片的审核和退回。如果学生的人脸照片不符合要求,那么有权退回并通知学生
老师
- 课程的创建
- 生成课程码,邀请学生加入
- 进入某个课程后可以发起发起点名
- 可以实时查看点名列表
- 可以选择课程结束
- 可以在课程结束后生成签到报告,查看学生总签到情况
学生
- 上传人脸照片并交给系统管理员审核
- 通过课程码加入课堂
- 进入课程后进行人脸签到
- 获取人脸签到的结果
结构化分析
结构化分析采用“自顶向下,逐层分解”的思想,由于系统规模较少,所以只将数据流图分为三层,分别是顶层、中层和底层。数据字典分为了五个部分,分别是数据流、数据项、数据存储、数据加工、实体数据。
数据流图与数据字典
系统的顶层数据流图与数据字典
(1)顶层图的数据字典
(1.1)数据流
学生信息={姓名+密码}
老师信息={姓名+密码}
课程信息(老师):课程名+任课教师编号
课程信息(学生):课程名+任课老师姓名
签到信息:课程号+签到结束时间
学生照片={学号+图片数据}
人脸识别签到信息:学号+课程码+签到id+图片数据
照片审核结果:审核状态+备注
课程码:7{数字}7
考勤结果:[考勤成功|考勤失败]
签到结果:[签到成功|签到失败]
照片审核结果:[审核通过|审核未通过]
(1.2)数据项
学生学号:10{数字}10
老师编号:6{数字}6
签到id:9{数字}9
管理员账号:3{数字}3
姓名:2{汉字}4
备注:1{字符}100
课程名:1{字符}30
签到结束时间:日期+时间
审核状态:[审核通过|审核未通过]
密码:8{[数字|字母|英文符号]}20
数据元素名称:图片数据
类型:二进制数据
长度:0~10MB
说明:图片实际储存在硬盘中,数据库中只保存图片的存储地址
(1.3)外部实体
学生={学号+姓名}
老师={编号+姓名}
管理员={管理员账号}
系统的中层数据流图与数据字典
(2)中层图的数据字典
(2.1)数据流
课程码:7{数字}7
学生照片:学号+图片数据
学生信息={学号+姓名+密码}
老师信息={编号+姓名+密码}
签到统计信息={学生姓名+[已签到|未签到]}
课程信息(学生查询):课程名+任课老师姓名
课程信息(创建课程):课程码+课程名+任课教师编号
课程信息(老师提供):课程名+任课教师编号
签到信息:课程号+签到结束时间
学生签到记录:学号+签到id
照片特征:学号+特征向量
签到结果:[签到成功|签到失败]
审核结果:[审核通过|审核未通过]
(2.2)数据项
学生学号:10{数字}10
老师编号:6{数字}6
管理员账号:3{数字}3
签到id:9{数字}9
姓名:2{汉字}4
备注:1{字符}100
课程名:1{字符}30
签到结束时间:日期+时间
审核状态:[审核通过|审核未通过]
密码:8{[数字|字母|英文符号]}20
特征向量:通过神经网络输出的人脸的128维特征向量
数据元素名称:图片数据
类型:二进制数据
长度:0~10MB
说明:图片实际储存在硬盘中,数据库中只保存图片的存储地址
(2.3)数据存储
学生名单={学号+姓名+密码}
老师名单={编号+姓名+密码}
课程信息={课程码+课程名+任课教师编号}
课程学生记录={课程码+学号}
签到信息库={签到id+课程号+签到结束时间}
学生签到记录={签到id+学号}
照片库={学号+特征向量}
(2.4)数据加工
信息上传:分配学生学号和老师编号
创建课程:分配课程码
签到发起:分配签到id
签到统计:获取课程学生记录和学生签到记录,筛选未签到同学的信息
照片审核:审核未成功的照片删除,反之,CNN处理得到128维照片特征
(2.5)外部实体
学生={学号+姓名}
老师={编号+姓名}
管理员={管理员账号}
学生签到底层数据流图与数据字典
(3)学生签到底层图的数据字典
(3.1)数据流
学生账号密码:学号+密码
上传照片:学号+学生照片
签到信息=签到id+学号
签到结果:[成功|失败]
签到通知={签到id+课程码+课程名称+任课老师}
(3.2)数据项
姓名:2{汉字}4
课程码:7{数字}7
签到id:9{数字}9
学生学号:10{数字}10
签到结束时间:日期+时间
密码:8{[数字|字母|英文符号]}20
特征向量:通过神经网络输出的人脸的128维特征向量
数据元素名称:学生照片
类型:二进制数据
长度:0~10MB
说明:图片实际储存在硬盘中,数据库中只保存图片的存储地址
(3.3)数据存储
学生名单={学号+姓名+密码}
签到信息库={签到id+课程码+签到结束时间}
照片库={学号+特征向量}
学生签到记录={签到id+学号}
(3.4)数据加工
登录系统:比对学生学号对应的密码是否和学生名单中保存的密码相同,则登录成功,否则登录失败
接收签到通知:寻找签到信息库中签到未结束的签到id,在学生签到记录中查找该学生是否已签到
生成照片特征码:利用CNN生成人脸128维特征向量
特征比对:利用分类算法为特征分类,比较二者对应学号是否相同,相同则识别成功,反之,失败
(3.5)外部实体
学生={学号+姓名}
信息上传底层数据流图与数据字典
(4)信息上传底层图的数据字典
(4.1)数据流
管理员:管理员账号+密码
管理员信息:{管理员账号+密码}
学生名单={姓名+密码}
老师名单={姓名+密码}
学生信息={学号+姓名+密码}
老师信息={编号+姓名+密码}
(4.2)数据项
姓名:2{汉字}4
管理员账号:3{数字}3
学生学号:10{数字}10
老师编号:6{数字}6
密码:8{[数字|字母|英文符号]}20
(4.3)数据存储
管理员名单={管理员账号+密码}
学生名单={学号+姓名+密码}
老师名单={编号+姓名+密码}
(4.4)数据加工
登录系统:比对管理员账号对应的密码是否和管理员名单中保存的密码相同,则登录成功,否则登录失败
名单检查:检查名单中的各数据项格式是否合法,输出非法名单
学号分配:分配学生的学号
老师编号分配:分配老师的编号
(4.5)外部实体
管理员={管理员账号}
某门课程的学生状态转换图
系统结构化设计
结构化概要设计
系统结构图
具有边界的中层DFD图
系统的结构图
根据具有边界的中层数据流图,我们得到了系统的结构图。
优化的系统结构图
根据信息上传和学生签到底层数据流图,我们优化了上述系统的结构图。
信息上传模块的结构图
根据信息上传和底层数据流图,我们绘制了信息上传模块的结构图。由底层数据流图可知,信息上传模块是以事务调度为核心的,是事务型的处理模块。
结构化详细设计
签到通知程序的流程图
签到通知程序的N-S图
我们将签到通知程序的流程图转换为了N-S图,使得模块间嵌套关系和层次关系得到更好地体现,思路清晰,结构良好,易于设计。
数据库设计
数据库的所有表单
各个表的结构
数据库代码(可迁移)
为了实现数据库的迁移,所以我们给出了数据库创建的代码。
-- phpMyAdmin SQL Dump
-- version phpStudy 2014
-- http://www.phpmyadmin.net
-- 主机: localhost
-- 服务器版本: 5.5.53
-- PHP 版本: 5.4.45
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
--
-- 数据库: `jdg`
--
-- --------------------------------------------------------
--
-- 表的结构 `admin`
--
CREATE TABLE IF NOT EXISTS `admin` (
`account` char(3) NOT NULL COMMENT '管理员账号',
`password` varchar(20) NOT NULL COMMENT '管理员密码',
PRIMARY KEY (`account`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统管理员';
-- --------------------------------------------------------
--
-- 表的结构 `canyu`
--
CREATE TABLE IF NOT EXISTS `canyu` (
`daka_id` char(9) NOT NULL COMMENT '签到ID',
`id` char(10) NOT NULL COMMENT '学号',
PRIMARY KEY (`daka_id`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='参与表';
-- --------------------------------------------------------
--
-- 表的结构 `chos_course`
--
CREATE TABLE IF NOT EXISTS `chos_course` (
`course_id` char(6) NOT NULL COMMENT '课程码',
`id` char(10) NOT NULL COMMENT '学号',
PRIMARY KEY (`course_id`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='选修表';
-- --------------------------------------------------------
--
-- 表的结构 `course`
--
CREATE TABLE IF NOT EXISTS `course` (
`course_id` char(6) NOT NULL COMMENT '课程码',
`course_name` varchar(30) NOT NULL COMMENT '课程名',
`teacher_id` char(6) NOT NULL COMMENT '教师编号',
PRIMARY KEY (`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='课程表';
-- --------------------------------------------------------
--
-- 表的结构 `daka`
--
CREATE TABLE IF NOT EXISTS `daka` (
`daka_id` char(9) NOT NULL COMMENT '签到ID',
`course_id` char(6) NOT NULL COMMENT '课程码',
`end_time` datetime NOT NULL COMMENT '结束时间',
PRIMARY KEY (`daka_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='签到表';
-- --------------------------------------------------------
--
-- 表的结构 `student`
--
CREATE TABLE IF NOT EXISTS `student` (
`id` char(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '学生学号,唯一',
`name` varchar(4) NOT NULL COMMENT '学生姓名',
`password` varchar(20) NOT NULL COMMENT '密码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='学生表';
-- --------------------------------------------------------
--
-- 表的结构 `student_photo`
--
CREATE TABLE IF NOT EXISTS `student_photo` (
`id` char(10) NOT NULL COMMENT '学生学号,唯一',
`tezhengxl` char(128) NOT NULL COMMENT '128维特征向量',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='学生照片';
-- --------------------------------------------------------
--
-- 表的结构 `teacher`
--
CREATE TABLE IF NOT EXISTS `teacher` (
`teacher_id` char(6) NOT NULL COMMENT '教师编号',
`name` varchar(4) NOT NULL COMMENT '教师姓名',
`password` varchar(20) NOT NULL COMMENT '密码',
PRIMARY KEY (`teacher_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='教师表';
面向对象分析与设计
UML用例图
原型设计与软件实现
原型设计
老师功能
用户登录
此功能需要编写对应的pojo、mappers、controller。
教师功能页
构造pojo类、Dao类、Service类并编写对应的Mapper。使用GetCourse.do查看自己的课程:设置按钮可以添加课程,使用addCourse.do实现。还要实现添加学生功能,通过将学生加入,形成了完整的课程列表。
课程创建
课程添加学生
教师可以添加学生到课程中。通过点击添加学生,并输入studentid,即可添加学生进去。
发起签到
通过发起签到,可以发起一次签到给学生,之后学生就可以进行签到了。教师发起签到以后,会添加一个check记录进入系统,学生进入系统即可查看到。
学生功能
学生上传照片
要求学生进入学生界面,可以上传自己的照片到后台数据库。如果想要打回,直接从后台删除,重新上传即可。
学生查看待签到列表
学生默认什么都看不到,学生需要输入签到ID,搜索之后才能看到这个签到记录。这个ID需要通过教师那里获取,一方面保证了同学一定在线。搜索之后方可查询到对应的签到记录,并且提供了进入签到的入口。点击该入口即可进行签到。
人脸识别签到
点击进入签到,即可完成调用摄像头,并提交签到。
软件实现
建立项目
采用Lay-UI的框架,进行导入。默认带了一些页面。
验证码模块实现
在RandomValidateCode.java中实现。
软件测试
我们首先进行了代码的走查,由高润、丁纪翔负责对姜宇晨编写的代码进行评价,发现代码潜在的问题。接着着重测试了系统中的每个单独的模块,以确保它作为一个单元来说功能是正确的。我们在单元测试中,主要采用白盒测试,以闰年检测模块的单元测试为例。在所有单元测试完毕后,我们就开始进行集成测试,集成测试中主要使用黑盒测试方法,采用自底向上的增量式集成测试方法,避免了开发大量桩模块,减少开发成本,测试效率得到提升。
代码走查
由高润、丁纪翔负责对姜宇晨编写的代码进行评价,发现代码潜在的问题,并进行更正。
程序结构
- 所有主要的数据构造描述清楚,合理
- 结构设计能够满足机能变更
函数组织
- 所有的变量声明每行只声明一个
- 函数名少于64个字符
代码结构
- 每行代码都少于80个字符
- 所有的变量名都少于32个字符
- 注释在代码中的位置不太好,不够清晰明了
数据类型与变量
- 程序没有使用特别的、易误解的、发音相似的命名
- 数据结构简单以便降低复杂性
循环
- 循环体不为空
- 代码不存在无穷次循环
输入输出
- 显示的文本无拼写和语法错误
注释
- 注释不清楚,部分主要的语句没有注释
- 看到代码不一定能快速明确其意义
闰年检测模块的单元测试
老师发起签到时,要对签到设置的日期进行检验,检查输入的日期信息是否正确。而输入日期中的“日”在闰年2月时有29天,非闰年2月时有28天。因此,想要检测“日”是否正确,就必须要判断“月”是否是闰年2月。
闰年检测模块实现代码
int IsLeap(int year) {
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 4 == 0)
leap = 1;
else
leap = 0;
}
else
leap = 1;
}
else
leap = 0;
return leap;
}
对闰年检测模块使用基本路径法进行白盒测试。首先通过IsLeap函数的代码,绘制了程序的流程图,进而绘制出如下控制流图G。
闰年检测模块的控制流程图
在闰年检测模块的控制流图G中,环路复杂度环路复杂度V(G)=P+1=3+1=4,P为图G中判定节点的数目。环路复杂度决定了线性无关的路径的条数,即测试用例最少需要覆盖的图G中的路径的条数。接着,我们设计了覆盖所有4条线性无关路径的测试用例,对InLeap模块进行测试。
基于基本路径覆盖法的闰年检测模块的测试用例设计
日期合法性检验模块的集成测试
由结构图可知,日期合法性检验模块集成了闰年检测模块。我们已经对闰年检测模块进行了单元测试,并无问题出现。
集成测试采用自底向上的增量式集成测试方法,避免了桩模块的开发。而且,本项目真正涉及复杂逻辑功能操作的模块多位于底层结构中,所以,采用“自底而上的增量式”能够从最有可能出错的模块开始测试,减少了回测成本,还提高了集成测试的效率,支持故障隔离。日期合法性检验模块由签到发起模块驱动,所以首先设计了该模块的驱动模块“D签到发起”。
对合法性检验模块的集成测试以黑盒测试形式进行,使用等价类划分法。将输入的年、月、日进行等价类划分,从每个等价类中任意挑选一个进行测试用例设计。
等价类划分
有效等价类测试用例设计
从上述等价类划分表的有效等价类中,选择能够覆盖年月、日的所有四种组合的测试用例。在实际开发中,往往大量的错误都发生在输入的边界值上,因此我们使用边界值分析法,对有效等价类的测试用例进行了补充,得到如下有效等价类测试用例设计表。
无效等价类测试用例设计
无效等价类测试用例设计中,也结合了边界值分析法的思想。
项目部署
完成系统的本地测试后,由经验丰富的项目组成员高润进行项目部署。目标是在Ubuntu系统上使用Apache Tomcat部署项目,配置Nginx反向代理。
参考文献
[1] 吕云翔. 软件工程:理论与实践[M]. 北京: 人民邮电出版社, 2018.5
[2] 刘竹林, 王素贞. 软件工程实践与项目管理[M]. 西安: 西安电子科技大学出版社, 2010.7