使用OpenCV,Python和深度学习进行人脸识别

在本教程中,你将学习如何使用OpenCV,Python和深度学习进行面部识别。首先,我们将简要讨论基于深度学习的面部识别,包括“深度度量学习(deep metric learning)”的概念。

然后,我们先安装执行人脸识别所需的库。

最后,我们将为静态图像和视频流实施人脸识别。

你还是会发现,我们的人脸识别实现将能够实时运行,准确且高效。

理解深度学习人脸识别嵌入

那么,深度学习+人脸识别如何工作?

秘密是一种称为深度度量学习(deep metric learning)的技术。

如果你之前有深度学习的经验,你知道我们通常会训练一个网络来:接受一个输入图像

并输出该图像的分类/标签

但是,深度度量学习是不同的。

相反,对比起输出单个标签(或者甚至是图像中的对象的坐标/边界框)的模式,深度度量学习是输出一个实值特征向量。

对于dlib面部识别网络,输出特征向量是用于量化面部的128-d(即,128个实数值列表)。使用三元组(triplets)来训练网络:图1:通过深度度量学习的面部识别涉及“三重训练步骤”。三重点由3个独特的人脸图像组成--3个图像中的2个是同一个人。NN为3幅面部图像中的每幅图像生成一个128d的矢量。对于同一个人的两幅面部图像,我们调整神经网络权重以通过距离度量使得该向量更近。图片来源: Adam Geitgey的“机器学习很有趣”博客

在这里,我们向网络提供三个图像:其中两幅图像是同一人。

第三张图像是我们数据集中的一张随机脸,与其他两张图像不一样。

作为一个例子,让我们再次考虑图1,我们提供了三个图像:一张Chad Smith的脸和两张Will Ferrell的。

我们的网络量化了人脸,为每个人构建了128-d嵌入(128-d embedding 量化)。

总得来说,我们将调整我们的神经网络的权重,以使两张Will Ferrell图像的128-d测量结果彼此更接近,并远离Chad Smith的测量结果。

我们用于人脸识别的网络架构基于He等人的

网络本身是由野外标记的人脸(LFW)数据集中,我们的网络与其他最先进的方法进行比较,可达到99.38%的准确度。

Davis King(dlib的创建者)和face_recognition模块的作者)都撰写了关于基于学习的面部识别深度的详细文章:

我强烈建议你阅读上述文章,了解有关深度学习面部嵌入如何工作的更多细节。

安装你的脸部识别库

为了使用Python和OpenCV进行脸部识别,我们需要安装两个额外的库:

由Davis King维护的dlib库包含我们实现的“深度度量学习”,用于构建用于实际识别过程的人脸嵌入。

face_recognition 库,开发者是亚当Geitgey,封装有关DLIB的面部识别功能,使其更易于使用。

我假设你的系统上安装了OpenCV。如果没有,请不要担心 - 只需访问我的OpenCV安装教程页面并按照适合你系统的指南进行操作即可。

好,现在让我们安装 dlib和 face_recognition两个包。

注意: 对于以下安装,请确定你在Python命令行中。如果你已经遵循了我的OpenCV安装指南(并安装了 virtualenv + virtualenvwrapper ),那么你可以使用workon命令 安装dlib 和face_recognition。

dlib 无需 GPU支持即可安装

如果你没有GPU,则可以按照本指南 使用pip 安装 dlib:

$ workon # optional

$ pip install dlib

或者你可以从源代码编译:

$ workon # optional

$ git clone https://github.com/davisking/dlib.git

$ cd dlib

$ mkdir build

$ cd build

$ cmake .. -DUSE_AVX_INSTRUCTIONS=1

$ cmake --build .

$ cd ..

$ python setup.py install --yes USE_AVX_INSTRUCTIONS

安装带有GPU支持的dlib(可选)

如果你这样做有一个兼容CUDA的GPU,那你可以安装带有GPU支持的DLIB,使得面部识别速度更快,效率更高。

为此,我建议 从源代码安装 dlib,因为你可以对构建有更多的控制:

$ workon # optional

$ git clone https://github.com/davisking/dlib.git

$ cd dlib

$ mkdir build

$ cd build

$ cmake .. -DDLIB_USE_CUDA=1 -DUSE_AVX_INSTRUCTIONS=1

$ cmake --build .

$ cd ..

$ python setup.py install --yes USE_AVX_INSTRUCTIONS --yes DLIB_USE_CUDA

安装face_recognition

所述face_recognition模块是通过一个简单的PIP命令安装:

$ workon # optional

$ pip install face_recognition

安装 imutils

你还需要我的一套便利功能,imutils。你可以通过pip将其安装在你的Python虚拟环境中:

$ workon # optional

$ pip install imutils

