树莓派人脸打卡机(考勤机)(Python)

利用百度智能云中的人脸识别。
调用方法以及代码↓

百度智能云人脸识别的注册以及代码


先介绍一下 需要安装的东西
先win+R打开 树莓派人脸打卡机(考勤机)(Python)_第1张图片

直接输入就行 ,需要安装的有 pip install baidu-aip pip install opencv-python

利用百度的人脸识别来进行操作。
如果之前没有用过可以先去https://login.bce.baidu.com 创建一个账号
进入之后
树莓派人脸打卡机(考勤机)(Python)_第2张图片
点击这个人脸识别

树莓派人脸打卡机(考勤机)(Python)_第3张图片
树莓派人脸打卡机(考勤机)(Python)_第4张图片
树莓派人脸打卡机(考勤机)(Python)_第5张图片
树莓派人脸打卡机(考勤机)(Python)_第6张图片
图片中的三个东西是在后面调用的时候需要用到的

树莓派人脸打卡机(考勤机)(Python)_第7张图片

树莓派人脸打卡机(考勤机)(Python)_第8张图片

创建一个文件夹
树莓派人脸打卡机(考勤机)(Python)_第9张图片

完整的文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-24F546qx-1615551601821)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210312195924535.png)]

check.py

#与百度人脸识别相连接,来对当前打卡的进行检测。

from aip import AipFace
import base64
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''

groupIdList = "Matrix_studio"
print("初始化完成")
imageType = "BASE64"
client = AipFace(APP_ID, API_KEY, SECRET_KEY)

filePath = (r"capture.jpg")

def run():
    f = open(filePath, "rb")
    data = base64.b64encode(f.read())
    f.close()
    image = str(data, 'UTF-8')
    result = client.search(image, imageType, groupIdList)
    print(result["result"]["user_list"][0]["group_id"])  # 用户组名称
    print(result["result"]["user_list"][0]["user_id"])  # 用户ID
    print(result["result"]["user_list"][0]["score"])  # 相似度

    if result["error_msg"] == "SUCCESS":
        score = result["result"]["user_list"][0]["score"]
        user_id = result["result"]["user_list"][0]["user_id"]
        if score > 85:
            result_ = ['yes',user_id]
            print(user_id, ":识别成功")
            return result_
        else:
            result_ = 'no'
            print("人脸库无此人")
            return result_
    else:
        print("error:", result["error_msg"])
    


gengxin.py

#当匹配结果正确的时候,更改此人在数据库中的打卡次数的数据。

import pymysql.cursors
import time
import check
connection = pymysql.connect(host='localhost', port=3306,
                             user='root', passwd='123456', database='sunck', charset='utf8')


def get(sql):
    #try:
        cursor = connection.cursor()
        cursor.execute(sql)
        results = cursor.fetchall()
        return results
    #except Exception:
        #print("查询失败")
    #finally:
    #    cursor.close()  # 关闭游标连接
    #    connection.close()  # 关闭数据库连接


def update(sql):
    try:
        cursor = connection.cursor()
        cursor.execute(sql)
        connection.commit()
    except Exception:
        print("修改失败")
    #finally:
    #    cursor.close()  # 关闭游标连接
    #    connection.close()  # 关闭数据库连接


def geng(name_):
    a_ = get('select * from myApp_people')
    #res = check.run()
    #print(res)
    for x in a_:
        #print(x)
        if name_ in x:
            #uname = res[1]
            result = x[-3]
            break
    #date_=time.strftime('%y-%m-%d')
    #if date_ in date_dic:
    #    date_dic[date_]
    try:
        update('update myApp_people set count=' +str(result+1) +" where NAME = '"+name_+"'")
        return result+1
    except:
        pass

GUI.py

