树莓派3B+、opencv3+PyQt5实现人脸识别门禁系统

前言

总结、干货、知识点、注意实现。无个人背景(别人不会关心,捂脸)

效果展示

没点效果,没兴趣往下看了吧(反正我是这样)

下面是两个界面:主页和人脸检测界面,主页可以密码锁、以及其他操作(自己按需),另一个界面是人脸检测的界面。

在这里插入图片描述
在这里插入图片描述

人脸录入:

在这里插入图片描述

开始检测:

在这里插入图片描述

识别成功之后就可以发指令控制步进电机转动控制门锁了

材料

树莓派3B+ 一块

USB摄像头 一个

3.5寸LCD显示屏(带触控)

HMDI接口的显示器(你去试试在3.5寸显示屏上面debug?)(或者试试ssh,下文逮到机会就说说一下)

飞鼠键盘(看个人兴趣)

在这里插入图片描述

准备

电脑上

在电脑上先把程序跑通再移植到树莓派上部署,我再pycharm上面把程序跑通(代码在后头)

pychram上安装opencv的库 opencv-python库、opencv-contrib-python库、PyQt5库、pyqt-tools库(这个是用来在qtdesinger拉控件,布置界面的,还有将ui界面转换成py文件),pycharm安装库看此链接

注意:

opencv-python库、opencv-contrib-python库这两个库的版本要一致。opencv-contrib-python库是opencv-python库的升级版,人脸识别的算法再里面。就是opencv-python库中有的,opencv-conteib-python库中都有,opencv-contrib-python库中有的opencv-python库中不一定有。安装opencv-contrib-python库就行了理论上,我没试过,可以试试,不然就两个都安装吧,反正不大。

树莓派上

1.装系统,网上很多教程,自己搞定。

2.装完,先换源,换成清华源吧。

3.sudo apt-get update 一下

4.装个输入法吧,推荐谷歌输入法,scim输入法用起来没有谷歌的好用

5.sudo apt-get install python3-opencv 安装到底就行了,我的树莓派系统是2019.7.15的版本,自带PyQt5,我试过确实不用安装。在终端上试试,python3 ,回车,之后

import PyQt5
import cv2

用这个方法看opencv是否可以用了,以及QT是否可以用如果没有显示其他问题,说明不用去安装PyQt5了。

  1. 3.5寸显示屏和HDMI显示器总要切换吧,3.5寸上看看效果,安装3.5寸显示屏的驱动参考这个

安装后你可以写个脚本控制这两种显示屏切换,比较方便

在终端上,安装vim,或者用自带nano 写一个脚本文件

1.sudo vim screen_choose.sh 这样就会生成一个脚本文件

2.按i 插入,把下面的写入到脚本中 ,

3.按esc退出编辑,

4.保存 输入:wq! 回车

5.sudo chmod 777 screen_choose.sh 权限设置

#!/bin/bash
echo $1
if [ $1 == 0 ]
then
	echo "5秒后切换成3.5寸显示屏。。。"
	sleep 5s
	echo "开始切换。。。"
	sleep 1s
	cd /这里放你驱动解压后的路径/
	./LCD35-show
elif [ $1 == 1 ]
then 
	echo "5秒后切换成HMDI显示器。。。"
	sleep 5s
	echo "开始切换。。。。"
	sleep 1s
	cd /这里的路径和上面一样,你解压后的路劲/
	./LCD-hdmi
fi

之后,在终端输入 ./screen_choose.sh 0 切换成3.5寸显示器,./screen_choose.sh 1切换成HDMI显示屏。

用了什么算子

流程

1.识别人脸,即人脸检测

2.视频中的人脸检测,即一帧一帧的人脸检测

3.录入人脸,即roi,把感兴趣的区域保存起来,存到对应文件夹

4.应用人脸识别算法,人脸识别,画框贴标签

5.PyQt5,布局设计

6.将界面与人脸识别链接起来

7.调试,部署到树莓派上

Haar级联分类器

这个分类器,通过对比分析相邻图像区域来判断给定图像或子图像与已知对象是否匹配。这里与图像特征的检测、识别计算有些关系。这里这个分类器,根据我们要识别的对象来选择对应的xml文件。

它有什么特点:

1.具有尺度不变性,在尺度变化上具有鲁棒性

2.不具有旋转不变性,旋转的人脸、侧脸是识别不出来的

3.opencv提供了尺度不变Haar级联的分类器和跟踪器,并将它们保存成指定的文件格式。用到哪个加载哪个文件即可

人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值。当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的。

