项目分享| 七步完成树莓派实时人脸识别
-
树莓派识别人脸项目再添一个,本次项目主要展示一步一步使用树莓派原装摄像头PiCam来实现实时人脸识别。虽然有详细的步骤,但你是新手零基础的话,建议补充人脸识别,以及树莓派使用的基础知识之后,再来尝试这个项目。
项目中使用到的软硬件:
硬件部分:Raspberry Pi 3 Model B,Raspberry Pi 3 Camera Module
软件部分:OPENCV,Python3
有很多树莓派的项目是使用的开源OpenCV,这里将用树莓派和python进行协同。代码编写有三个步骤:
步骤1:采集人脸数据和人脸检测
步骤2:训练人脸识别模型
步骤3:人脸识别推理
初步:配置软件环境:
在Raspberry Pi上安装OpenCV 3 + Python,这里不是重点,安装方法网上一大堆,自行搜索安装。
第二步:调用相机
如果已经RPi中安装了OpenCV,接下来就测试一下确认相机是否工作正常。在IDE上输入以下Python代码:
这段代码可以调用PiCam ,捕获视频流,并且通过黑白模式和RGB模式显示出来。按下Esc键即可退出程序。
第三步:人脸检测
人脸识别中的最基本任务是实现人脸检测,要先在一张图片中捕获到人脸,再去识别图片中的人脸和数据库中人脸数据进行比较。
人脸检测的最常见方法是使用“ Haar分类器” 。。基于Haar功能的级联分类器的对象检测是Paul Viola和Michael Jones提出的一种有效的对象检测,基于机器学习的方法。
进行人脸检测工作该算法需要大量的正图像(有人脸图像)和负图像(无人脸的图像)来训练分类器,然后从中提取特征。OpenCV可以进行人脸的训练和推理。如果想训练这些XML文件可以从 haarcascades 目录下载。
代码如下,或者你可以访问下载代码
https://github.com/Mjrovai/OpenCV-Face-Recognition/blob/master/FaceDetection/faceDetection.py
import numpy as npimport cv2faceCascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')cap = cv2.VideoCapture(0)cap.set(3,640) # set Widthcap.set(4,480) # set Heightwhile True:ret, img = cap.read()img = cv2.flip(img, -1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = faceCascade.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=5,minSize=(20, 20))for (x,y,w,h) in faces:cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)roi_gray = gray[y:y+h, x:x+w]roi_color = img[y:y+h, x:x+w]cv2.imshow('video',img)k = cv2.waitKey(30) & 0xffif k == 27: # press 'ESC' to quitbreakcap.release()cv2.destroyAllWindows()其中代码的这一部分是调用我们的分类器功能的:
faces = faceCascade.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=5,minSize=(20, 20))代码这一部分用作“标记”图像中的面孔,
for (x,y,w,h) in faces:cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)roi_gray = gray[y:y+h, x:x+w]roi_color = img[y:y+h, x:x+w]如果发现人脸,它会返回检测到的面部位置,作为左上角(x,y)的矩形,则将“ w”作为宽度,将“ h”作为高度= =(x,y,w,h) 。如下图:
如果可以实现以上功能,人脸检测功能基本实现,可以使用Rpi运行python代码。效果是这样的:
第四步:采集人脸数据
让我们开始项目代码的第一阶段。我们在这要存储每个ID的一组照片被后续进行人脸识别。
首先创建一个开发项目:FacialRecognitionProject,创建一个数据集数据集,存储我们的面部标本数据集。并且存储上述的调用PiCam代码和人脸检测代码。
import cv2import oscam = cv2.VideoCapture(0)cam.set(3, 640) # set video widthcam.set(4, 480) # set video heightface_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')# For each person, enter one numeric face idface_id = input('\n enter user id end press <return> ==> ')print("\n [INFO] Initializing face capture. Look the camera and wait ...")# Initialize individual sampling face countcount = 0while(True):ret, img = cam.read()img = cv2.flip(img, -1) # flip video image verticallygray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = face_detector.detectMultiScale(gray, 1.3, 5)for (x,y,w,h) in faces:cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)count += 1# Save the captured image into the datasets foldercv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])cv2.imshow('image', img)k = cv2.waitKey(100) & 0xff # Press 'ESC' for exiting videoif k == 27:breakelif count >= 30: # Take 30 face sample and stop videobreak# Do a bit of cleanupprint("\n [INFO] Exiting Program and cleanup stuff")cam.release()cv2.destroyAllWindows()对于每个捕获的帧,我们都把他保存在“数据集”目录上的文件。注意一下,要保存上述文件,必须导入库“ os”。每个文件的名称格式:
cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])
User.face_id.count.jpg
就像这样:
第五步:模型训练
现在要把之前存储的各个id号的图片提取特征,然后用于训练识别器。最后识别器上会生成一个yml文件。 首先在终端下载PIL库,函数getImagesAndLabels(路径)恢复我们刚刚的数据集上收集到ID号和对应的人脸特征。 具体代码如下:
import cv2import numpy as npfrom PIL import Imageimport os# Path for face image databasepath = 'dataset'recognizer = cv2.face.LBPHFaceRecognizer_create()detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml");# function to get the images and label datadef getImagesAndLabels(path):imagePaths = [os.path.join(path,f) for f in os.listdir(path)]faceSamples=[]ids = []for imagePath in imagePaths:PIL_img = Image.open(imagePath).convert('L') # convert it to grayscaleimg_numpy = np.array(PIL_img,'uint8')id = int(os.path.split(imagePath)[-1].split(".")[1])faces = detector.detectMultiScale(img_numpy)for (x,y,w,h) in faces:faceSamples.append(img_numpy[y:y+h,x:x+w])ids.append(id)return faceSamples,idsprint ("\n [INFO] Training faces. It will take a few seconds. Wait ...")faces,ids = getImagesAndLabels(path)recognizer.train(faces, np.array(ids))# Save the model into trainer/trainer.ymlrecognizer.write('trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi# Print the numer of faces trained and end programprint("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))第六步:人脸识别
人脸识别器已经实现,现在要在相机上捕获人脸。如果此人之前拍摄并训练过他的脸,识别器将做出预测,返回ID名和索引。
使用刚刚训练的识别器模型(加载trainer.yml),在这里使用了新的阵列,用姓名代替之前的标签,然后就和刚刚“人脸分类器”的步骤一样去进行人脸识别,并识别。预测将返回每张图片识别后的匹配率。 具体代码可以在“达尔闻说”微信回复:树莓派人脸识别,下载。
第七步:结果
最后,我们由PiCam采集图像,由识别器判断是否是我们数据集的人脸,在图像中显示该人名以及匹配指数,如果PiCam的图像不是我们数据库中的图像,无法进行识别的话,我们将显示未知。具体代码可以在“达尔闻说”微信回复:树莓派人脸识别,下载。 效果如下:
-