#向百度人脸库注册人脸的界面code。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(803, 531)
        MainWindow.setMinimumSize(QtCore.QSize(803, 531))
        MainWindow.setMaximumSize(QtCore.QSize(803, 531))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(10, 500, 641, 23))
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(10, 10, 640, 480))
        self.label.setMinimumSize(QtCore.QSize(640, 480))
        self.label.setMaximumSize(QtCore.QSize(639, 480))
        self.label.setText("")
        self.label.setPixmap(QtGui.QPixmap("C:/Users/wangxin/Desktop/未标题-1.jpg"))
        self.label.setScaledContents(False)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(660, 30, 41, 16))
        self.label_2.setObjectName("label_2")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(700, 30, 91, 21))
        self.lineEdit.setObjectName("lineEdit")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(660, 60, 131, 31))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(660, 140, 131, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(660, 100, 131, 31))
        self.pushButton_3.setObjectName("pushButton_3")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(660, 180, 131, 22))
        self.comboBox.setObjectName("comboBox")
        self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_4.setGeometry(QtCore.QRect(660, 210, 131, 28))
        self.pushButton_4.setObjectName("pushButton_4")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(660, 250, 72, 15))
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(660, 270, 121, 21))
        self.label_5.setText("")
        self.label_5.setObjectName("label_5")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "人脸录入系统"))
        self.label_2.setText(_translate("MainWindow", "姓名:"))
        self.pushButton.setText(_translate("MainWindow", "录入人脸数据"))
        self.pushButton_2.setText(_translate("MainWindow", "获取人脸列表"))
        self.pushButton_3.setText(_translate("MainWindow", "测试"))
        self.pushButton_4.setText(_translate("MainWindow", "删除"))
        self.label_4.setText(_translate("MainWindow", "信息:"))

move.py

#检测摄像头前是否有物体在移动,也就是为了避免当没有人时也在不断地向百度的人脸库发请求进行判断,避免消耗不必要的流量。

import cv2
def isMove(pre_frame, frame_lwpCV):
    #grabbed, frame_lwpCV = camera.read() # 读取视频流
    gray_lwpCV = cv2.cvtColor(frame_lwpCV, cv2.COLOR_BGR2GRAY) # 转灰度图
    pre_frame = cv2.cvtColor(pre_frame, cv2.COLOR_BGR2GRAY) # 转灰度图
    
    # 运动检测部分
    gray_lwpCV = cv2.resize(gray_lwpCV, (500, 500))
    pre_frame = cv2.resize(pre_frame, (500, 500))
    # 用高斯滤波进行模糊处理,进行处理的原因:每个输入的视频都会因自然震动、光照变化或者摄像头本身等原因而产生噪声。对噪声进行平滑是为了避免在运动和跟踪时将其检测出来。
    gray_lwpCV = cv2.GaussianBlur(gray_lwpCV, (21, 21), 0) 
    
    # 在完成对帧的灰度转换和平滑后,就可计算与背景帧的差异,并得到一个差分图(different map)。还需要应用阈值来得到一幅黑白图像,并通过下面代码来膨胀(dilate)图像,从而对孔(hole)和缺陷(imperfection)进行归一化处理

    img_delta = cv2.absdiff(pre_frame, gray_lwpCV)
    thresh = cv2.threshold(img_delta, 25, 255, cv2.THRESH_BINARY)[1]
    thresh = cv2.dilate(thresh, None, iterations=2)
    contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    for c in contours:
        if cv2.contourArea(c) < 1000: # 设置敏感度
            continue
        else:
            print("咦,有什么东西在动0.0")
            return True


register.py

#将新的人脸注册到百度人脸库之中。

from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.Qt import QThread, QImage, QPixmap, pyqtSignal, QIcon
import sys
from GUI import Ui_MainWindow
import cv2
import base64
from aip import AipFace
import binascii
image = None
flag = left = top = width = height = 0
name = list_text = ''


class Video(QThread):
    signal = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.cap = cv2.VideoCapture(0)
        self.qImg = None
        self.img = None

    def run(self):
        global image, left, top, width, height
        while True:
            _, self.img = self.cap.read()
            img2 = self.img.copy()
            cv2.rectangle(img2, (left, top), (left+width, top+height), (255, 255, 255), 2)
            image = self.img
            h, w, c = img2.shape
            self.qImg = QImage(img2.data, w, h, w * 3, QImage.Format_RGB888).rgbSwapped()
            self.signal.emit()


