人脸识别打卡项目(7)

目录

变量初始化

连接数据库

1. 数据库连接

2. 创建数据表

3. 查询数据

获取Access Token

图片编码

百度AI接口调用

1. 人脸质量检测

2. 人脸注册

3. 人脸搜索

4. 人脸删除

人脸跟踪

 功能验证

1.注册人脸

2. 打卡

3. 查看打卡信息

 4. 人脸删除

总结


变量初始化

在定义好GUI主体界面各模块后,需要对项目中用到的变量进行初始化;

代码实现如下,在类中的初始化模块,添加初始化变量代码:

import wx

class Face_recognition(wx.Frame):
    
    def init (self):
        self.frame = wx.Frame. init (self, parent=None, title="员工考勤系统",
        size=(1000, 700))
        self.initMenu()
        self.init_data() # 此处添加初始化变量代码

然后在类中初始化菜单的方法initMenu() 后面添加实现变量初始化的方法init_data() ;

    def init_data(self):
        self.on = True  # 注册标识变量
        self.reg_msg = None  # 注册时显示信息
        self.del_msg = None  # 删除时显示信息
        self.search_msg = None  # 查询时显示信息
        self.command = None  # 当前执行的命令
        self.sql_name = 'my_Punch.db'  # 数据库名字
        self.recognize = True  # 打卡
        self.registration = False  # 注册
        self.search = True  # 查询
        self.c = None  # 定义游标
        self.conn = None  # 连接名
        self.user_id = []  # 用户ID
        self.user_name = []  # 用户名
        self.time_1 = []  # 上班时间
        self.logcat_late = []  # 打卡时间
        self.time_2 = []  # 下班时间
        self.dur_time = []  # 持续时间

连接数据库

1. 数据库连接

在类中实现用于连接数据库的方法connect_sql ,在init_data()

""" 数据库连接
"""

import sqlite3

def connect_sql(self):
    conn = sqlite3.connect(self.sql_name)
    print("Opened database successfully!")
    c = conn.cursor()
    self.c = c
    self.conn = conn

2. 创建数据表

在类中实现创建数据表的方法create_table ,在connect_sql() 下方写入如下代码:

"""
创建数据表
"""

    def create_table(self):
        c, conn = self.c, self.conn
        c.execute('''CREATE TABLE if not exists attendance
	           (user_id CHAR(50) PRIMARY KEY     NOT NULL,
	           user_name      CHAR(50)    NOT NULL,
	           sign_in_time Datetime,
	           checking_state  CHAR(10) NOT NULL,
	           sign_out_time Datetime,
	           working_time float);''')
        conn.commit()

3. 查询数据

在类中实现查询数据的方法Query_data ,在create_table() 下方写入如下代码:

"""
    查询数据库中的数据
"""

    def Query_data(self):
        self.user_id = []
        self.user_name = []
        self.time_1 = []
        self.logcat_late = []
        self.time_2 = []
        self.dur_time = []
        self.connect_sql()
        self.create_table()
        c, conn = self.c, self.conn
        c.execute("select * from attendance")
        #         print(c.fetchall())

        for i in c.fetchall():
            self.user_id.append(i[0])
            self.user_name.append(i[1])
            if i[2] == None:
                self.time_1.append('None')
            else:
                self.time_1.append(i[2])
            self.logcat_late.append(i[3])
            if i[4] == None:
                self.time_2.append('None')
            else:
                self.time_2.append(i[4])
            if i[5] == None:
                self.dur_time.append('None')
            else:
                self.dur_time.append(i[5])
        self.c.close()

获取Access Token

向人脸识别API服务地址使用POST发送请求,必须在URL中带上参数access_token ,通过在百度智能云中创建应用得到的API Key和Secret Key生成(下方代码中ak和sk须修改为本人实际的密钥)。 在主类中实现代码如下:

    """
	    获取access_tokens
	"""

    def access_tokens(self):
        # 此处的AK和SK,需要替换成自己的
        ak = '********************'
        sk = '********************'

        # client_id 为官网获取的AK, client_secret 为官网获取的SK
        host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(
            ak, sk)
        response = requests.get(host)
        if response:
            return response.json()['access_token']

