在开始检测和识别面部之前,您需要设置开发环境。首先,您需要先通过Python“读取”图像,然后再对其进行任何处理。我们将使用绘图库matplotlib来读取和操作图像。通过安装程序安装最新版本pip:
pip3 install matplotlib
要使用CNN算法的任何实现,您需要安装keras。使用以下命令下载并安装最新版本:
pip3 install keras
运行以下命令以通过以下方式安装软件包pip:
pip3 install mtcnn
从图像中提取人脸后,为了进行比较,我们将使用牛津大学视觉几何小组开发的VGGFace2算法。可将VGG算法的基于TensorFlow的Keras实现作为软件包安装,以供您安装:
pip3 install keras_vggface
尽管您可能需要构建和训练自己的模型,但您需要庞大的训练数据集和强大的处理能力。由于本教程重点介绍这些模型的实用性,因此它使用了本领域专家提供的经过培训的现有模型。
现在,您已经成功安装了先决条件,让我们直接进入本教程!
此步骤的目标如下:
很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:705933274
您可能经常根据托管在外部服务器上的映像进行分析。在此示例中,我们将使用两张图像,它们是野马之父Lee Iacocca托管在BBC和The Detroit News网站上的。
为了将图像临时存储在本地以供我们分析,我们将从其URL中检索每个图像并将其写入本地文件。store_image为此,我们定义一个函数:
import urllib.request
def store_image(url, local_file_name):
with urllib.request.urlopen(url) as resource:
with open(local_file_name, 'wb') as f:
f.write(resource.read())
现在,您可以简单地使用URL和您要在其中存储图像的本地文件来调用该函数:
store_image('https://ichef.bbci.co.uk/news/320/cpsprodpb/5944/production/_107725822_55fd57ad-c509-4335-a7d2-bcc86e32be72.jpg',
'iacocca_1.jpg')
store_image('https://www.gannett-cdn.com/presto/2019/07/03/PDTN/205798e7-9555-4245-99e1-fd300c50ce85-AP_080910055617.jpg?width=540&height=&fit=bounds&auto=webp',
'iacocca_2.jpg')
成功检索图像后,让我们检测其中的面孔。
为此,我们将进行两次导入-matplotlib读取图像和mtcnn检测图像中的人脸:
from matplotlib import pyplot as plt
from mtcnn.mtcnn import MTCNN
使用该imread()功能读取图像:
image = plt.imread('iacocca_1.jpg')
接下来,将一个MTCNN()对象初始化为detector变量,然后使用该.detect_faces()方法检测图像中的人脸。让我们看看它返回什么:
detector = MTCNN()
faces = detector.detect_faces(image)
for face in faces:
print(face)
对于每张脸,都会返回一个Python字典,其中包含三个键。该box密钥包含图像内的脸的边界。它具有四个值:左上角顶点的x和y坐标,包含面的矩形的宽度和高度。其他键是confidence和keypoints。该keypoints键包含一个字典,其中包含检测到的面部特征及其坐标:
{'box': [160, 40, 35, 44], 'confidence': 0.9999798536300659, 'keypoints': {'left_eye': (172, 57), 'right_eye': (188, 57), 'nose': (182, 64), 'mouth_left': (173, 73), 'mouth_right': (187, 73)}}
现在,我们已经成功检测到一张脸,让我们在其上绘制一个矩形以突出显示图像中的脸,以验证检测是否正确。
要绘制矩形,请Rectangle从导入对象matplotlib.patches:
from matplotlib.patches import Rectangle
让我们定义一个函数highlight_faces,该函数首先显示图像,然后在检测到的面部上绘制矩形。首先,通读图像imread()并通过进行绘制imshow()。对于检测到的每张脸,使用Rectangle()类绘制一个矩形。
最后,使用.show()方法显示图像和矩形。如果您使用的是Jupyter笔记本,则可以使用%matplotlib inlinemagic命令内联显示绘图:
def highlight_faces(image_path, faces):
image = plt.imread(image_path)
plt.imshow(image)
ax = plt.gca()
for face in faces:
x, y, width, height = face['box']
face_border = Rectangle((x, y), width, height,
fill=False, color='red')
ax.add_patch(face_border)
plt.show()
现在,使用highlight_faces()函数显示图像和检测到的面部:
highlight_faces('iacocca_1.jpg', faces)
在李·艾柯卡(Lee Iacocca)的图像中检测到脸部。资料来源:BBC
让我们显示第二张图像和其中检测到的脸部:
image = plt.imread('iacocca_2.jpg')
faces = detector.detect_faces(image)
highlight_faces('iacocca_2.jpg', faces)
在这两张图片中,您可以看到MTCNN算法正确检测到了脸部。现在,让我们从图像中提取该脸部以对其进行进一步分析。
在这一点上,您可以从检测器知道人脸的坐标。使用列表索引提取面部是一项相当容易的任务。但是,我们使用的VGGFace2算法需要将面部尺寸调整为224 x 224像素。我们将使用PIL库调整图像的大小。
该函数extract_face_from_image()从图像中提取所有面部:
from numpy import asarray
from PIL import Image
def extract_face_from_image(image_path, required_size=(224, 224)):
image = plt.imread(image_path)
detector = MTCNN()
faces = detector.detect_faces(image)
face_images = []
for face in faces:
x1, y1, width, height = face['box']
x2, y2 = x1 + width, y1 + height
face_boundary = image[y1:y2, x1:x2]
face_image = Image.fromarray(face_boundary)
face_image = face_image.resize(required_size)
face_array = asarray(face_image)
face_images.append(face_array)
return face_images
extracted_face = extract_face_from_image('iacocca_1.jpg')
plt.imshow(extracted_face[0])
plt.show()
这是从第一张图像中提取的脸部外观。
从第一张图像中提取并调整尺寸的脸部
在本节中,让我们首先在我们检索到的Lee Iacocca的两个图像上测试模型。然后,我们将继续比较切尔西足球队在2018年和2019年的前十一名球员的图像中的面孔。然后,您将能够评估该算法是否在图像之间识别出普通球员的面孔。
在本节中,您需要导入三个模块:VGGFace准备要提取的人脸以用于人脸识别模型,以及cosine来自SciPy的函数来计算两个人脸之间的距离:
from keras_vggface.utils import preprocess_input
from keras_vggface.vggface import VGGFace
from scipy.spatial.distance import cosine
让我们定义一个函数,该函数将提取的面部作为输入并返回计算出的模型得分。该模型返回一个向量,该向量表示脸部特征:
def get_model_scores(faces):
samples = asarray(faces, 'float32')
samples = preprocess_input(samples, version=2)
model = VGGFace(model='resnet50',
include_top=False,
input_shape=(224, 224, 3),
pooling='avg')
return model.predict(samples)
faces = [extract_face_from_image(image_path)
for image_path in ['iacocca_1.jpg', 'iacocca_2.jpg']]
model_scores = get_model_scores(faces)
由于每个人脸的模型得分都是向量,因此我们需要找到两个人脸的得分之间的相似性。我们通常可以使用欧几里得或余弦函数来计算相似度。
人脸的向量表示适合于余弦相似度。这是一个余弦与欧几里得距离的详细比较,并提供了一个示例。
该cosine()函数计算两个向量之间的余弦距离。这个数字越小,您的脸就越匹配。在我们的例子中,我们将阈值放在0.4远处。此阈值值得商and,并且会因您的用例而异。您应该根据数据集上的案例研究设置此阈值:
if cosine(model_scores[0], model_scores[1]) <= 0.4:
print("Faces Matched")
在这种情况下,Lee Iacocca的两张脸相吻合。
Faces Matched
让我们在教程的此部分中充分利用该模型。我们将在两张图片中比较面孔,这两张图片分别是在2018-19赛季与欧罗巴联赛对阵布拉格斯拉维亚的比赛中,切尔西足球俱乐部的十一岁开始以及在2019-20赛季对阵利物浦的欧洲足联超级杯的比赛中。尽管两个比赛日小队都有许多球员,但让我们看看该算法是否能够检测到所有普通球员。
首先,让我们从URL中检索资源,检测每个图像中的面孔并突出显示它们:
store_image('https://cdn.vox-cdn.com/thumbor/Ua2BXGAhneJHLQmLvj-ZzILK-Xs=/0x0:4872x3160/1820x1213/filters:focal(1877x860:2655x1638):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/63613936/1143553317.jpg.5.jpg',
'chelsea_1.jpg')
image = plt.imread('chelsea_1.jpg')
faces_staring_xi = detector.detect_faces(image)
highlight_faces('chelsea_1.jpg', faces_staring_xi)
store_image('https://cdn.vox-cdn.com/thumbor/mT3JHQtZIyInU8_uGxVH-TCbF50=/0x415:5000x2794/1820x1213/filters:focal(1878x1176:2678x1976):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/65171515/1161847141.jpg.0.jpg',
'chelsea_2.jpg')
image = plt.imread('chelsea_2.jpg')
faces = detector.detect_faces(image)
highlight_faces('chelsea_2.jpg', faces)
在继续进行之前,以下是两场比赛的前11名:
我们有8个玩家,这对于开始XI来说是共同的,并且理想情况下应该由算法进行匹配。
首先计算分数:
slavia_faces = extract_face_from_image('chelsea_1.jpg')
liverpool_faces = extract_face_from_image('chelsea_2.jpg')
model_scores_starting_xi_slavia = get_model_scores(slavia_faces)
model_scores_starting_xi_liverpool = get_model_scores(liverpool_faces)
``
for idx, face_score_1 in enumerate(model_scores_starting_xi_slavia):
for idy, face_score_2 in enumerate(model_scores_starting_xi_liverpool):
score = cosine(face_score_1, face_score_2)
if score <= 0.4:
print(idx, idy, score)
plt.imshow(slavia_faces[idx])
plt.show()
plt.imshow(liverpool_faces[idy])
plt.show()
这是算法匹配的两副面孔列表。请注意,它已经能够匹配所有八对面孔。
八张正确识别的面孔(Kepa,Azpilicueta,Emerson,Giroud,Kante,Pedro,Christensen,Kovacic)
虽然我们能够成功匹配图像中的每个面孔,但我想退后一步来讨论分数的影响。如前所述,没有将两个图像匹配在一起的通用阈值。您可能需要使用进入分析的新数据来重新定义这些阈值。例如,当无法通过编程确定一对最佳阈值时,即使Google Photos也会接受您的输入。
Google相册接受用户输入进行面部匹配
最好的方法是在匹配不同类型的面孔时仔细评估案例。面部的表情及其角度也决定了精度。在我们的用例中,请注意当玩家凝视相机时,我是如何故意使用开始的十一岁的照片的!您可以尝试将开始的11张面孔与奖杯庆典的面孔相匹配,我敢肯定,准确性会下降。
在本教程中,我们首先使用MTCNN模型检测图像中的人脸,并在图像中突出显示它们,以确定模型是否正常工作。接下来,我们使用VGGFace2算法以矢量的形式从面部提取特征,并匹配不同的面部以将它们组合在一起。