树莓派3B实现人脸识别
参考大佬的文章:个人学习日志——树莓派实时人脸识别项目
一、连接摄像头
-
硬件:
(一定要断开电源再接摄像头,不然摄像头会烧坏)
先断开树莓派的电源,再将官方摄像头接到树莓派上,如图接:
-
打开VNC连接上树莓派,打开树莓派的终端,输入
sudo raspi-config
进入到树莓派的配置设置,将光标移动到Interface Options
回车确定确定后,将光标移动到 Legacy Camera上,回车确定,将树莓派的照相功能打开。
完成以上操作后,重启树莓派,重启树莓派后,在终端命令行里输入sudo raspi-config。打开树莓派的Camera后,树莓派的分辨率会被影响,我们将光标移动到
Display Options
上,回车确定选择第一个
revolution
,回车确定然后选择1280x720分辨率的,再回车确定。最后屏幕会弹出一个提示框问我们是否reboot,回车确定便是。
-
检测树莓派是否连接上摄像头:
通过VNC连接树莓派打开树莓派的终端,输入以下命令可以查看树莓派是否连接上摄像头,若连上detect=1,supported=1如下图:
vcgencmd get_camera
若出现如下情况:(注意:重新拔开摄像头时一定要断了电源再拔,不然会烧坏摄像头)
- 情况一:supported=0 detected=0,说明还没有打开树莓派的camera,返回重新进行上一步的操作,
- 情况二:supported=1 detected=0,说明摄像头没有很好地连接树莓派,或者是摄像头上的某些地方松动了。我们可以先断开电源,拔出摄像头,用纸巾擦一擦摄像头的线头,用金属触碰一下线头导除静电,再将其插稳在树莓派上,接着接通电源。
-
完成以上步骤基本就能连上摄像头了
二、检测树莓派的摄像头功能
-
查看摄像头情况:
ls /dev/video*
video 0指的就是树莓派的官方摄像头,有这个说明,摄像头已经连接上
-
用树莓派进行拍照(图片直接保存到当前终端所在的目录下,可以cat test.jpg)
raspistill -o ./test.jpg
打开文件夹,可以在home目录下看见一张jpg格式的照片
三、下载安装opencv
-
在树莓派终端,直接输入以下代码:
(网上有各种教程,教你如何在树莓派配置opencv的环境,但过程太复杂,所花的时间太久,如果你想只是进行人脸识别,可以直接运行一下代码,下载的是opencv4.5.1的版本的)
-
更新源:
sudo apt-get update
-
下载opencv:
sudo apt-get install python3-opencv
-
-
检测是否成功下载opencv:
在终端输入以下代码:
-
打开
Thonny
,输入以下代码,测试摄像头:import cv2 cap=cv2.VideoCapture(0) i=0 while(1): ret ,frame = cap.read() k=cv2.waitKey(1) if k==27: #按下ESC退出窗口 break cv2.imshow("capture", frame) cap.release()
能正常运行即可
四、人脸识别代码部分
1、采集人脸
-
首先通过树莓派的终端新建一个名为
dataset
的目录,在终端输入以下代码:mkdir dataset
-
获取Haar级联数据
-
在电脑上打开[opencv的官网][https://opencv.org/]点击release
-
接着选择一个版本的windows进行下载
-
下载完成之后打开这个下载好的exe,进行install,然后我们会获得一个文件,打开这个文件,找到
sources
双击,接着找data
双击,再接着找到haarcascades
双击 -
打开haarcascades后,下图红框的xml文件就是我们所需要的人脸识别数据文件(其他的xml文件是用于人的嘴巴,耳朵,或者眼睛的识别,有需要的自行选择),将该文件复制粘贴到电脑的桌面上。
-
利用VNC的文件传输功能,将上面红框的xml文件传输到树莓派上,并且该xml文件要放在你树莓派的用户目录下。
-
-
新建一个名为dataset的文件夹,然后打开
Thonny
,再新建一个名为collect_faces
的Python文件,将下面这段代码复制粘贴上去。import cv2 import numpy import os faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') #调用树莓派上的摄像头 cap = cv2.VideoCapture(0) #设置图像窗口的大小 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) #输入人脸的id,这里只能填整数 face_id = input('\n enter user id end press <return> ==> ') print('\n [INFO] Initializing face capture. Look the camera and wait ...') count = 0 while True: ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, # 表示每次图像尺寸减小的比例 minNeighbors=5, # 表示一个目标至少要被检测5次才会被认定为人脸 minSize=(20, 20), ) for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2) count += 1 cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h, x:x+w]) cv2.imshow('image', frame) if 27 == cv2.waitKey(10):#按下ESC健停止运行 break elif count >= 20:#收集到20张人脸照片停止 break print('\n [INFO] Exiting Program and cleanup stuff') #释放视频缓存,清理窗口 cap.release() cv2.destroyAllWindows()
-
运行以上代码,输入人脸id(id必须是整数,我这里先输入0),它先会弹出你的人脸窗口,直到识别收集到20张结束,这时,在目录dataset下会有20张灰度图。(这20张灰度图是user.0的人脸灰度图)
2、训练人脸
-
在树莓派的终端运行一下代码,新建一个叫
trainer
的目录mkdir trainer
-
进入终端,输入
pip list
查看是否已经下载了pillow,若没下载,运行以下代码进行下载:pip install pillow
-
接着打开
Thonny
,新建一个名为train_faces
的python文件,输入以下代码:import cv2 import numpy as np from PIL import Image import os # 人脸图像数据库的路径 path = 'dataset' recognizer = cv2.face.LBPHFaceRecognizer_create() detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") # 用于获取图像和标签数据的函数 def 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')# 将其转换为灰度 img_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, ids print ("\n [INFO] Training faces. It will take a few seconds. Wait ...") #调用函数 faces, ids = getImagesAndLabels(path) #对输入的人脸数据和对应的人脸id进行训练 recognizer.train(faces, np.array(ids)) # 将模型保存到 trainer/trainer.yml 中 recognizer.write('trainer/trainer.yml')# recognizer.save函数在 Mac 上工作,但在 Pi 上不起作用 # 打印经过训练的面孔数量并结束程序 print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))
-
运行以上代码后,文件trainer下会生成一个yml文件,这个便是训练好的模型文件,后面的人脸识别便要用到它。
3、人脸识别
-
打开
Thonny
,点击save,命名该文件为detect_faces
, 接着输入以下代码:import cv2 import numpy as np import os recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read('trainer/trainer.yml') cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2.CascadeClassifier(cascadePath) font = cv2.FONT_HERSHEY_SIMPLEX # 启动式 ID 计数器 id = 0 # id名称 names = ['liangjiahua', 'cxk', 'Paula', 'Ilza', 'Z', 'W'] # 初始化并开始实时视频捕获 cap = cv2.VideoCapture(0) #设置图像窗口的大小 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) while True: ret, img = cap.read() img = cv2.flip(img, 1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( # faces的值为人脸的坐标 gray, ) for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 显示方框 id, confidence = recognizer.predict(gray[y:y + h, x:x + w]) # 捕获人脸返回所在位置 # 检查匹配度是否小于它们 ,100 ==>“0”的匹配度 if (confidence < 100): id = names[id] confidence = " {0}%".format(round(100 - confidence)) # 显示百分比匹配度 else: id = "unknown" # 否则输出不认识 confidence = " {0}%".format(round(100 - confidence)) # 显示百分比匹配度 cv2.putText(img, str(id), (x + 5, y - 5), font, 1, (255, 255, 255), 2) # 显示id名 cv2.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (255, 255, 0), 1) # 显示匹配度 cv2.imshow('camera', img) k = cv2.waitKey(10) & 0xff # Press 'ESC' for exiting video if k == 27: break # 做一些清理 print("\n [INFO] Exiting Program and cleanup stuff") cap.release() cv2.destroyAllWindows()
-
识别情况如下:
五、用摄像头拍照出现bug
-
运行下面这段代码时,出现一段报错,虽然能生成一张照片但打不开,打开也是黑乎乎的一片。
raspivid -o Desktop/test.jpg
- 出现以上这段报错,直接买新的摄像头吧,大概是已经烧坏了