我们的脸部识别数据集图2:使用Python和Bing Image Search API以编程方式创建示例人脸识别数据集。图中显示了侏罗纪公园电影系列中的六个角色。

由于艾伦格兰特,古生物学家(22图像)

克莱尔·迪林,园区运营管理(53张图片)

Ellie Sattler,古植物学家(31幅图像)

伊恩马尔科姆,数学家(41个图像)

约翰哈蒙德,商人/侏罗纪公园所有者 (36张图片)

欧文格雷迪,恐龙研究员(35张图片)

这个数据集是在30分钟内使用我为数据集中的每个面创建128-d嵌入

使用这些嵌入来识别图像和视频流中字符的面部

人脸识别项目结构

通过检查树 命令的输出可以看到我们的项目结构 :

$ tree --filelimit 10 --dirsfirst

.

├── dataset

│ ├── alan_grant [22 entries]

│ ├── claire_dearing [53 entries]

│ ├── ellie_sattler [31 entries]

│ ├── ian_malcolm [41 entries]

│ ├── john_hammond [36 entries]

│ └── owen_grady [35 entries]

├── examples

│ ├── example_01.png

│ ├── example_02.png

│ └── example_03.png

├── output

│ └── lunch_scene_output.avi

├── videos

│ └── lunch_scene.mp4

├── search_bing_api.py

├── encode_faces.py

├── recognize_faces_image.py

├── recognize_faces_video.py

├── recognize_faces_video_file.py

└── encodings.pickle

10 directories, 11 files

我们的项目有4个顶级目录:dataset/ :根据各自名称组织到子目录中的六个字符的脸部图像。

examples/ :三个不在数据集中的用于测试的面部图像。

output/ :这是你可以存储处理过的人脸识别视频的地方。里面包含我放的一个文件夹 - 原始侏罗纪公园电影中的经典“午餐场景” 。

videos/ :输入视频应存储在此文件夹中。该文件夹还包含“午餐现场”视频,但它尚未经过我们的人脸识别系统。

我们在根目录中也有 6个文件:search_bing_api .py :第一步是建立一个数据集(我已经为你做过)。要了解如何使用Bing API与我的脚本构建数据集,请参阅此博客文章。

encode_faces.py :使用此脚本构建面部的编码(128-d向量)。

recognize_faces_image.py :识别单个图像面(根据编码从数据集)。

recognize_faces_video.py :用于网络摄像头实时拍摄或者视频流中的人脸识别。

recognize_faces_video_file.py :识别人脸在驻留在磁盘上并输出所处理的视频到硬盘的视频文件。我今天不会讨论这个文件,因为这和视频流文件相同有相同的框架。

encodings.pickle :面部识别编码通过 encode_faces.py从你的数据集生成 ,然后序列化到磁盘。

创建图像数据集(使用 search_bing_api.py )后,我们将运行 encode_faces.py来构建嵌入。

然后,我们将运行识别脚本来实际识别脸部。

使用OpenCV和深度学习对脸部进行编码

图3:通过深度学习的人脸识别和Python使用face_recognition 模块方法为每个人脸生成一个128-d实数数字特征向量。

在我们识别图像和视频中的人脸之前,我们首先需要量化我们训练集中的人脸。请记住,我们实际上并没有在这里训练网络,因为网络已经被大约300万张图像的数据集训练过以创建128-d嵌入。

我们当然可以从头开始训练网络,甚至可以微调现有模型的权重,但这对于许多项目来说可能是过度的。此外,你需要大量图像来从头开始训练网络。

相反,使用预先训练的网络更容易,然后使用它为我们的数据集中的每218个面部图片构建128-d嵌入。

然后,在分类过程中,我们可以使用简单的k-NN模型+投票来进行最终的人脸分类。其他传统的机器学习模型也可以在这里使用。

要构建我们的脸部嵌入,可从本文结束后的下载连接中使用encode_faces.py

import the necessary packages

from imutils import paths

import face_recognition

import argparse

import pickle

import cv2

import os

首先,我们需要导入所需的软件包。再次注意,这个脚本需要安装 imutils,face_recognition 和OpenCV,请确保所需的库已安装好。

让我们来处理在运行时使用argparse处理的命令行参数 :

# construct the argument parser and parse the arguments

ap = argparse.ArgumentParser()

ap.add_argument("-i", "--dataset", required=True,

help="path to input directory of faces + images")

ap.add_argument("-e", "--encodings", required=True,

help="path to serialized db of facial encodings")

ap.add_argument("-d", "--detection-method", type=str, default="cnn",

help="face detection model to use: either `hog` or `cnn`")

args = vars(ap.parse_args())