class FaceDetection(QThread):
    flag1 = pyqtSignal()
    flag2 = pyqtSignal(list)
    flag3 = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        app_id = '23167253'
        api_key = '38jgdZXVu0azpywqCw4Z7NAZ'
        secret_key = 'KrQZFsjoPNY44BD6qghUCDTuE9FyjV6n'
        self.client = AipFace(app_id, api_key, secret_key)
        self.img_type = 'BASE64'
        self.group = 'Matrix_studio'
        self.buffer = None
        self.video = Video()
        self.img = None

    def face_detection(self, img):
        face = self.client.detect(img, self.img_type)
        if face['error_msg'] == 'SUCCESS':
            x = int(face['result']['face_list'][0]['location']['left'])
            y = int(face['result']['face_list'][0]['location']['top'])
            w = int(face['result']['face_list'][0]['location']['width'])
            h = int(face['result']['face_list'][0]['location']['height'])
        else:
            x, y, w, h = left, top, width, height

        return x, y, w, h

    def cv2_base64(self, img):
        _, self.buffer = cv2.imencode('.jpg', img)
        base64_s = base64.b64encode(self.buffer)
        base64_st = str(base64_s, 'utf-8')
        return base64_st

    def face_enter(self, img, text):
        #texts = str(binascii.b2a_hex(text.encode('GBK')))[2:-1]
        texts = text
        self.client.addUser(img, self.img_type, self.group, texts)
        self.flag1.emit()

    def face_list(self):
        global flag
        names = []
        lists = self.client.getGroupUsers(self.group)
        for li in lists['result']['user_id_list']:
            names.append(li)
        self.flag2.emit(names)
        flag = 0

    def face_test(self, img):
        result = self.client.search(img, self.img_type, self.group)
        msg = result['error_msg']
        if msg == 'SUCCESS':
            names = result['result']['user_list'][0]['user_id']
            #names = bytes().fromhex(names).decode('gbk')
            score = result['result']['user_list'][0]['score']
        else:
            names = ''
            score = 0
        return msg, names, score

    def delete_face(self, text):
        #texts = str(binascii.b2a_hex(text.encode('GBK')))[2:-1]
        texts = text
        self.client.deleteUser(self.group, texts)

    def run(self):
        global image, left, top, width, height, flag, name
        while True:
            base64_str = self.cv2_base64(image)
            x, y, w, h = left, top, width, height
            left, top, width, height = self.face_detection(base64_str)
            if flag == 1:
                if x != left or y != top or w != width or h != height:
                    self.face_enter(base64_str, name)
            elif flag == 2:
                self.face_list()
            elif flag == 3:
                msg, names, score = self.face_test(base64_str)
                if msg == 'SUCCESS':
                    if score >= 70:
                        self.flag3.emit('你好 %s !' % names)
                    else:
                        self.flag3.emit('我不认识你!')
                if msg == 'pic not has face':
                    self.flag3.emit('未识别到人脸!')
            elif flag == 4:
                self.delete_face(list_text)


class MainWin(Ui_MainWindow):

    def __init__(self):
        self.video = Video()
        self.video.start()
        self.detection = FaceDetection()
        self.detection.start()
        self.progress = 0

    def setupUi(self, MainWindow):
        Ui_MainWindow.setupUi(self, MainWindow)
        self.video.signal.connect(self.Video)
        self.pushButton.clicked.connect(self.button1)
        self.detection.flag1.connect(self.progress_bar)
        self.pushButton_2.clicked.connect(self.button2)
        self.detection.flag2.connect(self.face_list)
        self.pushButton_3.clicked.connect(self.button3)
        self.detection.flag3.connect(self.face_test)
        self.pushButton_4.clicked.connect(self.button4)

    def face_test(self, text):
        self.label_5.setText(text)

    def face_list(self, lists):
        self.comboBox.addItems(lists)

    def progress_bar(self):
        global flag
        self.progress += 20
        if self.progress == 100:
            self.pushButton.setEnabled(True)
            self.pushButton_2.setEnabled(True)
            self.pushButton_3.setEnabled(True)
            self.pushButton_4.setEnabled(True)
            self.label_5.setText('录入完成!')
            self.progress = 0
            flag = 0
        self.progressBar.setProperty("value", self.progress)

    def button1(self):
        global flag, name
        if self.lineEdit.text() + 'None' != 'None':
            name = self.lineEdit.text()
            flag = 1
            self.pushButton.setEnabled(False)
            self.pushButton_2.setEnabled(False)
            self.pushButton_3.setEnabled(False)
            self.pushButton_4.setEnabled(False)
            self.label_5.setText('人脸信息录入中!')
        else:
            self.label_5.setText('请输入名字!')

    def button2(self):
        global flag
        flag = 2
        self.comboBox.clear()
        self.label_5.setText('获取成功!')

    def button3(self):
        global flag
        if flag == 0:
            flag = 3
            self.pushButton.setEnabled(False)
            self.pushButton_2.setEnabled(False)
            self.pushButton_4.setEnabled(False)
            self.pushButton_3.setText('停止测试')
        else:
            flag = 0
            self.pushButton.setEnabled(True)
            self.pushButton_2.setEnabled(True)
            self.pushButton_4.setEnabled(True)
            self.pushButton_3.setText('测试')
            self.label_5.setText('')

    def button4(self):
        global flag, list_text
        flag = 4
        list_text = self.comboBox.currentText()
        self.comboBox.clear()
        self.label_5.setText('删除成功!')

    def Video(self):
        self.label.setPixmap(QPixmap(self.video.qImg))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setWindowIcon(QIcon('./icon.ico'))
    main = QMainWindow()
    ui = MainWin()
    ui.setupUi(main)
    main.show()
    sys.exit(app.exec_())