OpenCV有已经自带了人脸的Haar特征分类器。OpenCV安装目录中的\data\ haarcascades目录下的haarcascade_frontalface_alt.xml与haarcascade_frontalface_alt2.xml都是用来检测人脸的Haar分类器。这个haarcascades目录下还有人的全身,眼睛,嘴唇的Haar分类器。

在这里插入图片描述

按需选择。。

下面代码,引入这个分类器。

face_cascade = cv2.CascadeClassifier('/home/pi/pyqt/helloworld/Lib/site- packages/cv2/data/haarcascade_frontalface_default.xml')

人脸检测

静态图像人脸检测

识别一张图片中人脸(正脸,这个是这个级联分类器的缺点),用这个级联分类器还是比较方便快速的。流程如下:

1.加载图像

2.检测人脸

3.根据检测出人脸位置参数,绘制矩形框

4.显示最终图片

def detect(filename):#静态人脸检测
        img = cv2.imread(filename)
        gray = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray , 1.3 , 5)#多尺度检测,参数有框这个框位置的准确性,需要了解自行百度
        for (x , y, w, h) in faces:
            img = cv2.rectangle(img, (x, y) , (x+w , y+h) , (0,0,255) , 2)
        cv2.namedWindow('get_face')
        cv2.imshow('get_face',img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
视频中的人脸检测

在静态图像人脸检测的基础上,对视频中的每一帧图像进行检测。流程如下:

1.打开摄像头,读取帧

2.检测帧中的人脸

3.画框

4.显示

5.按‘c’结束检测

代码如下:

要开启摄像头:

cap = cv2.VideoCapture(0)
def video_face_detect():#视频人脸检测
        while True:
            ret, frame = cap.read()
            #img = cv2.imread(frame)
            frame1 = frame.copy()  #图像拷贝
            gray = cv2.cvtColor(frame , cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray , 1.3 , 5)
            for (x , y , w, h) in faces:
                img = cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
            cv2.namedWindow('after_detect')
            img1 = np.hstack((frame1 , img))
            cv2.imshow('after_detect',img1)
            if cv2.waitKey(1) == ord('c'):
                break
人脸识别

人脸检测是人脸识别的基础。人脸识别就是一个程序能识别给定图像或视频中的人脸。opencv中是采用一系列分类好的图像(生成样本)来训练程序。

人脸识别另一个重要的特征就是有个置信度评分,可设置阈值来进行筛选。

人脸识别所需要的样本是有两种方式得到,一是自己采集来的图像、二是互联网上有许多人脸数据库(不是这里的重点,知道即可)

生成人脸识别数据

要满足一下条件:

1.图像是灰度,后缀名为.pgm

2.图像形状为正方形(程序中调整一下即可)

3.图像大小要一样大

def generate():                                          #2020.4.9已测试成功可以用
        counts = 1
        path1 = '/home/pi/pyqt/my_user'
        files = os.listdir(path1)
        count,nums = 1,0
        for filename in files:#计算文件夹中有多少个pgm文件 ,比较灵活点
            count += 1
            nums +=1
        Id = nums/200
        print('开始录入用户脸部信息!请摘掉眼镜........')
        print('不要固定的表情。。。。')
        Face_process.ass.stop()                                    #关闭定时器
        while True:
            ret , frame = cap.read()
            gray = cv2.cvtColor( frame , cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale( gray , 1.3 , 5 )
            for (x , y , w , h) in faces:
                img = cv2.rectangle(frame , (x, y) , (x+w,y+h) , (0,0,255) , 3)
                after = cv2.resize(gray[y:y+h,x:x+w] , (200 , 200))  #调整图片规格
                cv2.imwrite('/home/pi/pyqt/my_user/%s.pgm' %str(count) , after)
                Csv_file.write_csv(('my_user/%s.pgm'%str(count)) , Id)  #####################################################
                print('已录入' + str(counts) + '张图像....')
                cv2.putText(img,str(counts) + 'pictures have been entered...',(10, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255),3)
                count += 1
                counts += 1
            cv2.namedWindow('camera')
            print(frame.shape)
            cv2.imshow('camera' , frame)
            cv2.waitKey(80)  #延时500毫秒
            if counts > 200:   #录入20张照片
                print('录入结束!')
                Face_process.ass.start(10)#开启定时器
                break

我录入的是2一个人200个样本。

运行之后:对应文件夹下,就会有
在这里插入图片描述

在这里插入图片描述

pgm文件就是你的录入的人脸。上一个csv文件是后面训练程序时,分类、以及告诉程序样本在哪的作用。

人脸识别

opencv中提供了3种算法,这几种都是机器学习的算法,比如SVM,k均值聚类,这些算法背后都有用到它们。

1.Fisherfaces算法

2.Eigenfaces算法

3.LBPH算法

上面三种算法,第三种的效果是最好的。

前两种的置信度评分和最后一种是不一样的,前两种是产生的置信度在0到20000之内,评分低于4000的都可以被认为是可靠的识别了。而最后一种算法评分低于50的则可以被看成为可靠的识别,高于80则会被视为评分比较低的了

用上它们也不难,一行代码搞定:

model = cv2.face.createLBPHFaceRecognizer()

相应的,用其他算法就把LBPHFace改成其他算法名称就可以了

注意:

opencv3的版本就用上面这种格式,如果是opencv4,即版本的问题,就得改成下面的格式:

model = cv2.face.LBPHFaceRecognizer_create()
训练及人脸识别

直接上代码了,就是导入上面采集好的样本,训练模型,之后对视频帧进行识别显示即可

def face_distinguish():
        names = []
        f = open('/home/pi/pyqt/yonghu.csv' , 'r+')
        csv_read = csv.reader(f)
        for name in csv_read:
            names.append(name[0])
        [x , y] = Face_process.read_images('/home/pi/pyqt/ja.csv') #加载图片
        y = np.asarray(y , dtype=np.int32)
        Face_process.ass.stop()                                                        #关闭定时器,不显示图像
        Face_process.sd.setPixmap(QtGui.QPixmap(""))                                   #模型训练时需要一段事件,将最后卡顿是照片清理掉。。
        Face_process.sd.setText('系统正在工作,请耐心等候........')
        cv2.waitKey(1)                                                                 #延时一毫秒才有效果
        model = cv2.face.createLBPHFaceRecognizer()                                   #人脸识别模型c
        model.train(np.asarray(x) , np.asarray(y))                                     #训练模型
        while True:
            read , img = cap.read()                                                    #读取摄像头信息
            gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)                                #灰度化
            faces = face_cascade.detectMultiScale(gray, 1.3 , 5)                       #人脸检测
            for (x,y,w,h) in faces:
                img = cv2.rectangle(img , (x , y) , (x+w , y+h) , (0,0,255) , 3)       #画框
                roi = gray[x:x+w , y:y+h]                                              #扣出人脸图
                try:
                    roi = cv2.resize(roi,(200,200) , interpolation=cv2.INTER_LINEAR)   #图像规格大小调整
                    params = model.predict(roi)                                        #预测、识别
                    if params[1]<=50:
                        print('label:%s,confidence:%.2f' % (params[0], params[1]))  # 打印识别信息
                        cv2.putText(img, names[params[0]+1], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0),3)  # 贴标签
                except:
                    continue
            cv2.namedWindow('camera')
            cv2.imshow('camera' , img)
            cv2.waitKey(1)
            print(Face_process.zuiz)
            #print(System.cc)
            if Face_process.zuiz == 1:                                        #退出检测
                Face_process.zuiz = 0
                Face_process.ass.start(10)                                    #开始定时器
                break