如果你是PyImageSearch的新手,请让我将你的注意力放在上面的代码块上,当你博客帖子时,这些代码块将变得很熟悉。我们使用argparse来解析命令行参数。当你在命令行中运行Python程序时,你可以在不离开终端的情况下向脚本提供更多信息。 第10-17行在解析来自终端的输入时不需要修改。如果对这些不熟悉的话,看看我的博客文章有关命令行参数。

让我们列出参数标志并讨论它们:dataset:我们数据集的路径(我们在上周的博客文章的方法#2中 描述了用search_bing_api.py创建一个数据集 )。

encodings:我们的脸部编码被写入该参数指向的文件。

detection- method:在我们可以对图像中的脸部进行编码之前,我们首先需要检测它们。两种人脸检测方法包括 hog 和 cnn,这是两个唯一可用于 - detection-method的标志(flags)。

现在我们已经定义了我们的参数,让我们抓取数据集中文件的路径(以及执行两个初始化)

# grab the paths to the input images in our dataset

print("[INFO] quantifying faces...")

imagePaths = list(paths.list_images(args["dataset"]))

# initialize the list of known encodings and known names

knownEncodings = []

knownNames = []跟代码一样的部分

第21行使用的路径,我们的输入数据集目录下建所有的列表 imagePaths 包含在其中。

我们还需要分别在循环之前初始化两个列表,knownEncodings 和 knownNames。这两个列表将包含数据集中每个人的面部编码和相应名称(第24行和第25行)。

现在是开始循环我们侏罗纪公园人物面孔的时候了!

# loop over the image paths

for (i, imagePath) in enumerate(imagePaths):

# extract the person name from the image path

print("[INFO] processing image {}/{}".format(i + 1,

len(imagePaths)))

name = imagePath.split(os.path.sep)[-2]

# load the input image and convert it from RGB (OpenCV ordering)

# to dlib ordering (RGB)

image = cv2.imread(imagePath)

rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

该循环将循环218次,对应于我们在数据集中的218张脸部图像。我们正在循环第28行中每个图像的路径 。

然后,我们在第32行中 从imagePath中提取该人的name(因为我们的子目录被适当命名) 。

之后让我们加载image,同时将imagePath传递给 cv2.imread(第36行)。

OpenCV默认选择BGR颜色(orders color channels in BGR),但dlib实际上需要用RGB。 face_recognition模块使用 dlib,所以在开始处理之前,让我们在第37行交换的颜色空间,命名新的图像 rgb 。

接下来,让我们定位面部并计算编码:

# detect the (x, y)-coordinates of the bounding boxes

# corresponding to each face in the input image

boxes = face_recognition.face_locations(rgb,

model=args["detection_method"])

# compute the facial embedding for the face

encodings = face_recognition.face_encodings(rgb, boxes)

# loop over the encodings

for encoding in encodings:

# add each encoding + name to our set of known names and

# encodings

knownEncodings.append(encoding)

knownNames.append(name)

这是脚本的有趣部分!

对于循环的每次迭代,我们将检测一张脸(或可能是多张脸,并假定它是图像多个位置中的同一个人 - 此假定可能不会在你的图片中实现,所以这里要注意一下)。

例如,假设 rgb包含Ellie Sattler脸部的图片(一张或多张)。

第41和42行实际查找/本地化她面部列表的boxes。我们将两个参数传递给face_recognition.face_locations方法:rgb:我们的RGB图像。

model: cnn 或 hog(该值包含在与 “detection_method” 关联的命令行参数字典中 )。CNN方法更精确但速度更慢,HOG速度更快但不够准确。

然后,我们打算将Ellie Sattler脸上的边界boxes变成第45行上128个数字的列表。这是用face_recognition.face_encodings方法来向量化脸部 。

我们只需要将Ellie Sattler的encoding 和 name附加到适当的列表( knownEncodings 和knownNames)。

我们将继续为数据集中的所有218个图像执行此操作。

除非我们可以在另一个处理识别的脚本中使用encodings,不然编码图像将没有意义 。

现在让我们来关注一下:

# dump the facial encodings + names to disk

print("[INFO] serializing encodings...")

data = {"encodings": knownEncodings, "names": knownNames}

f = open(args["encodings"], "wb")

f.write(pickle.dumps(data))

f.close()

第56行用两个键“encoding”和“names” 构建一个字典。

然后第57-59行将名称和编码转储到磁盘以供将来调用。

那现在该如何在终端中运行 encode_faces.py脚本?

要创建我们的面部嵌入(facial embeddings),请打开终端并执行以下命令:

$ python encode_faces.py --dataset dataset --encodings encodings.pickle

[INFO] quantifying faces...

[INFO] processing image 1/218

[INFO] processing image 2/218

[INFO] processing image 3/218

...

[INFO] processing image 216/218

[INFO] processing image 217/218

[INFO] processing image 218/218

[INFO] serializing encodings...

$ ls -lh encodings*

-rw-r--r--@ 1 adrian staff 234K May 29 13:03 encodings.pickle

从输出中可以看到,我们现在有一个名为encodings.pickle - 这个文件包含我们数据集中每个脸部的128-d脸部嵌入。

在我的Titan X GPU上,处理整个数据集需要一点点时间,但如果你使用的是CPU,请 准备好等待一段时间完成此脚本!

在我的Macbook Pro(无GPU)上,编码218张图像需要21分20秒。

如果你拥有GPU并编译支持GPU的dlib,你应该期望速度更快。

识别图像中的脸部图4: John Hammond的面孔被Adam Geitgey的深度学习face_recognitionPython模块所辨识。

现在我们已经为数据集中的每个图像创建了128-d脸部嵌入,接下来准备使用OpenCV,Python和深度学习识别图像中的脸部。

打开 recognize_faces_image.py 和插入下面的代码:

# import the necessary packages

import face_recognition

import argparse

import pickle

import cv2

# construct the argument parser and parse the arguments

ap = argparse.ArgumentParser()

ap.add_argument("-e", "--encodings", required=True,

help="path to serialized db of facial encodings")

ap.add_argument("-i", "--image", required=True,

help="path to input image")

ap.add_argument("-d", "--detection-method", type=str, default="cnn",

help="face detection model to use: either `hog` or `cnn`")

args = vars(ap.parse_args())

这个脚本在第2-5行只需要导入四个包 。face_recognition 模块将heavy lifting,OpenCV将帮助我们来加载,转换和显示处理后的图像。

我们将在第8-15行解析三个命令行参数 :- encodings:包含我们脸部编码的pickle文件的路径。

- image:这是正在进行面部识别的图像。

- detection-method:现在你应该熟悉这个方法 - 根据系统的功能,我们要么使用 hog或cnn方法。为了速度,选择hog,为了准确,选择cnn 。

注意:在Raspberry Pi上,你需要选择 hog,因为没有足够的内存来支持CNN方法。

让我们加载预先计算的编码+脸部名称,然后构建输入图像的128-d脸部编码:

# load the known faces and embeddings

print("[INFO] loading encodings...")

data = pickle.loads(open(args["encodings"], "rb").read())

# load the input image and convert it from BGR to RGB

image = cv2.imread(args["image"])

rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# detect the (x, y)-coordinates of the bounding boxes corresponding

# to each face in the input image, then compute the facial embeddings

# for each face

print("[INFO] recognizing faces...")

boxes = face_recognition.face_locations(rgb,

model=args["detection_method"])

encodings = face_recognition.face_encodings(rgb, boxes)

# initialize the list of names for each face detected

names = []

第19行从磁盘加载我们的准备好的编码(pickled encodings)和脸部名称。稍后在实际的人脸识别步骤中我们需要这些数据。

然后,在第22行和第23行,我们加载并将输入image转换为 rgb 颜色通道序列(就像我们在encode_faces.py 脚本中所做的那样)。

在第29-31行(这些行也应该很熟悉了)我们继续检测输入图像中的所有面孔和计算其128-d的encodings 。

现在是初始化 检测到的每个面的names列表的好时机 - 此列表将在下一步中填充。

接下来,让我们循环面部encodings :

# loop over the facial embeddings

for encoding in encodings:

# attempt to match each face in the input image to our known

# encodings

matches = face_recognition.compare_faces(data["encodings"],

encoding)

name = "Unknown"

在第37行,我们开始循环从我们的输入图像计算出的人脸编码。

现在见证奇迹的时候了!

我们使用face_recognition.compare_faces将输入图像(encoding )中的每个人脸与我们已知的编码数据集(保存在 data [ “encodings” ]中)进行匹配。(第40和41行)。

该函数返回True / False 值的列表 ,数据集中的每个图像对应一个值。对于我们的侏罗纪公园示例,数据集中有218个图像,因此返回的列表将具有218个布尔值。

实际机理,compare_faces 函数计算候选嵌入(candidate embedding)和我们数据集中所有面(faces)的欧几里得距离:如果距离低于某个容差(容差越小,我们的面部识别系统将越严格),那么我们返回True ,表示脸部匹配。

否则,如果距离高于容差阈值,我们将返回 False,表示脸部不匹配。

本质上,我们正在使用“更花哨”的k-NN模型进行分类。请务必参阅compare_faces实现以获取更多详细信息。

name变量将最终持有人的姓名串-现在,我们把它设为 “unknown” ,以防有没有“票”的情况(no votes)(第42号线)。

根据我们的 matches 列表,我们可以计算每个名称的“投票数”(与每个名称关联的True的数量),计算出投票数,并选择具有最相应投票的人的姓名:

# check to see if we have found a match

if True in matches:

# find the indexes of all matched faces then initialize a

# dictionary to count the total number of times each face

# was matched

matchedIdxs = [i for (i, b) in enumerate(matches) if b]

counts = {}

# loop over the matched indexes and maintain a count for

# each recognized face face

for i in matchedIdxs:

name = data["names"][i]

counts[name] = counts.get(name, 0) + 1

# determine the recognized face with the largest number of

# votes (note: in the event of an unlikely tie Python will

# select first entry in the dictionary)

name = max(counts, key=counts.get)

# update the list of names

names.append(name)

如果 在matches中有任何True的投票(第45行),我们需要确定这些True值在matche的索引 。我们在第49行做了这样的工作 ,我们为example_01 .png构建了一个简单的matchedIdx列表,其格式如下 :

(Pdb) matchedIdxs

[35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75]

然后我们初始化一个叫做counts的字典,它将把字符名称(character name)作为键,投票数作为值(第50行)。

现在,让我们遍历 matchedIdxs并设置与每个名称关联的值,同时根据需要在counts中增加它 。这个counts字典可能是这样的一个如下面代码的伊恩·马尔科姆(ian_malcolm)的高的分:

(Pdb) counts

{'ian_malcolm': 40}

回想一下,我们在数据集中只有41张Ian的图片,所以40的得分是非常高了。

第61行从计数中提取得票最多的名称 ,在这种情况下,它将是 'ian_malcolm' 。

现在做第二次迭代(因为在我们的示例图像中有两个面),产生以下counts :

(Pdb) counts

{'alan_grant': 5}

这绝对是一个较小的投票分数,但在字典中仍然只有一个名字,所以我们可能找到了Alan Grant。

注意:PDB Python调试器用于验证counts字典的值 。PDB的使用超出了本博文的范围; 但是,你可以发现如何在Python文档页面上使用它。

如下图5所示,Ian Malcolm和Alan Grant都已被正确识别,因此脚本的这部分运行良好。

让我们继续前进,并遍历每个人的边界框和标签名称,并将其绘制在输出图像上用于可视化目的:

# loop over the recognized faces

for ((top, right, bottom, left), name) in zip(boxes, names):

# draw the predicted face name on the image

cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2)