use.py

#展示出用户的界面,能够限制每人每日的打卡次数为1次。

from tkinter import *
import cv2
from PIL import Image, ImageTk
import threading
import time
import check
import gengxin
import move
import json

root = Tk()
root.title('Matrix_工作室 考勤系统')  # 名字
root.wm_attributes('-topmost', True)
root.overrideredirect(True)

# root.geometry('800x500')


l1 = Label(root, text='Matrix 工作室', font=(
    'Arial', 12), width=15, height=2)  # 显示工作室的名字
l1.grid(row=0, column=1)


# 显示考勤的结果
var = StringVar()
l2 = Label(root, textvariable=var,
           font=('Arial', 12))
l2.grid(row=0, column=2)

im = Image.open("logo.jpg")
img_ = ImageTk.PhotoImage(im)
imLabel = Label(root, image=img_)
imLabel.grid(row=0, column=0)


camera = cv2.VideoCapture(0)  # 摄像头
success, img = camera.read()  # 从摄像头读取照片
cv2.imwrite("capture.jpg", img)  # 写入图片
old_img = img


def video_loop():
    global img
    global old_img
    old_img = img
    success, img = camera.read()  # 从摄像头读取照片
    cv2.imwrite("capture.jpg", img)  # 写入图片
    if success:
        cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)  # 转换颜色从BGR到RGBA
        current_image = Image.fromarray(cv2image)  # 将图像转换成Image对象
        imgtk = ImageTk.PhotoImage(image=current_image)
        panel.imgtk = imgtk
        panel.config(image=imgtk)
        root.after(1, video_loop)


#root = Tk()
#root.title("opencv + tkinter")
# root.protocol('WM_DELETE_WINDOW', detector)

panel = Label(root)  # initialize image panel
panel.grid(row=1, column=0, columnspan=3)
root.config(cursor="arrow")

# use_dic={}
with open('use_dic.json', 'r') as f:
    use_dic = f.read()
use_dic = json.loads(use_dic)


def write_date():
    with open('use_dic.json', 'w') as f:
        f.write(json.dumps(use_dic, indent=4))


name_dic = {
     
           
            }


def check_():
    global var
    while True:
        if move.isMove(old_img, img):
            try:
                time.sleep(1)
                res = check.run()
                if res[0] == 'yes':
                    if res[1] in use_dic:
                        if use_dic[res[1]][1] == time.strftime('%y-%m-%d'):
                            var.set('今日已打卡,无需重复')
                            time.sleep(2)
                        else:
                            if res[1] in name_dic:
                                cishu = gengxin.geng(use_dic[res[1]][0])
                                use_dic[res[1]][1] = time.strftime('%y-%m-%d')
                                write_date()
                                var.set('考勤成功,已累计打卡'+str(cishu)+'次')
                                time.sleep(2)
                            else:
                                var.set("工作室无此人信息。")
                    else:
                        use_dic[res[1]] = [name_dic[res[1]],
                                           time.strftime('%y-%m-%d')]
                        cishu = gengxin.geng(use_dic[res[1]][0])
                        write_date()
                        var.set('考勤成功,已累计打卡'+str(cishu)+'次')
                        time.sleep(2)

                elif res[0] == 'no':
                    var.set('人脸库无此人信息')
            except TypeError:
                var.set('考勤失败')
                continue


def check_main():
    thread_check = threading.Thread(target=check_)
    thread_check.start()


check_main()

video_loop()


root.mainloop()
# 当一切都完成后,关闭摄像头并释放所占资源
camera.release()
cv2.destroyAllWindows()

Django的安装


用浏览器搜索pypi.org
树莓派人脸打卡机(考勤机)(Python)_第10张图片
树莓派人脸打卡机(考勤机)(Python)_第11张图片
在这里插入图片描述
树莓派人脸打卡机(考勤机)(Python)_第12张图片
然后打开cmd,直接粘贴在网站中复制的命令就好了,回车运行。

