实时人脸识别:端到端项目
我们将逐步学习如何使用 PiCam 实时识别人脸。在我上一个探索 OpenCV 的教程中,我们学习了自动视觉对象跟踪。
现在我们将使用我们的 PiCam 实时识别人脸,如下所示:
这个项目是用这个很棒的“开源计算机视觉库”OpenCV 完成的。在本教程中,我们将专注于 Raspberry Pi(因此,Raspbian 作为操作系统)和 Python,但我也在我的 Mac 上测试了代码,它也运行良好。 OpenCV 旨在提高计算效率,并非常注重实时应用程序。因此,它非常适合使用相机进行实时人脸识别。
3个阶段
要创建一个完整的人脸识别项目,我们必须在 3 个非常不同的阶段工作:
- 人脸检测和数据收集
- 训练识别器
- 人脸识别
下面的框图恢复了这些阶段:
第 1 步:物料清单 - 物料清单
主要部分:
- Raspberry Pi V3 – 32.00 美元
- 5 百万像素 1080p 传感器 OV5647 迷你相机视频模块 - 13.00 美元
第 2 步:安装 OpenCV 3 包
我使用的是更新到 Raspbian (Stretch) 最新版本的 Raspberry Pi V3,因此安装 OpenCV 的最佳方法是遵循 Adrian Rosebrock 开发的优秀教程:Raspbian Stretch:安装Raspberry Pi 上的 OpenCV 3 + Python。
我尝试了几种不同的指南来在我的 Pi 上安装 OpenCV。 Adrian 的教程是最好的。我建议你也这样做,按照他的指导一步一步来。
完成 Adrian 的教程后,您应该有一个 OpenCV 虚拟环境准备好在您的 Pi 上运行我们的实验。
让我们进入我们的虚拟环境并确认 OpenCV 3 已正确安装。
Adrian 建议您每次打开新终端时都运行命令“source”,以确保您的系统变量设置正确。
源 ~/.profile
接下来,让我们进入我们的虚拟环境:
工作简历
如果您看到提示前的文本 (cv),则您处于 cv 虚拟 环境:
(简历) pi@raspberry:~$
Adrian 提请注意cv Python 虚拟环境 完全独立并与 Raspbian Stretch 下载中包含的默认 Python 版本隔离。因此,全局 site-packages 目录中的任何 Python 包都将无法用于 cv 虚拟环境。同样,安装在 cv 的 site-packages 中的任何 Python 包将无法用于 Python 的全局安装。
现在,输入您的 Python 解释器:
蟒蛇
并确认您运行的是 3.5(或更高)版本。
在解释器内(会出现“>>>”),导入 OpenCV 库:
导入cv2
如果没有出现错误消息,则 OpenCV 已正确安装在您的 PYTHON 虚拟环境中。
也可以查看安装的OpenCV版本:
cv2.__版本__
应该会出现3.3.0(或者以后可以发布的高级版本)。
上面的终端 PrintScreen 显示了前面的步骤。
第 3 步:测试您的相机
在您的 RPi 中安装 OpenCV 后,让我们进行测试以确认您的相机是否正常工作。
我假设您的 Raspberry Pi 上已经安装了 PiCam。
运行 Adrian 的教程时必须启用摄像头,否则将无法正确安装驱动程序。
万一您遇到以下错误:OpenCV 错误:断言失败 ,您可以尝试使用以下命令解决问题:
须藤 modprobe bcm2835-v4l2
正确安装所有驱动程序后,在您的 IDE 中输入以下 Python 代码:
import numpy as np
import cv2
cap =cv2.VideoCapture(0)
cap.set(3,640) # 设置宽度
cap.set(4,480) # 设置高度
while(True):
ret, frame =cap.read()
frame =cv2.flip(frame, -1) # 垂直翻转相机
gray =cv2.cvtColor(frame , cv2.COLOR_BGR2GRAY)
cv2.imshow(‘frame’, frame)
cv2.imshow(‘gray’,gray)
k =cv2.waitKey(30) &0xff
if k ==27:# 按'ESC'退出
break
cap.release()
cv2.destroyAllWindows()
以上代码将捕获由您的 PiCam 生成的视频流,以 BGR 颜色和灰色模式显示。
请注意,由于其组装方式,我垂直旋转了相机。如果不是您的情况,请注释或删除“翻转”命令行。
您也可以从我的 GitHub 下载代码:simpleCamTest.py
执行,输入命令:
python simpleCamTest.py
要完成程序,您必须按键盘上的 [ESC] 键。在视频窗口上单击鼠标,然后按 [ESC]。
如上图所示。
一些制造商在尝试打开相机时发现问题(“断言失败”错误消息)。如果在 OpenCv 安装期间未启用相机,则可能会发生这种情况,因此相机驱动程序未正确安装。要更正,请使用以下命令:
须藤 modprobe bcm2835-v4l2
您还可以将 bcm2835-v4l2 添加到 /etc/modules 文件的最后一行,以便驱动程序在启动时加载。
要了解有关 OpenCV 的更多信息,您可以按照教程进行操作:loading -video-python-opencv-tutorial
第 4 步:人脸检测
人脸识别最基本的任务当然是“人脸检测”。在做任何事情之前,你必须“捕捉”一张脸(第 1 阶段)才能识别它,然后与未来(第 3 阶段)捕捉到的新面孔进行比较。
检测人脸(或任何物体)的最常用方法是使用“Haar Cascade 分类器”
使用基于 Haar 特征的级联分类器的对象检测是 Paul Viola 和 Michael Jones 在他们的论文“Rapid Object Detection using a Boosted Cascade of Simple Features”于 2001 年提出的一种有效的对象检测方法。是一种基于机器学习的方法,其中级联函数是从大量正面和负面图像中训练出来的。然后用于检测其他图像中的对象。
在这里我们将使用人脸检测。最初,该算法需要大量的正图像(人脸图像)和负图像(没有人脸的图像)来训练分类器。然后我们需要从中提取特征。好消息是 OpenCV 带有一个训练器和一个检测器。如果你想为汽车、飞机等任何对象训练你自己的分类器,你可以使用 OpenCV 来创建一个。此处提供了其完整详细信息:级联分类器培训。
如果您不想创建自己的分类器,OpenCV 已经包含许多用于面部、眼睛、微笑等的预训练分类器。这些 XML 文件可以从 haarcascades 目录下载。
理论够了,让我们用 OpenCV 创建一个人脸检测器!
从我的 GitHub 下载文件:faceDetection.py。
import numpy as np
import cv2
faceCascade =cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')
cap =cv2.VideoCapture(0)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
while 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 face:
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) &0xff
if k ==27:# 按'ESC ' 退出
break
cap.release()
cv2.destroyAllWindows()
信不信由你,上面几行代码就是你检测人脸所需要的,使用Python和OpenCV。
当您与用于测试相机的最后一段代码进行比较时,您会发现其中添加了很少的部分。请注意以下行:
faceCascade =cv2.CascadeClassifier(‘Cascades/haarcascade_frontalface_default.xml’)
这是加载“分类器”的行(必须在项目目录下名为“Cascades/”的目录中)。
然后,我们将设置我们的相机并在循环内以灰度模式加载我们的输入视频(与我们之前看到的相同)。
现在我们必须调用我们的分类器函数,向它传递一些非常重要的参数,如比例因子、邻居数和检测到的人脸的最小尺寸。
faces =faceCascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5,
minSize=(20, 20)
)
哪里,
- 灰色 是输入的灰度图像。
- 比例因子 是指定图像大小在每个图像比例下缩小多少的参数。它用于创建比例金字塔。
- minNeighbors 是一个参数,指定每个候选矩形应该有多少个邻居,以保留它。数字越大,误报越低。
- 最小尺寸 是被视为人脸的最小矩形尺寸。
该函数将检测图像上的人脸。接下来,我们必须“标记”图像中的人脸,例如使用蓝色矩形。这是通过这部分代码完成的:
for (x,y,w,h) in face:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray =灰色[y:y+h, x:x+w]
roi_color =img[y:y+h, x:x+w]
如果找到人脸,它会将检测到的人脸的位置返回为一个矩形,左上角为 (x,y),宽度为“w”,高度为“h” ==> (x,y,w,h)。请看图。
一旦我们获得了这些位置,我们就可以为人脸创建一个“ROI”(绘制的矩形)并使用 imshow() 呈现结果 功能。
使用 Rpi 终端在您的 Python 环境中运行上述 Python 脚本:
python faceDetection.py
结果:
您还可以包含用于“眼睛检测”甚至“微笑检测”的分类器。在这些情况下,您将在面部循环内包含分类器函数和矩形绘制,因为在面部之外检测眼睛或微笑是没有意义的。
请注意,在 Pi 上,在同一代码中使用多个分类器会减慢处理速度,一旦这种检测方法 (HaarCascades) 使用大量计算能力。在桌面上,运行起来更容易。
例子
在我的 GitHub 上你会找到其他例子:
- faceEyeDetection.py
- faceSmileDetection.py
- faceSmileEyeDetection.py
并且在图片中,你可以看到结果。
您也可以按照以下教程更好地了解人脸检测:
Haar Cascade 对象检测人脸和眼睛 OpenCV Python 教程
第 5 步:数据收集
首先,我要感谢 Ramiz Raja 在照片人脸识别方面的出色工作:
使用 OpenCV 和 Python 进行人脸识别:初学者指南
还有 Anirban Kar,使用视频开发了一个非常全面的教程:
人脸识别 – 3 部分
我真的建议你看看这两个教程。
说到这里,让我们开始我们项目的第一阶段。我们在这里要做的是,从最后一步(人脸检测)开始,我们将简单地创建一个数据集,我们将在其中为每个 id 存储一组灰色照片以及用于人脸检测的部分。
首先,创建一个用于开发项目的目录,例如 FacialRecognitionProject:
mkdir FacialRecognitionProject
在这个目录中,除了我们将为我们的项目创建的 3 个 python 脚本之外,我们必须在上面保存了面部分类器。你可以从我的 GitHub 下载:haarcascade_frontalface_default.xml
接下来,创建一个子目录,我们将在其中存储我们的面部样本并将其命名为“数据集”:
mkdir 数据集
并从我的 GitHub 下载代码:01_face_dataset.py
import cv2
import os
cam =cv2.VideoCapture(0)
cam.set(3, 640) # 设置视频宽度
cam.set(4, 480) # set视频高度
face_detector =cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#每个人输入一个数字人脸id
face_id =input('\n输入用户id end press
print(“\n [INFO] 正在初始化人脸捕捉。看着相机等待……”)
# 初始化个人采样人脸计数
count =0
while(True):
ret, img =cam.read()
img =cv2.flip(img, -1) # 垂直翻转视频图像
gray =cv2.cvtColor(img , cv2.COLOR_BGR2GRAY)
faces =face_detector.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in face:
cv2.rectangle(img, (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', img)
k =cv2.waitKey(100) &0x ff # 按'ESC'退出视频
if k ==27:
break
elif count>=30:# 取30张人脸样本并停止视频
break
# 做一些清理
print(“\n [INFO] 退出程序并清理东西”)
cam.release()
cv2.destroyAllWindows()
代码与我们看到的人脸检测代码非常相似。我们添加的是一个“输入命令”来捕获用户 ID,它应该是一个整数(1、2、3 等)
face_id =input('\n 输入用户名 end press ==> ')
并且对于每个捕获的帧,我们应该将其保存为“数据集”目录中的文件:
cv2.imwrite(“dataset/User.” + str(face_id) + ‘.’ + str(count) + “.jpg”, gray[y:y+h,x:x+w])
请注意,要保存上述文件,您必须已导入库“os”。每个文件的名称将遵循以下结构:
User.face_id.count.jpg
例如,对于 face_id =1 的用户,dataset/ 目录中的第 4 个示例文件将类似于:
User.1.4.jpg
如我的 Pi 照片所示:
在我的代码中,我从每个 id 中捕获了 30 个样本。您可以在最后一个“elif”上更改它。样本数用于打破人脸样本采集的循环。
运行 Python 脚本并捕获一些 Id。每次要聚合新用户(或更改已存在用户的照片)时,都必须运行该脚本。
第 6 步:培训师
在第二阶段,我们必须从我们的数据集中获取所有用户数据并“训练”OpenCV 识别器。这是由特定的 OpenCV 函数直接完成的。结果将是一个 .yml 文件,该文件将保存在“trainer/”目录中。
阅读更多细节:实时人脸识别:一个端到端的项目
制造工艺