毕业设计| 树莓派3B+与opencv3+PyQt5实现人脸识别门禁系统
-
现在的毕设与智能相关的越来越多,比如人脸识别门禁系统。今天我们分享来自愚人国度的King的作品,给大家一些参考思路。
先来点效果展示,下面是两个界面:主页和人脸检测界面,主页可以密码锁、以及其他操作(自己按需),另一个界面是人脸检测的界面:
人脸录入:
开始检测:
识别成功之后就可以发指令控制步进电机转动控制门锁了。
接下来看看,要完成门禁系统,需要哪些材料:
- 树莓派3B+ 一块
- USB摄像头 一个
- 3.5寸LCD显示屏(带触控)
- HMDI接口的显示器
- 飞鼠键盘(看个人兴趣)
需要的知识点:
- python
- opencv-python
- PyQt5
- linux命令、指令、相关知识
- 脚本文件知识。
在开始大干之前,需要做一些准备:
◆ 电脑上
在电脑上,先把程序跑通再移植到树莓派上部署,我在pycharm上面把程序跑通(代码在后头)。
pychram上安装opencv的库: opencv-python库、opencv-contrib-python库、PyQt5库、pyqt-tools库(这个是用来在qtdesinger拉控件,布置界面的,还有将ui界面转换成py文件)。pycharm安装库如下链接:https://note.youdao.com/ynoteshare1/index.html?id=9d025059ad0326d9511ea4fc2bea321b&type=note
注意:
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了。
6)3.5寸显示屏和HDMI显示器总要切换吧,3.5寸上看看效果,安装3.5寸显示屏的驱动,安装后你可以写个脚本控制这两种显示屏切换,比较方便。
在终端上,安装vim,或者用自带nano 写一个脚本文件:
sudo vim screen_choose.sh 这样就会生成一个脚本文件;按i 插入,把下面的写入到脚本中 ;按esc退出编辑;保存 输入:wq! 回车;通过sudo chmod 777 screen_choose.sh 权限设置
之后,在终端输入 ./screen_choose.sh 0 切换成3.5寸显示器,./screen_choose.sh 1切换成HDMI显示屏。
用了什么算子,详细的实现过程:
☞ 流程
- 识别人脸,即人脸检测
- 视频中的人脸检测,即一帧一帧的人脸检测
- 录入人脸,即roi,把感兴趣的区域保存起来,存到对应文件夹
- 应用人脸识别算法,人脸识别,画框贴标签
- PyQt5,布局设计
- 将界面与人脸识别链接起来
- 调试,部署到树莓派上
☞ 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.根据检测出人脸位置参数,绘制矩形框
.显示最终图片
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
运行之后:对应文件夹下,就会有:
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
☞ 与单片机端通讯
树莓派负责人脸识别,之后,与单片机端,即下位机通讯,发送指令控制下位机端。下位机参考这篇博客,我一个大二师弟搞的:https://blog.csdn.net/ddddddddddda/article/details/105779357这两端构成整个系统。
之前有同学问妮姐有没有这方面的设计,妮姐才找到了愚人国度的King,无巧不成书他也曾看过我们达尔闻视频。再次感谢愚人国度的King的分享,对这个设计、树莓派、opencv感兴趣的同学可以关注他的csdn博客,博客ID:愚人国度的King,他经常会分享一些学习的经验,如嵌入式开发, C++,控制相关等内容,之后他的好内容我们还会继续分享给达尔闻粉丝们。
-