What!吴恩达要参加美国大选?带你一起用人脸识别技术看看真的是吴恩达吗?

本文介绍了一种基于深度学习的人脸识别技术,使用吴恩达与杨安泽的照片作为案例,详细讲解了人脸检测、对齐、特征提取及相似度计算的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

What!吴恩达去参加美国大选了?最近几周,想必很多人都有看到这新闻,是不是在想吴恩达老师是不是有个双胞胎兄弟去参加美国大选了???

答案都不是,参选的是杨安泽,两人不仅长得像,英文名都叫Andrew,Andrew Yang(杨安泽)、Andrew Ng(吴恩达),下面是两个人的照片:
在这里插入图片描述

是不是分不清啊?没关系,接下来带你一起,用人脸识别技术判断是不是同一个人。

在上一篇文章中,我们介绍了实现人脸检测的两种方法,接下来要介绍的是人脸识别,通过对比两张人脸,计算其特征相似度,来判断是否是同一个人。

人脸识别模型

使用基于NN4改造的CNN模型训练和提取特征

nn4.small2.v1是FaceNet论文中描述的NN4模型的变体,在OpenFace的模型列表中有nn4.small2详细介绍,具体内容点击下方链接查看
https://cmusatyalab.github.io/openface/models-and-accuracies/#model-definitions

模型列表

ModelNumber of Parameters
nn4.small23733968
nn4.small15579520
nn46959088
nn27472144

本文使用Keras版本中的一种实现,模型定义在model.py
Keras版本的github地址:https://github.com/krasserm/face-recognition

Retrain人脸识别模型工作流程

1、加载训练数据集
2、人脸检测、对齐和提取(使用OpenFace的人脸对齐工具AlignDlib)
3、人脸特征向量学习(使用预训练的nn4.small1.v1模型)
4、人脸分类(使用KNN或SVM)

加载训练数据集

训练集组织形式

images目录中有3张图像,两张吴恩达(Andrew Ng)的照片,一张杨安泽(Andrew Yang)照片,放一起看两个人还是很像的。
在这里插入图片描述
最好是1:1比例,如果原图不是1:1比例,提取后的人脸会进行拉伸变换,仅支持.jpg和.jpeg两种格式。

# 加载训练数据集
import numpy as np
import cv2
import os.path

class IdentityMetadata():
    def __init__(self, base, file):
        self.base = base # 数据集根目录
        # self.name = name # 目录名
        self.file = file # 图像文件名

    def __repr__(self):
        return self.image_path()

    def image_path(self):
        return os.path.join(self.base, self.file) 

def load_metadata(path):
    metadata = []
    for f in os.listdir(path):
        # 检查文件名后缀,仅支持 jpg 和 jpeg 两种文件格式
        ext = os.path.splitext(f)[1]
        if ext == '.jpg' or ext == '.jpeg':
            metadata.append(IdentityMetadata(path, f))
    return np.array(metadata)

def load_image(path):
    img = cv2.imread(path, 1)
    # OpenCV 默认使用 BGR 通道加载图像,转换为 RGB 图像
    return img[...,::-1]

metadata = load_metadata('images')

人脸检测、对齐和提取

从原图提取96*96RGB人脸图像。

# 人脸检测、对齐和提取
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from align import AlignDlib

# 初始化 OpenFace 人脸对齐工具,使用 Dlib 提供的 68 个关键点
alignment = AlignDlib('landmarks.dat')