y = top - 15 if top - 15 > 15 else top + 15

cv2.putText(image, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX,

0.75, (0, 255, 0), 2)

# show the output image

cv2.imshow("Image", image)

cv2.waitKey(0)

在 第67行,我们开始循环检测到的边界boxes 和预测的names。为了创建一个可迭代的对象,以便我们可以轻松地循环访问这些值,我们称之为 zip(boxes, names),从而生成元组,我们可以从中提取box的坐标和名称。

我们使用box坐标在第69行上画一个绿色的矩形 。

我们还使用坐标来计算我们应该在哪里绘制人物名称的文本(第70行),然后将名称文本实际放在图像上(第71行和第72行)。如果面框位于图像的最上方,我们需要将文本移动到方框的顶部(在第70行处理),否则文本会被截断。

然后我们继续显示图像,直到按下一个键(第75和76行)。

你应该如何运行面部识别Python脚本?

使用你的终端,首先使用workon命令。

然后运行脚本,同时至少提供两个命令行参数。如果你选择使用HoG方法,一定要传递 --detection-method hog (否则它将默认为深度学习探测器deep learning detector)。

坚持一下,马上就成功啦!

使用OpenCV和Python识别人脸打开你的终端并执行我们的脚本:

$ python recognize_faces_image.py --encodings encodings.pickle \

