百度AI人脸识别与检测九:学生人脸识别打卡签到系统之学生相关信息查询

《百度AI人脸识别与检测》专栏为项目专栏,从零到一,从无到有开发一个学生人脸识别签到系统;主要用到的技术有百度开放平台中的人脸检测、人脸识别、Python图形界面开发PyQt5、线程的管理、以及通过python调用百度接口实现人脸检测、百度开放平台中人脸检测技术文档的理解等,由浅入深、由局部到整体的一个项目学习过程,如果你想对人脸识别感兴趣,对python的图形界面设计感兴趣,可以订阅本专栏,因为对你可能有帮助哦!

前文参考:

百度AI人脸识别与检测一:学生人脸识别签到系统简介及百度AI开放平台账号注册和人脸实例应用创建
百度AI人脸识别与检测二:学生人脸识别打卡签到系统主界面功能需求和设计以及通过Python实现界面运行
百度AI人脸识别与检测三:学生人脸识别打卡签到系统通过OpenCV实现电脑摄像头数据在Label控件上的实时显示
百度AI人脸识别与检测四:学生人脸识别打卡签到系统之百度AI人脸检测及相应程序异常处理
百度AI人脸识别与检测五:学生人脸识别打卡签到系统之百度AI人脸识别
百度AI人脸识别与检测六:学生人脸识别打卡签到系统之班级的增删查
百度AI人脸识别与检测七:学生人脸识别打卡签到系统之学生人脸信息的添加
百度AI人脸识别与检测八:学生人脸识别打卡签到系统之删除学生人脸及信息

上一章的内容我们完成了系统中学生人脸及有关信息的删除,在百度API文档的帮助之下,比较优秀的完成了“删除学生”模块的功能。在昨天对学生人脸搜索的基础之下,本章的内容便会变得非常的简单,需要完成的便是学生基本信息的查询,一起来看吧!



一、功能分析

1、功能的基本分析

学生有关信息查询的功能分析其实很简单,在了解API访问规则的前提之下,进行UI界面的创作,通过学生学号,查询出学生的姓名、所处的班级就是学生人脸识别打卡签到系统实现学生有关信息管理的目的。
借助PyQT5中的有关库的功能,就能够对该模块进行稳定的实现。


二、百度API文档详阅

1、百度AI开放平台该模块参考地址

百度AI开放平台API用户信息查询地址
在这里插入图片描述

2、请求规则

(1)、利用Python代码对百度AI发起请求的规则如下所示:


# encoding:utf-8

import requests

'''
用户信息查询
'''

request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/get"

params = "{"user_id":"user1","group_id":"group1"}"
access_token = '[调用鉴权接口获取的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:
    print (response.json())

(2)、访问参数说明
在以上的参数中,每个参数的具体说明如下所示:

  • user_id:学生学号
  • group_id:学生所在的班级,如传入“@ALL”则从所有组中查询用户信息,因此这里需要设置为“@ALL”

在这里插入图片描述

3、返回参数说明

(1)、返回的具体参数如下图所示:
在这里插入图片描述
其中,学生的相关信息在参数“user_info”中,也就是说,如果要获取学生的有关信息,我们需要从user_info中进行提取,而对于在那个班级,则对应“group_id”。
(2)、返回实例


{
  "user_list": [
      {
          "user_info": "user info ...",
          "group_id": "gid1"
      },
      {
          "user_info": "user info2 ...",
          "group_id": "gid2"
      }
  ]
}

以上的返回实例便是在请求规则的基础之上进行访问,并从百度AI开放平台中得到的数据结果。下面将以上的访问规则应用到学生人脸识别打开签到系统中的相关信息查询上面。


三、功能实现

功能实现包括两个部分,一个是功能代码的实现:对百度AI开放平台的人脸识别模块中的用户发送信息请求,然后接收,另一个部分则是软件中对该代码的调用,只有正确的调用,才能在没有bug的基础之上完成该模块!

1、学生信息查询功能代码编写

(1)、在function_window.py文件末尾编写方法名为search_student的函数,函数中的内容通过访问规则编写如下:

    #学生有关信息查询
    def search_student(self):
        # 打开输入框,进行输入用户组
        student_no, ret = QInputDialog.getText(self, "学生学号", "请输入学生学号")
        if student_no == "":
            return
        else:
            request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/get"
            params = {
                "user_id": student_no,
                "group_id": "@ALL"
            }
            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, "查询结果", "学生姓名:"+data["result"]["user_list"][0]["user_info"]+
                                      ",班级:"+data["result"]["user_list"][0]["group_id"])
                else:
                    QMessageBox.about(self, "查询结果", "暂无该生!")