图片编码

请求的图片需经过Base64编码 ,图片的base64编码指将图片数据编码成一串字符串,使用该字符串代 替图像地址。可以首先得到图片的二进制,然后用Base64格式编码即可。在主类中实现代码如下:

"""
    获取追踪到图片的BASE64格式并返回参数列表
"""

    def imgdata(self, file1path, name=None, user_list=None):
        import base64
        f = open(r'%s' % file1path, 'rb')
        pic = base64.b64encode(f.read())
        f.close()

        # 人脸搜索params
        if name == 'face_search':
            params = json.dumps({"image": str(pic, 'utf-8'),
                                 "image_type": "BASE64", "group_id_list": "vipUser", "quality_control": "LOW",
                                 "liveness_control": "NORMAL"})
        # 人脸注册params
        elif name == 'face_registration':
            params = json.dumps({"image": str(pic, 'utf-8'), "image_type": "BASE64",
                                 "group_id": "vipUser", "user_id": user_list[0], "user_info": user_list[1],
                                 "quality_control": "LOW", "liveness_control": "NORMAL"})
        # 人脸质量检测params
        else:
            params = json.dumps(
                {"image": str(pic, 'utf-8'), "image_type": "BASE64", "face_type": "LIVE", "quality_control": "LOW"})
        return params

百度AI接口调用

1. 人脸质量检测

需要判断一张图片中的人脸,是否符合后续识别或者对比的条件,在请求时在face_field 参数中请求 quality 。基于返回结果 quality 中,以下字段及对应阈值,进行质量检测的判断,以保证人脸质量符 合后续业务操作要求。在主类中实现代码如下:

'''
   调用人脸质量检测API
'''

    def picture_quality(self, file1path):
        access_token = self.access_tokens()
        assert access_token != None, 'access_token is None'
        params = self.imgdata(file1path)
        request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"
        request_url = request_url + "?access_token=" + access_token
        headers = {'content-type': 'application/json'}
        response = requests.post(request_url, data=params, headers=headers).json()
        print(response)
        if response['error_msg'] == 'SUCCESS':
            score = response['result']['face_list'][0]['face_probability']
            print(score, type(score))
            if (type(score) == float) | (type(score) == int):
                if score >= 0.8:
                    self.recognize = False
                else:
                    self.recognize = True
                    print(score)

        else:
            self.recognize = True
            print(response['error_msg'])

2. 人脸注册

向人脸库中添加人脸,用于后续的人脸对比,在主类中实现代码如下:

"""
    调用人脸注册API
"""

    def face_registration(self, file1path, user):
        c, conn = self.c, self.conn
        c.execute("select user_id from attendance where user_id='{}'".format(user[0]))
        conn.commit()
        l = c.fetchone()
        if l == None:
            c.execute("insert into attendance(user_id,user_name,checking_state) values(?,?,'未打卡')", (user[0], user[1]))
            conn.commit()
            access_token = self.access_tokens()
            params = self.imgdata(file1path, 'face_registration', user)
            request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add"
            request_url = request_url + "?access_token=" + access_token
            headers = {'content-type': 'application/json'}
            response = requests.post(request_url, data=params, headers=headers).json()
            if response['error_msg'] == 'SUCCESS':
                self.registration = True
                print("注册成功")
                self.reg_msg = "注册成功"
                self.on = False

            elif response['error_msg'] == 'face already exist':
                print('您已经注册过了!')
                self.registration = True
                self.reg_msg = '您已经注册过了!'
                self.on = False
        else:
            self.reg_msg = '您已经注册过了!'
            self.on = False
        self.c.close()

3. 人脸搜索

也称为1:N识别,在指定人脸集合中,找到最相似的人脸,用于识别后记录此人打卡信息,在主类中实 现代码如下:

"""
    调用人脸搜索API
"""

    def face_search(self, file1path):
        c, conn = self.c, self.conn
        access_token = self.access_tokens()
        assert access_token != None, 'access_token is None'
        params = self.imgdata(file1path, 'face_search')
        request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"
        request_url = request_url + "?access_token=" + access_token
        headers = {'content-type': 'application/json'}
        response = requests.post(request_url, data=params, headers=headers).json()
        if response['error_msg'] == 'SUCCESS':
            self.search = False
            user_id = response['result']['user_list'][0]['user_id']
            times = time.time()
            this_time = time.localtime(times)
            punch_time = "{}-{}-{} {}:{}:{}".format(this_time.tm_year, this_time.tm_mon, this_time.tm_mday,
                                                    this_time.tm_hour, this_time.tm_min, this_time.tm_sec)
            c.execute("select checking_state from attendance where user_id='{}'".format(user_id))
            if c.fetchone()[0] == '未打卡':
                print('上班打卡')
                if this_time.tm_hour >= 8:
                    stats = '是'
                    self.search_msg = '上班打卡成功!您迟到了!'
                    print('迟到了')
                else:
                    stats = '否'
                    self.search_msg = '上班打卡成功!'
                c.execute("update attendance set sign_in_time='{}', checking_state ='{}'  where user_id='{}' ".format(
                    punch_time, stats, user_id))
                conn.commit()
            else:
                c.execute("select sign_in_time from attendance where user_id='{}'".format(user_id))
                start = time.mktime(time.strptime(c.fetchone()[0], "%Y-%m-%d %H:%M:%S"))
                during_time = round((times - start) / 60 / 60, 2)
                c.execute(
                    "update attendance set sign_out_time='{}', working_time='{}' where user_id='{}'".format(punch_time,
                                                                                                            during_time,
                                                                                                            user_id))
                conn.commit()
                print('下班打卡')
                self.search_msg = '下班打卡成功,今日上班时长为{}小时'.format(during_time)

            self.on = False

        elif response['error_msg'] == 'match user is not found':
            self.search = False
            self.search_msg = '请您先进行注册!'
            print('请您先进行注册!')
            self.on = False
        else:
            self.search = False
            self.search_msg = response['error_msg']
            self.on = False
        self.c.close()

4. 人脸删除

用于删除指定用户的某张人脸,指定用户可以上传20张以内的人脸图片,在主类中实现代码如下:

'''
	获取用户人脸列表并删除
'''

    def face_getlist(self, user_id):
        self.connect_sql()
        self.create_table()
        c, conn = self.c, self.conn
        c.execute("DELETE FROM attendance where user_id='{}'".format(user_id))
        conn.commit()
        access_token = self.access_tokens()
        assert access_token != None, 'access_token is None'

        # 人脸删除
        def face_delete(user_idx, face_token):
            request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/face/delete"

            params = json.dumps({"user_id": user_idx, "group_id": "vipUser", "face_token": face_token})
            request_url = request_url + "?access_token=" + access_token
            headers = {'content-type': 'application/json'}
            response = requests.post(request_url, data=params, headers=headers).json()
            if response['error_code'] == 0:
                del_msg = "删除成功"
            else:
                del_msg = response['error_msg']
            print(del_msg)
            self.del_msg = del_msg

        # 获取用户的face_token
        request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/face/getlist"
        params = json.dumps({"user_id": user_id, "group_id": "vipUser"})
        request_url = request_url + "?access_token=" + access_token
        headers = {'content-type': 'application/json'}
        response = requests.post(request_url, data=params, headers=headers).json()
        if response['error_msg'] == 'SUCCESS':
            for i in response['result']['face_list']:
                face_token = i['face_token']
                face_delete(user_id, face_token)
        else:
            self.del_msg = response['error_msg']
            print(response['error_msg'])

        self.c.close()

人脸跟踪

人脸跟踪用于检测图片中的人脸并标记出位置信息,此模块由OpenCV实现,在主类中实现代码如下:

"""
    使用OpenCV实现人脸追踪
"""

    def face_tracking(self):
        self.connect_sql()
        self.create_table()
        if self.command == 'registration':
            user, ids, name = [], self.txtRegisterNum.GetValue(), self.txtName.GetValue()
            user.extend([ids, name])
        cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
        # 设置显示大小
        cap.set(3, 450)
        cap.set(4, 450)
        # 创建人脸检测器(快速Harr)
        face_cascade = cv2.CascadeClassifier(".\\haarcascade_frontalface_alt2.xml")
        start_time = time.time()
        i = 1
        while True:
            print(i)
            i = i + 1
            ret, frame = cap.read()
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            ret, buf = cv2.imencode(".jpg", gray)
            img_bin = Image.fromarray(np.uint8(buf)).tobytes()
            faces = face_cascade.detectMultiScale(gray)
            max_face = 0
            value_x = 0
            # 追踪到人脸
            last_time = time.time()
            time_interval = last_time - start_time
            if (len(faces) > 0) & (time_interval >= 3):
                for (x, y, w, h) in faces:
                    if self.recognize == True:
                        roiImg = frame[y:y + w + 30, x:x + h]
                        cv2.imwrite('.//1.jpg', roiImg)
                    cv2.rectangle(frame, (x, y), (x + h, y + w), (0, 255, 0), 2)
                    result = (x, y, w, h)
                    x = result[0]
                    y = result[1]
                # 判断是否需要人脸质量检测
                if self.recognize == True:
                    self.picture_quality('.//1.jpg')
                else:
                    if self.command == 'search':
                        if self.search == True:
                            self.face_search('.//1.jpg')
                    elif self.command == 'registration':
                        if self.registration == False:
                            self.face_registration('.//1.jpg', user)

            if self.command == 'search':
                height, width = frame.shape[:2]
                image1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                pic = wx.Bitmap.FromBuffer(width, height, image1)
                self.bmpSign.SetBitmap(pic)
            if (self.command == 'search') & (self.on == False):
                wx.MessageBox(self.search_msg, 'message', wx.OK | wx.ICON_INFORMATION)
                self.c.close()
                self.init_data()
                self.bmpSign.SetBitmap(wx.Bitmap(self.imageBackgroud))
                break

            if self.command == 'registration':
                height, width = frame.shape[:2]
                image1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                pic = wx.Bitmap.FromBuffer(width, height, image1)
                self.bmpRegister.SetBitmap(pic)
            if (self.command == 'registration') & (self.on == False):
                wx.MessageBox(self.reg_msg, 'message', wx.OK | wx.ICON_INFORMATION)
                self.c.close()
                self.init_data()
                self.bmpRegister.SetBitmap(wx.Bitmap(self.imageBackgroud1))
                break

        cap.release()
        cv2.destroyAllWindows()
        self.btnSign.Show()

至此,所有模块实现完毕! 

 功能验证

1.注册人脸

点击人脸注册菜单,输入ID号和姓名,点击【确认】按钮,启动摄像头,识别并注册人脸,弹出【注册 成功】提示!

 点击【确认】按钮,退出注册!

2. 打卡

点击员工菜单,点击【打卡】按钮,启动摄像头,识别并完成打卡任务,弹出【上班打卡成功】提示!

3. 查看打卡信息

点击【查看员工打卡信息】菜单,点击【查询】按钮,在工作区显示打卡记录信息,如图所示!

 4. 人脸删除

点击【人脸删除】菜单,在文本框中输入待删除员工的id,如上述步骤中注册的【001】,点击【确 认删除】按钮,从人脸库中删除该用户信息,如图所示,弹出【删除成功】对话框!

 点击【确认】保存退出!

总结

本节课我们学习了变量初始化,连接数据库,获取Access Token,图片编码,百度AI接口调用,人脸跟踪和项目功能验证的相关内容。至此人脸识别打卡项目(1-7)也到这里结束了。回首这段时光,来时是重重的行囊,走时是满满的收获。感谢大家一路陪伴。

如果有需要全部代码的可以私信我,我也会第一时间为排忧解难。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

weixin_54822781

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

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

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

打赏作者

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

抵扣说明:

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

余额充值