配置环境变量:
在这里插入图片描述
树莓派人脸打卡机(考勤机)(Python)_第13张图片
树莓派人脸打卡机(考勤机)(Python)_第14张图片
树莓派人脸打卡机(考勤机)(Python)_第15张图片
然后添加 C:\Python33\Lib\site-packages\django 和 C:\Python33\Scripts

然后验证
树莓派人脸打卡机(考勤机)(Python)_第16张图片
最后得到的是下载的django的版本号

mysql的安装和配置


如果之前没安装过mysql,可以参考:https://www.bilibili.com/video/BV1ut4y1y7tt?p=2

在settings.py文件中,通过DATABASES选项进行数据库配置
树莓派人脸打卡机(考勤机)(Python)_第17张图片
配置MySQL:
1、在__init__.py中写下代码

import pymysql
pymysql.install_as_MySQLdb()

树莓派人脸打卡机(考勤机)(Python)_第18张图片
在这里插入图片描述
然后 以管理员身份打开cmd 输入 mysql -u root -p

如果出现
‘mysql’ 不是内部或外部命令,也不是可运行的程序或批处理文件
那么可能是因为没有配置mysql的环境变量
我们根据上面安装链接操作下载的是5.7版本的mysql那么
树莓派人脸打卡机(考勤机)(Python)_第19张图片
点击这个带有 Server的文件,然后复制里面的bin文件的路径就行了,
树莓派人脸打卡机(考勤机)(Python)_第20张图片
点击PATH,树莓派人脸打卡机(考勤机)(Python)_第21张图片
添加进去,然后再以管理员的身份打开cmd就可以了。
树莓派人脸打卡机(考勤机)(Python)_第22张图片
后输入代码,创建一个数据库,注意:结尾有一个英文状态下的**;**
在这里插入图片描述
创建完成之后在DATABASES中进行改动
树莓派人脸打卡机(考勤机)(Python)_第23张图片
树莓派人脸打卡机(考勤机)(Python)_第24张图片
格式:
树莓派人脸打卡机(考勤机)(Python)_第25张图片

创建DJango的第一个项目

第一步、先在合适的位置创建目录。
然后继续输入:django-admin startproject project [z这个project的位置是项目的名称可以自定义]

树莓派人脸打卡机(考勤机)(Python)_第26张图片
然后就拥有了第一个项目的文件夹了。

里面的几个初始文件的介绍
树莓派人脸打卡机(考勤机)(Python)_第27张图片

Django创建应用


在一个项目中可以创建多个应用,每个应用进行一种业务处理。

1、打开cmd终端,进入01-sunck下的project目录
树莓派人脸打卡机(考勤机)(Python)_第28张图片
2、在终端中执行 python manage.py startapp myApp
树莓派人脸打卡机(考勤机)(Python)_第29张图片
myApp目录说明
树莓派人脸打卡机(考勤机)(Python)_第30张图片
3、激活应用
在settings.py文件中将myApp应用加入到INSTALLED_APPS选项中
树莓派人脸打卡机(考勤机)(Python)_第31张图片
4、定义模型
树莓派人脸打卡机(考勤机)(Python)_第32张图片
树莓派人脸打卡机(考勤机)(Python)_第33张图片
5、生成数据表
树莓派人脸打卡机(考勤机)(Python)_第34张图片
树莓派人脸打卡机(考勤机)(Python)_第35张图片
树莓派人脸打卡机(考勤机)(Python)_第36张图片
树莓派人脸打卡机(考勤机)(Python)_第37张图片
引入模块
树莓派人脸打卡机(考勤机)(Python)_第38张图片
树莓派人脸打卡机(考勤机)(Python)_第39张图片
查看:(与上图操作不在同一个cmd终端中)
树莓派人脸打卡机(考勤机)(Python)_第40张图片
树莓派人脸打卡机(考勤机)(Python)_第41张图片
以管理员身份运行cmd操作树莓派人脸打卡机(考勤机)(Python)_第42张图片
在项目所在的文件路径中操作
树莓派人脸打卡机(考勤机)(Python)_第43张图片
Admin站点管理
树莓派人脸打卡机(考勤机)(Python)_第44张图片
树莓派人脸打卡机(考勤机)(Python)_第45张图片
管理数据表
树莓派人脸打卡机(考勤机)(Python)_第46张图片
树莓派人脸打卡机(考勤机)(Python)_第47张图片

你可能感兴趣的:(人脸识别,数据库,mysql,opencv)