(2)、在function_window.py文件的类中,对学生信息管理菜单栏中的“学生查找”按钮进行事件方法绑定,使得按钮可以完成该功能

self.actionfindStu.triggered.connect(self.search_student)  # 学生信息查询事件绑定

添加代码的位置如下所示:
在这里插入图片描述
通过以上两个步骤,学生信息查找的基本功能便做好了,下面一起看一下演示效果吧!

2、功能演示

(1)、运行程序,选择菜单栏中“学生查找”按钮,进行效果演示,在弹出的窗口中输入学生学号进行学生查询,如下所示:
在这里插入图片描述
(2)、查询成功如下图所示:

在这里插入图片描述
可以看出,在通过上面的步骤之后,学生信息的有关查询便实现了,本章节的主要内容就完成了。下面看一下本次模块的实现修改了那些文件中的代码吧!

3、修改后文件代码

(1)、在function_window.py文件中修改后的内容如下所示:

import base64

import cv2
import requests
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QInputDialog
from cameraVideo import camera
from mainWindow import Ui_MainWindow
from detect import detect_thread
from add_student_window import add_student_window
from del_student_window import del_student_window
class function_window(Ui_MainWindow,QMainWindow):
    '''
    初始化函数
    '''
    def __init__(self):
        super(function_window, self).__init__()
        self.setupUi(self)
        self.label.setScaledContents(True)#设置图像自适应label显示框
        self.pushButton.clicked.connect(self.open_Sign)#打开签到事件绑定
        self.pushButton_2.clicked.connect(self.close_Sign)#关闭签到事件绑定
        self.actionaddclass.triggered.connect(self.add_class)#添加班级按钮事件绑定
        self.actionfindclass.triggered.connect(self.display_class)#查询班级按钮事件绑定
        self.actiondelclass.triggered.connect(self.delete_calss)#删除班级按钮事件绑定
        self.actionaddStu.triggered.connect(self.add_student)#增加学生人脸信息事件绑定
        self.actiondelStu.triggered.connect(self.del_student)#删除学生人脸信息事件绑定
        self.actionfindStu.triggered.connect(self.search_student)  # 学生信息查询事件绑定
        self.access_token=self.get_accessToken()#获取Access_token访问令牌,并复制为全局变量
        self.start_state=True
    '''
        打开签到
    '''
    def open_Sign(self):
        if self.start_state==True:
            # 启动摄像头
            self.cameravideo = camera()
            # 启动定时器进行定时,每隔多长时间进行一次获取摄像头数据进行显示
            self.timeshow = QTimer(self)
            self.timeshow.start(10)
            # 每隔10毫秒产生一个信号timeout
            self.timeshow.timeout.connect(self.show_cameradata)
            self.detect = detect_thread(self.access_token)  # 创建线程
            self.detect.start()  # 启动线程
            # 签到500毫秒获取一次,用来获取检测的画面
            self.faceshow = QTimer(self)
            self.faceshow.start(500)
            self.faceshow.timeout.connect(self.get_cameradata)
            self.detect.transmit_data.connect(self.get_data)
            self.detect.transmit_data1.connect(self.get_seach_data)
            self.start_state=False
        else:
            QMessageBox.about(self, "提示", "正在检测,请先关闭!")

    '''
        关闭签到
    '''
    def close_Sign(self):
        if self.start_state==False:
            self.faceshow.stop()  # 计时器停止
            self.detect.ok = False  # 停止run函数运行
            self.detect.quit()  # 关闭线程
            # 关闭定时器,不再获取摄像头的数据
            self.timeshow.stop()
            self.timeshow.timeout.disconnect(self.show_cameradata)
            # 关闭摄像头
            self.cameravideo.colse_camera()
            self.start_state=True
            # 判断定时器是否关闭,关闭,则显示为自己设定的图像
            if self.timeshow.isActive() == False:
                self.label.setPixmap(QPixmap("image/1.jpg"))
                self.plainTextEdit_2.clear()
            else:
                QMessageBox.about(self, "警告", "关闭失败,存在部分没有关闭成功!")
        else:
            QMessageBox.about(self, "提示", "请先开始检测!")
    #获取人脸检测数据并显示到文本框中
    def get_data(self,data):
        if data['error_code']!=0:
            self.plainTextEdit_2.setPlainText(data['error_msg'])
            return
        elif data['error_msg'] == 'SUCCESS':
            self.plainTextEdit_2.clear()
            # 在data字典中键为result对应的值才是返回的检测结果
            face_num = data['result']['face_num']
            # print(face_num)
            if face_num == 0:
                self.plainTextEdit_2.setPlainText("当前没有人或人脸出现!")
                return
            else:
                self.plainTextEdit_2.clear()
                self.plainTextEdit_2.appendPlainText("检测到人脸!")
                self.plainTextEdit_2.appendPlainText("——————————————")
            # 人脸信息获取['result']['face_list']是列表,每个数据就是一个人脸信息,需要取出每个列表信息(0-i)
            for i in range(face_num):
                age = data['result']['face_list'][i]['age']  # 年龄
                # print(age)
                beauty = data['result']['face_list'][i]['beauty']  # 美观度
                gender = data['result']['face_list'][i]['gender']['type']  # 性别
                expression = data['result']['face_list'][i]['expression']['type']
                face_shape = data['result']['face_list'][i]['face_shape']['type']  # 脸型
                glasses = data['result']['face_list'][i]['glasses']['type']  # 是否戴眼镜
                emotion = data['result']['face_list'][i]['emotion']['type']  # 情绪
                mask = data['result']['face_list'][i]['mask']['type']  # 是否戴口罩
                # 往窗口中添加文本,参数就是需要的文本信息
                # print(age,gender,expression,beauty,face_shape,emotion,glasses,mask)
                self.plainTextEdit_2.appendPlainText("第" + str(i + 1) + "个学生人脸信息:")
                self.plainTextEdit_2.appendPlainText("——————————————")
                self.plainTextEdit_2.appendPlainText("年龄:" + str(age))
                if gender == 'male':
                    gender = "男"
                else:
                    gender = "女"
                self.plainTextEdit_2.appendPlainText("性别:" + str(gender))
                self.plainTextEdit_2.appendPlainText("表情:" + str(expression))
                self.plainTextEdit_2.appendPlainText("颜值分数:" + str(beauty))
                self.plainTextEdit_2.appendPlainText("脸型:" + str(face_shape))
                self.plainTextEdit_2.appendPlainText("情绪:" + str(emotion))
                if glasses == "none":
                    glasses="否"
                elif glasses == "common":
                    glasses="是:普通眼镜"
                else:
                    glasses="是:太阳镜"
                self.plainTextEdit_2.appendPlainText("是否佩戴眼镜:" + str(glasses))
                if mask == 0:
                    mask = "否"
                else:
                    mask = "是"
                self.plainTextEdit_2.appendPlainText("是否佩戴口罩:" + str(mask))
                self.plainTextEdit_2.appendPlainText("——————————————")
        else:
            print("人脸获取失败!")

    '''
        获取图像,并转换为base64格式
    '''
    def get_cameradata(self):
        camera_data1 = self.cameravideo.read_camera()
        # 把摄像头画面转化为一张图片,然后设置编码为base64编码
        _, enc = cv2.imencode('.jpg', camera_data1)
        base64_image = base64.b64encode(enc.tobytes())
        #产生信号,传递数据
        self.detect.get_imgdata(base64_image)
    '''
        摄像头数据显示
    '''
    def show_cameradata(self):
        #获取摄像头数据
        pic=self.cameravideo.camera_to_pic()
        #在lebel框中显示数据、显示画面
        self.label.setPixmap(pic)

    '''
        获取Access_token访问令牌
    '''
    def get_accessToken(self):

        # client_id 为官网获取的AK, client_secret 为官网获取的SK
        host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=TKGXdKC7WPWeADGHmFBN8xAr&client_secret=lsr1tAuxv3tRGmOgZTGgNyri667dfKGg'
        # 进行网络请求,使用get函数
        response = requests.get(host)
        if response:
            data = response.json()
            self.access_token = data['access_token']
            return self.access_token
        else:
            QMessageBox(self,"提示","请检查网络连接!")


    def get_seach_data(self,data):
        self.plainTextEdit.setPlainText(data)


    #添加班级
    def add_class(self):
        # 打开输入框,进行输入用户组
        group, ret = QInputDialog.getText(self, "添加班级", "请输入班级名称(由数字、字母、下划线组成)")
        if group == "":
            print("取消添加班级")
        else:
            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:
                print(response.json())
                message = response.json()
                if message['error_code'] == 0:#根据规则,返回0则为班级添加成功
                    QMessageBox.about(self, "班级创建结果", "班级创建成功")
                else:
                    QMessageBox.about(self, "班级创建结果", "班级创建失败")

    #班级查询
    def get_class(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()
    #将查询到的结果显示在MessageBOX框上面
    def display_class(self):
        list=self.get_class()
        str=''
        for i in list['result']['group_id_list']:
            str=str+'\n'+i
        QMessageBox.about(self,"班级列表",str)
    #班级删除
    def delete_calss(self):
        #打开输入框,进行输入用户组
        list = self.get_class()#首先获取用户组信息
        group,ret=QInputDialog.getText(self, "存在的班级", "班级信息"+str(list['result']['group_id_list']))
        if group == "":
            print("取消删除班级")
        else:
            request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/delete"

            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:
                print(response.json())
                message = response.json()
                if message['error_code'] == 0:
                    QMessageBox.about(self, "班级删除结果", "班级删除成功")
                else:
                    QMessageBox.about(self, "班级删除结果", "班级删除失败")
    #增加学生信息
    def add_student(self):
        '''
        人脸注册
        '''
        list=self.get_class()#获取班级,将班级信息传递到我们新建的界面之中
        # 创建一个窗口,进行用户信息录入
        window = add_student_window(list['result']['group_id_list'],self)#将获取到的班级传递到新的界面,后续有用
        #新创建窗口,通过exec()函数一直在执行,窗口不进行关闭
        window_status=window.exec_()
        #判断
        if window_status !=1:
            return
        base64_image = window.base64_image
        # 参数请求中,需要获取人脸编码,添加的组的id,添加的用户,新用户id信息
        request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add"

        params = {
            "image": base64_image,  # 人脸图片
            "image_type": "BASE64",  # 图片编码格式
            "group_id": window.class_id,  # 班级名称
            "user_id": window.student_id,  # 学生学号
            "user_info": window.student_name# 学生姓名
        }
        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, "增加结果", "学生增加失败!")
    #删除学生信息
    def del_student(self):
        list = self.get_class()#获取班级列表
        if list['error_msg'] == 'SUCCESS':
            window = del_student_window(list['result']['group_id_list'], self.access_token, self)
            # 新创建窗口,通过exec()函数一直在执行,窗口不进行关闭
            window_status = window.exec_()
            # 判断
            if window_status != 1:
                return
            class_name = window.class_name
            student_list = window.get_student_list(class_name)
            if student_list['error_msg'] == 'SUCCESS':
                student_no = window.student_no
                if student_no == "":
                    return
                for i in student_list['result']['user_id_list']:
                    if student_no == i:
                        face_list = self.user_face_list(class_name, student_no)
                        if face_list['error_msg'] == 'SUCCESS':
                            for i in face_list['result']['face_list']:
                                self.del_face_token(class_name, student_no, i['face_token'])
                        else:
                            return
                    else:
                        return
            else:
                return
        else:
            return
    #通过API访问规则,对学生人脸及有关信息进行删除
    def del_face_token(self,class_name,student_no,facetoken):
        request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/face/delete"
        params = {
            "user_id":student_no,
            "group_id":class_name,
            "face_token":facetoken
        }
        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,"删除状态","学生人脸及信息删除失败!")

    # 获取用户人脸列表
    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 search_student(self):
        # 打开输入框,进行输入用户组
        student_no, ret = QInputDialog.getText(self, "学生学号", "请输入学生学号")
        if student_no == "":
            return
        else:
            request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/get"
            params = {
                "user_id": student_no,
                "group_id": "@ALL"
            }
            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, "查询结果", "学生姓名:"+data["result"]["user_list"][0]["user_info"]+
                                      ",班级:"+data["result"]["user_list"][0]["group_id"])
                else:
                    QMessageBox.about(self, "查询结果", "暂无该生!")

到这里,本章的内容就结束了,希望通过对本章内容的阅读,可以帮助小伙伴更好的了解如何运用百度AI开放平台来实现自己项目中的某些功能,同时,学习Python的有关语法,完成对自我的提升,本章内容还是很简单哇!


以上就是本次博客的全部内容,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷!

工作单位培训的第四天,入职培训逐渐接近尾声,对公司的了解更深,学习到的东西也很多,在这里感谢自己孜孜不倦的学习,同时也感谢授课老师,培训策划的有关人员,因为有你们,这个入职体验很完美!

陈一月的又一天编程岁月^ _ ^

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陈一月的编程岁月

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

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

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

打赏作者

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

抵扣说明:

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

余额充值