PyQt5界面

直接安装pyqt-tools库,用qtdesiger搭建一个心仪的界面出来,之后将ui文件转换成py文件,想个法子将它和人脸识别整合到一块,不过上面的代码都是模块化的,用按键来执行相应动作一个也不难。我直接上我的效果图(捂脸)

在这里插入图片描述

在这里插入图片描述

毕竟是个系统所以还是要功能完整一些的啦,密码锁也在其中。上面就是我在pycharm下面开发出来的界面,debug、debug最终就满足了自己想要的效果。

移植到树莓派上

把整个工程文件复制到树莓派上面,在终端上面执行main.py文件就可以了。文件最好要多拷贝几份(树莓派很容易炸鸡、黑屏,特别不要随便断电,不然系统某些文件一旦丢失、缺损。各种蜜汁bug。),然后部署的时候可能得debug,运气好,直接运行成功。
执行语句用

sudo python3 +你的文件名.py

与单片机端通讯

树莓派负责人脸识别,之后,与单片机端,即下位机通讯,发送指令控制下位机端。

下位机参考这篇博客,我一个大二师弟搞的。这两端构成整个系统。

最后

好吧,有空可以搞搞看,其实每那么难。
需要的知识点:
1.python
2.opencv-python
3.PyQt5
4.linux命令、指令、相关知识
5.脚本文件知识。

源码

2020.6.19更新

我放在github上啦,有用的话欢迎star,有改进之处请指点,后面会做一版用CNN来做一个人脸分类器。
https://github.com/ZJ-science/face_detection_demo

  • 20
    点赞
  • 157
    收藏
    觉得还不错? 一键收藏
  • 32
    评论
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值