--image examples/example_01.png

[INFO] loading encodings...

[INFO] recognizing faces...图5: Alan Grant和Ian Malcom的面孔被认可使用我们的Python + OpenCV +深度学习方法。

第二个人脸识别示例如下:

$ python recognize_faces_image.py --encodings encodings.pickle \

--image examples/example_02.png

[INFO] loading encodings...

[INFO] recognizing faces...图6:使用OpenCV和Python进行人脸识别。

识别视频中的脸部图7:通过Python,OpenCV和深度学习在视频中进行人脸识别。

现在我们已经将人脸识别应用于图像,我们也将人脸识别应用于视频(实时)。

关于性能的提醒:只有在使用GPU时(你可以将它与CPU配合使用,但期望低于0.5 FPS,这会造成choppy video),才能在实时视频使用CNN人脸识别器。如果你正在使用CPU,你应该使用HoG方法(甚至可以使用未来博客文章中介绍的OpenCV Haar级联),并期望有足够的速度。

下面的脚本与 recognize_faces_image.py有许多相同的地方。因此,不再赘述,现在只是审查视频组件,让你明白正在做的事情。

可以在本文结束下载代码,打开 recognize_faces_video.py,然后运行以下代码:

# import the necessary packages

from imutils.video import VideoStream

import face_recognition

