手把手教你使用Keras进行人脸检测和识别

先决条件

在开始检测和识别面部之前,您需要设置开发环境。首先,您需要先通过Python“读取”图像,然后再对其进行任何处理。我们将使用绘图库matplotlib来读取和操作图像。通过安装程序安装最新版本pip:

pip3 install matplotlib

要使用CNN算法的任何实现,您需要安装keras。使用以下命令下载并安装最新版本:

pip3 install keras

运行以下命令以通过以下方式安装软件包pip:

pip3 install mtcnn

从图像中提取人脸后,为了进行比较,我们将使用牛津大学视觉几何小组开发的VGGFace2算法。可将VGG算法的基于TensorFlow的Keras实现作为软件包安装,以供您安装:

pip3 install keras_vggface

尽管您可能需要构建和训练自己的模型,但您需要庞大的训练数据集和强大的处理能力。由于本教程重点介绍这些模型的实用性,因此它使用了本领域专家提供的经过培训的现有模型。

现在,您已经成功安装了先决条件,让我们直接进入本教程!

步骤1:使用MTCNN模型进行人脸检测

此步骤的目标如下:

  • 检索外部托管在本地服务器上的图像
  • 通过matplotlib的imread()功能读取图像
  • 通过MTCNN算法检测和探索人脸
  • 从图像中提取人脸。

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:705933274

1.1存储外部图像

您可能经常根据托管在外部服务器上的映像进行分析。在此示例中,我们将使用两张图像,它们是野马之父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')

成功检索图像后,让我们检测其中的面孔。

1.2检测图像中的人脸

为此,我们将进行两次导入-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)}}

1.3高亮显示图像中的面孔

现在,我们已经成功检测到一张脸,让我们在其上绘制一个矩形以突出显示图像中的脸,以验证检测是否正确。

要绘制矩形,请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()

这是从第一张图像中提取的脸部外观。

从第一张图像中提取并调整尺寸的脸部

步骤2:使用VGGFace2模型进行人脸识别

在本节中,让我们首先在我们检索到的Lee Iacocca的两个图像上测试模型。然后,我们将继续比较切尔西足球队在2018年和2019年的前十一名球员的图像中的面孔。然后,您将能够评估该算法是否在图像之间识别出普通球员的面孔。

2.1比较两张脸

在本节中,您需要导入三个模块: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

2.2比较两个图像中的多个面孔

让我们在教程的此部分中充分利用该模型。我们将在两张图片中比较面孔,这两张图片分别是在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名:

  • 斯拉维亚·布拉格(Slavia Prague)比赛开始XI:科帕(Kepa),阿兹皮里卡塔(Azpilicueta),路易斯(Luiz),克里斯滕森(Christensen),艾默生(Emerson),坎特(Kante),巴克利(Barkley),科瓦奇(Kovacic),危险,佩德罗(Pedro),吉鲁(Giroud)
  • 利物浦第十一比赛开始:科帕,阿兹皮里库塔,克里斯滕森,祖马,艾默生,坎特,约尔吉尼奥,科瓦奇,佩德罗,吉鲁德,普利西奇

我们有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算法以矢量的形式从面部提取特征,并匹配不同的面部以将它们组合在一起。

在这里还是要推荐下我自己建的Python学习Q群:705933274,群里都是学Python的,如果你想学或者正在学习Python ,欢迎你加入,大家都是软件开发党,不定期分享干货(只有Python软件开发相关的),包括我自己整理的一份2021最新的Python进阶资料和零基础教学,欢迎进阶中和对Python感兴趣的小伙伴加入!

猜你喜欢

转载自blog.csdn.net/m0_55479420/article/details/115268470