# 加载一张训练图像
img = load_image(metadata[0].image_path())
# 检测人脸并返回边框
bb = alignment.getLargestFaceBoundingBox(img)
# 使用指定的人脸关键点转换图像并截取 96x96 的人脸图像
aligned_img = alignment.align(96, img, bb, landmarkIndices=AlignDlib.OUTER_EYES_AND_NOSE)
# 绘制原图
plt.figure(1)
plt.subplot(131)
plt.imshow(img)
plt.xticks([])
plt.yticks([])
# 绘制带人脸边框的原图
plt.subplot(132)
plt.imshow(img)
plt.gca().add_patch(patches.Rectangle((bb.left(), bb.top()), bb.width(), bb.height(), fill=False, color='red'))
plt.xticks([])
plt.yticks([])
# 绘制对齐后截取的 96x96 人脸图像
plt.subplot(133)
plt.imshow(aligned_img)
plt.xticks([])
plt.yticks([])
plt.show()

人脸检测、对齐和提取的结果如下图所示
在这里插入图片描述

加载预训练模型nn4.small2.v1

我们从 OpenFace 提供的 预训练模型 中选择 nn4.small2.v1。

这些模型使用公开数据集 FaceScrub 和 CASIA-WebFace进行训练。Keras-OpenFace 项目将这些模型文件转换为 csv 文件,然后我们将其转换为 Keras h5 模型文件 nn4.small2.v1.h5。

预训练模型

Modelalignment landmarkIndices
nn4.v1openface.AlignDlib.INNER_EYES_AND_BOTTOM_LIP
nn4.v2openface.AlignDlib.OUTER_EYES_AND_NOSE
nn4.small1.v1openface.AlignDlib.OUTER_EYES_AND_NOSE
nn4.small2.v1openface.AlignDlib.OUTER_EYES_AND_NOSE

nn4.small2.v1.h5、model.py、align.py这些文件可以从下面github仓库获取:
https://github.com/krasserm/face-recognition

# 加载预训练模型nn4.small2.v1
from model import create_model

nn4_small2_pretrained = create_model()
nn4_small2_pretrained.load_weights('models/nn4.small2.v1.h5')


def align_image(img):
    return alignment.align(96, img, alignment.getLargestFaceBoundingBox(img), 
                           landmarkIndices=AlignDlib.OUTER_EYES_AND_NOSE)

embedded = np.zeros((metadata.shape[0], 128))

for i, m in enumerate(metadata):
    img = load_image(m.image_path())
    img = align_image(img)
    # 数据规范化
    img = (img / 255.).astype(np.float32)
    # 人脸特征向量
    embedded[i] = nn4_small2_pretrained.predict(np.expand_dims(img, axis=0))[0]

计算人脸特征的欧式距离,计算相似度

Squared L2 Distance(欧式距离),计算两个向量之间的距离。

在上一步,我们获得所有测试人脸的特征向量,我们可以通过计算其之间的距离,来判断人脸的相似度,距离越小,相似度越高。

# Squared L2 Distance
def distance(emb1, emb2):
    return np.sum(np.square(emb1 - emb2))

count = 0
def show_pair(idx1, idx2):
    global count
    count += 1
    plt.figure(num=count, figsize=(8,3))
    plt.suptitle(f'Distance = {distance(embedded[idx1], embedded[idx2]):.2f}')
    plt.subplot(121)
    plt.imshow(load_image(metadata[idx1].image_path()))
    plt.xticks([])
    plt.yticks([])
    plt.subplot(122)
    plt.imshow(load_image(metadata[idx2].image_path()))
    plt.xticks([])
    plt.yticks([])


show_pair(0, 1)
show_pair(0, 2)
show_pair(1, 2)
plt.show()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从上面三张结果图我们可以看到,两个吴恩达的照片人脸特征的欧式距离为0.09,吴恩达跟杨安泽的距离为0.33。

如何利用获得的距离来判断两个张照片上的人是否是同一个人?如果距离值低于某一阈值,则认为是同一个人。

如何确定阈值,一般通过大量已标记的测试值,阈值从小到大取值,计算获得识别的准确率,取准确率比较高阈值。

我们这里阈值取0.3,则可以判断测试的人脸1、2为同一个人,3为另一个人,但两个人长得很像。

完整代码:
https://github.com/Hanpeng-Chen/tensorflow-learning

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值