基于人脸识别的课堂签到管理系统
工程项目:基于人脸识别的课堂签到管理系统
分为:三个阶段
1.定义阶段
可行性分析
技术可行性
成本可行性:自底向上估价
开发评估成本
开发的时间周期,开发的人力
10天 3-4人
收益评估成本
需求分析:
a、摄像头进行人脸检测
b、人脸比对判断
c、人脸库
d、人脸库添加、删除
e、数据库保存
f、导出签到数据
2.开发阶段
概要设计:规定接口,模块功能的组成
详细设计:对每一个功能的实现流程进行设计
实现:对详细设计的功能进行代码实现
测试 :测试功能的正确性,稳定性
3.运行维护阶段
交付客户,上线运营
维护软件正常工作运行状态,进行版本更新
采用pyqt5作为界面开发
1、设计界面程序
pyqt5designer.exe打开ui界面设计工具,进行界面设计
a、创建项目,选择对应的虚拟解释环境
b、使用qt的工具,创建一个界面
在下方找到terminal—》pyqt5deisgner.exe
qt的界面设计
c、把界面UI文件添加到项目中,作为项目文件
d、把ui界面转换成python文件的界面程序
python只会解释.py文件,在项目中就不认识.ui
需要把.ui转换成.py
pyuic5 源UI文件.ui -o 目标文件.py
e、创建一个新的类,继承ui类与基础界面类
在新的类中既有设计的ui类中的界面内容,也有基础界面类(窗口类)显示等操作
能够实现管理学生人脸签到的系统
分析:
关键代码:
def detect_face(self, base64_image):
# 发送请求的地址
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"
# 请求参数是一个字典,在字典中存储了,百度AI要识别的图片信息,要识别的属性内容
params = {
"image": base64_image, # 图片信息字符串
"image_type": "BASE64", # 图片信息的格式
"face_field": "gender,age,beauty,expression,face_shape,glasses,emotion,mask", # 请求识别人脸的属性,各个属性在字符串中用','逗号隔开
"max_face_num": 10,
}
# 访问令牌
access_token = self.access_token
# 把请求地址和访问令牌组成可用的网络请求地址
request_url = request_url + "?access_token=" + access_token
# 参数,设置请求的格式体
headers = {
'content-type': 'application/json'}
# 发送网络post请求,请求百度AI进行人脸检测,返回检测结果
# 发送网络请求,就会等待一段时间,程序就在这里阻塞执行
response = requests.post(request_url, data=params, headers=headers)
if response:
data = response.json()
if data['error_code'] != 0:
self.transmit_data.emit(data)
self.search_data.emit(data['error_msg'])
return
if data['result']['face_num'] > 0:
self.transmit_data.emit(dict(data))
self.face_search()
通过百度API返回人脸的一些信息
关键代码:
def face_search(self):
list = self.getlist()
grouplist = list[‘result’][‘group_id_list’]
request_url = “https://aip.baidubce.com/rest/2.0/face/v3/search”
params = {
“image”: self.base64_image,
“image_type”: “BASE64”,
“group_id_list”: “class3” # 从哪些组中进行人脸识别
}
access_token = self.access_token
request_url = request_url + “?access_token=” + access_token
headers = {‘content-type’: ‘application/json’}
response = requests.post(request_url, data=params, headers=headers)
if response:
data = response.json()
if data[‘error_code’] == 0:
if data[‘result’][‘user_list’][0][‘score’] > 90:
# -------显示到窗口------- #
# 存储要保存的签到数据,方便进行显示
del(data['result']['user_list'][0]['score'])
datetime = QDateTime.currentDateTime()
datetime = datetime.toString()
data['result']['user_list'][0]['datetime'] = datetime
key = data['result']['user_list'][0]['group_id'] + data['result']['user_list'][0]['user_id']
if key not in self.sign_list.keys():
self.sign_list[key] = data['result']['user_list'][0]
print(self.sign_list[key])
group1 = self.sign_list[key]['group_id']
user_id = self.sign_list[key]['user_id']
name = self.sign_list[key]['user_info'][5:9]
time = self.sign_list[key]['datetime']
self.insert_stu(user_id, name, group1, time)
# ---------------------- #
self.search_data.emit("签到成功\n学生信息:\n"+data['result']['user_list'][0]['user_info'])
else:
self.search_data.emit("未注册人脸信息")
通过调用百度人脸识别的API搜索比对人脸库里已经录入的人脸信息,根据匹配程度返回识别结果,成功返回为签到成功并输出人脸信息
关键代码:
def add_group(self):
# 打开对话框,进行输出用户组
group, ret = QInputDialog.getText(self, "添加用户组", "输入用户组(由数字、字母、下划线组成)")
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/add"
params = {
"group_id": group
}
access_token = self.access_token
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
message = response.json()
if message['error_code'] == 0:
QMessageBox.about(self, "用户组创建结果", "用户组创建成功")
else:
QMessageBox.about(self, "用户组创建结果", "用户组创建失败" + message['error_msg'])
# 删除用户组
def del_group(self):
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/delete"
# 删除,需要知道存在哪些组
list = self.getlist()
group, ret = QInputDialog.getText(self, "存在的用户组", "用户组信息\n"+str(list['result']['group_id_list']))
params = {
"group_id": group # 要删除的用户组的ID
}
access_token = self.access_token
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
data = response.json()
if data['error_code'] == 0:
QMessageBox.about(self, "用户组删除结果", "用户组删除成功")
else:
QMessageBox.about(self, "用户组删除结果", "用户组删除失败" + data['error_msg'])
# 获取用户组信息
def getlist(self):
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/getlist"
params = {
"start": 0,
"length": 100
}
access_token = self.access_token
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
return response.json()
# 获取用户组列表并显示
def getgrouplist(self):
list = self.getlist()
str = ''
for i in list['result']['group_id_list']:
str = str + '\n' + i
QMessageBox.about(self, "用户组列表", str)
实现效果:
关键代码:
def show_grouplist(self, list):
for i in list:
self.listWidget.addItem(i)
def get_user(self):
self.listWidget_2.clear()
self.listWidget_3.clear()
group = self.listWidget.currentItem().text()
list = self.getuserlist(group)
# print(list['result']['user_id_list'])
for i in list['result']['user_id_list']:
self.listWidget_2.addItem(i)
def get_facetoken(self):
self.listWidget_3.clear()
group = self.listWidget.currentItem().text()
user = self.listWidget_2.currentItem().text()
face_list = self.user_face_list(group, user)
for i in face_list['result']['face_list']:
self.listWidget_3.addItem(i['face_token'])
# 获取用户列表
def getuserlist(self, group):
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/getusers"
params = {
"group_id": group
}
access_token = self.access_token
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
return response.json()
# 删除用户中的一张人脸信息(face_token)
def del_face_token(self, group, user, face_token):
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/face/delete"
params = {
"user_id": user,
"group_id": group,
"face_token": face_token
}
access_token = self.access_token
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
data = response.json()
if data['error_code'] == 0:
QMessageBox.about(self, "人脸删除结果", "人脸删除成功")
else:
QMessageBox.about(self, "人脸删除结果", "人脸删除失败" + data['error_msg'])
#获取用户人脸列表
def user_face_list(self, group, user):
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/face/getlist"
params = {
"user_id": user,
"group_id": group
}
access_token = self.access_token
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/json'}
response = requests.post(request_url, data=params, headers=headers)
if response:
return response.json()
def get_ok(self):
group = self.listWidget.currentItem().text()
user = self.listWidget_2.currentItem().text()
face_token = self.listWidget_3.currentItem().text()
self.del_face_token(group, user, face_token)
关键代码:
def insert_stu(self, user_id, name, group1, time):
conn = sqlite3.connect('student.db')
c = conn.cursor()
data = (user_id, name, group1, time) # or ['love2', 2221]
sql = "INSERT INTO Student(id, name, class, datatime) VALUES(?, ?, ?, ?)"
c.execute(sql, data)
conn.commit()
conn.close()
关键代码:
def get_ok(self):
# 传入数据库路径
conn = sqlite3.connect('student.db')
c = conn.cursor()
mysel = c.execute("select * from student")
filepath, ret = QFileDialog.getSaveFileName(self, "导出数据", ".", "Excel文件(*.xls)\n文本文件(*.txt)")
path = filepath[-3:]
if path == 'xls':
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet("签到数据")
for i, row in enumerate(mysel):
for j, value in enumerate(row):
worksheet.write(i, j, value)
workbook.save(filepath)
elif path == 'txt':
f = open(filepath, mode='w') # 打开文件,若文件不存在系统自动创建
f.writelines(['学号\t\t', '姓名\t', '班级\t\t', '签到时间\n'])
for i, row in enumerate(mysel):
for j, value in enumerate(row):
data = value.split('\n')
f.write(str(data[0]) + '\t')
f.write('\n')
f.close() # 关闭文件
if QMessageBox.question(self, "完成", "文件已经导出,是否现在打开?", QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok:
QDesktopServices.openUrl(QUrl("file:///" + QDir.toNativeSeparators(filepath)))