import argparse

import imutils

import pickle

import time

import cv2

# construct the argument parser and parse the arguments

ap = argparse.ArgumentParser()

ap.add_argument("-e", "--encodings", required=True,

help="path to serialized db of facial encodings")

ap.add_argument("-o", "--output", type=str,

help="path to output video")

ap.add_argument("-y", "--display", type=int, default=1,

help="whether or not to display output frame to screen")

ap.add_argument("-d", "--detection-method", type=str, default="cnn",

help="face detection model to use: either `hog` or `cnn`")

args = vars(ap.parse_args())

我们在第2-8行导入包 ,然后继续解析第11-20行的命令行参数 。

我们有四个命令行参数,其中两个你应该认得( -encodings和 -detection-method)。另外两个参数是:- output:输出视频的路径。

- display:指示脚本将画面显示在屏幕上的标志,值1显示,值0不会将输出帧显示到我们的屏幕。

我们将加载我们的编码并启动我们的 VideoStream :

# load the known faces and embeddings

print("[INFO] loading encodings...")

data = pickle.loads(open(args["encodings"], "rb").read())

# initialize the video stream and pointer to output video file, then

# allow the camera sensor to warm up

print("[INFO] starting video stream...")

vs = VideoStream(src=0).start()

writer = None

time.sleep(2.0)

要访问我们的相机,我们使用imutils的 VideoStream类。 第29行开始视频流。如果系统上有多个摄像头(例如内置摄像头和外部USB摄像头),那你可以则可以将src = 0更改为 src = 1 等等。

稍后我们可以选择将处理后的视频帧写入磁盘,因此我们将writer初始化为None(第30行)。休眠2秒钟可以让我们的相机预热(第31行)。

从那里我们将开始一个 while 循环,并开始抓取和处理帧:

# loop over frames from the video file stream

while True:

# grab the frame from the threaded video stream

frame = vs.read()

# convert the input frame from BGR to RGB then resize it to have

# a width of 750px (to speedup processing)

rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

rgb = imutils.resize(frame, width=750)

r = frame.shape[1] / float(rgb.shape[1])

# detect the (x, y)-coordinates of the bounding boxes

# corresponding to each face in the input frame, then compute

# the facial embeddings for each face

boxes = face_recognition.face_locations(rgb,

model=args["detection_method"])

encodings = face_recognition.face_encodings(rgb, boxes)

names = []

我们的循环从第34行开始,我们的第一步是 从视频流中抓取一个frame(第36行)。

上述代码块中剩余的第40-50行几乎与前一脚本中的行相同,只是这是一个视频帧而不是静态图像。本质上,我们读取frame,预处理,然后检测面部边界boxes + 计算 每个边界框(bounding boxes)的econdings。

接下来,让我们循环 与我们刚刚找到的脸相关的脸部encodings:

# loop over the facial embeddings

for encoding in encodings:

# attempt to match each face in the input image to our known

# encodings

matches = face_recognition.compare_faces(data["encodings"],

encoding)

name = "Unknown"

# check to see if we have found a match

if True in matches:

# find the indexes of all matched faces then initialize a

# dictionary to count the total number of times each face

# was matched

matchedIdxs = [i for (i, b) in enumerate(matches) if b]

counts = {}

# loop over the matched indexes and maintain a count for

# each recognized face face

for i in matchedIdxs:

name = data["names"][i]

counts[name] = counts.get(name, 0) + 1

# determine the recognized face with the largest number

# of votes (note: in the event of an unlikely tie Python

# will select first entry in the dictionary)

name = max(counts, key=counts.get)

# update the list of names

names.append(name)

在这个代码块中,我们遍历每个 encodings 并尝试匹配脸部。如果找到匹配项,我们会为数据集中的每个名称计算增加投票数。然后我们提取最高的票数,这是与脸相关的名字。这些行 与我们回顾的前一个脚本完全相同,所以继续往下看。

在下一个区块中,我们循环识别的脸部,并继续绘制脸部周围的框以及脸部上方人物的显示名称:

# loop over the recognized faces

for ((top, right, bottom, left), name) in zip(boxes, names):

# rescale the face coordinates

top = int(top * r)

right = int(right * r)

bottom = int(bottom * r)

left = int(left * r)

# draw the predicted face name on the image

cv2.rectangle(frame, (left, top), (right, bottom),

(0, 255, 0), 2)

y = top - 15 if top - 15 > 15 else top + 15

cv2.putText(frame, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX,

0.75, (0, 255, 0), 2)

这些行也是相同的,所以我们来关注与视频相关的代码。

我们将把帧写入磁盘,让我们看看如何

# if the video writer is None *AND* we are supposed to write

# the output video to disk initialize the writer

if writer is None and args["output"] is not None:

fourcc = cv2.VideoWriter_fourcc(*"MJPG")

writer = cv2.VideoWriter(args["output"], fourcc, 20,

(frame.shape[1], frame.shape[0]), True)

# if the writer is not None, write the frame with recognized

# faces t odisk

if writer is not None:

writer.write(frame)

假设我们在命令行参数中提供了输出文件路径,并且我们尚未初始化视频writer(第99行),那么让我们继续并初始化它。

在第100行,我们初始化 VideoWriter_fourcc ,FourCC是一个4字符的代码,在我们的例子中,我们将使用“MJPG”4字符代码。

我们会将该对象连同我们的输出文件路径,每秒帧数目以及帧尺寸(第101和102行)一起传递到 VideoWriter。

最后,如果 writer 存在,我们可以继续写一个框架到磁盘(第106-107行)。

让我们来处理我们是否应该在屏幕上显示人脸识别视频帧:

# check to see if we are supposed to display the output frame to

# the screen

if args["display"] > 0:

cv2.imshow("Frame", frame)

key = cv2.waitKey(1) & 0xFF

# if the `q` key was pressed, break from the loop

if key == ord("q"):

break

如果我们显示的命令行参数已经设置好了,那我们继续前进,显示的画面(第112行),并检查是否退出键( “Q” )已被按下(第113-116行),这里我们是要 break 出循环(第117行)。

最后,让我们执行我们的清理一下显示器(housekeeping duties):

# do a bit of cleanup

cv2.destroyAllWindows()

vs.stop()

# check to see if the video writer point needs to be released

if writer is not None:

writer.release()

在第120-125行中,我们清理并释放显示,视频流和视频编写器。

你准备好看脚本们运行了吗?

为了演示使用OpenCV和Python实时进行人脸识别,请打开终端并执行以下命令:

$ python recognize_faces_video.py --encodings encodings.pickle \

--output output/webcam_face_recognition_output.avi --display 1

[INFO] loading encodings...

[INFO] starting video stream...

你可以在下面找到我录制的输出示例视频,演示面部识别系统的实际应用:https://www.zhihu.com/video/992354788100706304

视频文件中的人脸识别

正如我在我们提到的“脸部识别项目结构”部分中,有包含在其他脚本 recognize_faces_video_file.py(文章结束给出下载链接)。

这个文件基本上与我们刚刚为网络摄像头所查看的文件相同,只是它会采用输入视频文件并根据需要生成输出视频文件。

我将我们的脸部识别代码应用于原始侏罗纪公园电影中受欢迎的“午餐现场”,演员们围坐在一张桌子上,与公园分享他们的担忧:

$ python recognize_faces_video_file.py --encodings encodings.pickle \

--input videos/lunch_scene.mp4 --output output/lunch_scene_output.avi \

--display 0

结果如下:https://www.zhihu.com/video/992354278362595328

注:回想一下,我们的模型接受了原始演员中的四名成员的训练:艾伦格兰特,艾莉萨特勒,伊恩马尔科姆和约翰哈蒙德。该模型 没有接受唐纳德热纳罗(律师)的培训,因此他的脸被标记为“未知”。这种行为是通过设计(不是偶然的)来表明我们的人脸识别系统可以识别它所训练的脸部,同时留下它不能识别为“未知”的脸部。

在下面的视频中,我已经将侏罗纪公园和侏罗纪世界剪辑的“精彩片段”放在一起,主要来自预告片:https://www.zhihu.com/video/992354414820282368

正如我们所看到的,我们可以看到,我们的人脸识别和OpenCV代码工作得非常好!

总结

在本教程中,你学习了如何使用OpenCV,Python和深度学习进行人脸识别。

此外,我们利用Davis King的dlib库 和Adam Geitgey的face_recognition模块 ,这个模块包含了dlib的深度度量学习,使得面部识别更容易完成。

正如我们发现的那样,我们的人脸识别实现是:准确

能够通过GPU实时执行

如果需要数据集的话,再来私信我呀。

python模块cv2人脸识别_手把手教你使用OpenCV,Python和深度学习进行人脸识别相关推荐

  1. python深度文字识别_【OCR技术系列之四】基于深度学习的文字识别(3755个汉字)...

    上一篇提到文字数据集的合成,现在我们手头上已经得到了3755个汉字(一级字库)的印刷体图像数据集,我们可以利用它们进行接下来的3755个汉字的识别系统的搭建.用深度学习做文字识别,用的网络当然是CNN ...

  2. python高斯噪声怎么去除_手把手教你如何实现Python手势识别与控制(含代码及动图)...

    Python手势识别与控制 概述 本文中的手势识别与控制功能主要采用 OpenCV 库实现, OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库, 可以运行在Linux, Windows ...

  3. python画史迪仔_手把手教你如何使用Python来生成马赛克画!

    今天小伙伴问我,你知道什么是马赛克画,我笑了笑,你是说哪种哦?我知道一种,不过不是某些电影的马赛克哦~~ 马赛克画是一张由小图拼成的大图,本文的封面就是我们的效果图,放大看细节,每一块都是一张独立的图 ...

  4. python爬取网页文本_手把手教你如何用Python爬取网站文本信息

    提取网页源代码--Requests 工具包 在我们提取网络信息之前,我们必须将网页的源代码进行提取,Requests工具包现在可以说是最好用和最普及的静态网页爬虫工具,它是由大神Kenneth Rei ...

  5. 软件_手把手教vscode配置c++,python开发环境

    原创:软件_手把手教vscode配置c++,python开发环境 之前主用Python作为项目开发语言,将项目迁移到arm边缘盒子上后发现arm的cpu不给力,软件速度低于预期,所以计划将部分程序改为 ...

  6. python k线合成_手把手教你写一个Python版的K线合成函数

    手把手教你写一个Python版的K线合成函数 在编写.使用策略时,经常会使用一些不常用的K线周期数据.然而交易所.数据源又没有提供这些周期的数据.只能通过使用已有周期的数据进行合成.合成算法已经有一个 ...

  7. python 人脸识别_手把手教你用python实现人脸识别,识别率高达99.38%

    之前本人在实训时需要实现人脸识别这个功能,当时是借助百度的人脸识别api,这个需要注册账号,还需要用到密钥.操作起来也不麻烦,代码也不多.就是如果网速跟不上,返回的结果时,速度有点慢.当时也没那么在意 ...

  8. python处理时间序列非平稳_手把手教你用Python处理非平稳时间序列

    简介 预测一个家庭未来三个月的用电量,估计特定时期道路上的交通流量,预测一只股票在纽约证券交易所交易的价格--这些问题都有什么共同点? 它们都属于时间序列数据的范畴!如果没有"时间" ...

  9. 如何用python抓取qq音乐_手把手教你使用Python抓取QQ音乐数据(第三弹)-阿里云开发者社区...

    [一.项目目标] 通过手把手教你使用Python抓取QQ音乐数据(第一弹)我们实现了获取 QQ 音乐指定歌手单曲排行指定页数的歌曲的歌名.专辑名.播放链接. 通过手把手教你使用Python抓取QQ音乐 ...

最新文章

  1. [转载] 英语科技论文写作——Difference between APAMLA
  2. python基本语法总结-Python基本语法总结(二)
  3. vb6中使text控件的光标随着增加的内容向下移动
  4. leetcode 26 删除排序数组中的重复项
  5. The Preliminary Contest for ICPC China Nanchang National Invitational
  6. ajxs跨域 php_php设置header头允许ajax跨域请求
  7. ImageView相关
  8. 二进制文件签名_二进制数的签名表示
  9. ictclas4j 分词工具包 安装流程
  10. Jmeter4.X - 使用本身自带的脚本录制功能录制脚本
  11. HDOJ---1232 畅通工程[并查集]
  12. Arp病毒专杀工具下载及其防治解决方案
  13. IEEE极限编程:Word Ordering
  14. 机器学习 | 实战(二)Fashion-MNIST
  15. css全局加粗,CSS 实现矩形四个边角加粗的方法
  16. 【Python3.6爬虫学习记录】(十三)在阿里云服务器上运行爬虫
  17. 浅谈mysql的执行计划是何方神圣
  18. 计算机工程怎么评,美国电气与计算机工程专业怎么样?评价如何
  19. SqlServer遇到以零作除数错误
  20. 华为模拟器ensp ACL技术

热门文章

  1. VC创建进程CreateProcess的方法
  2. jQuery之Jcrop
  3. 供应商绩效管理指南:挑战、考核指标与管理工具
  4. linux快速扫ip段端口,手把手教你 3 个 Linux 中快速检测端口的小技巧
  5. python超市买苹果
  6. 【大咖有约】华泰证券管文琦:华泰证券分布式数据库演进之路
  7. Linux备份还原数据( dump、restore)
  8. 《中国新歌声》81位评审为何投出92票
  9. win7 计算机 只有硬盘分区,Win7磁盘分区只有盘符没有容量怎么办?
  10. 如何通过数据分析做到科学预测?