使用 mtcnn 和 facenet 进行人脸识别

news2024/10/6 20:36:21

一、前言

人脸识别目前有比较多的应用了,比如门禁系统,手机的人脸解锁等等,今天,我们也来实现一个简单的人脸识别。

二、思维导图

三、详细步骤

3.1 准备

3.1.1 facenet 权重文件下载

下载地址:https://drive.google.com/drive/folders/1pwQ3H4aJ8a6yyJHZkTwtjcL4wYWQb7bn,下载 facenet_keras_weights.h5权重文件到本地。

3.1.2 依赖库安装

pip 安装库的时候如果太慢,设置软件源的地址为清华源,设置命令:

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
依赖库作用安装命令
OpenCV一个用于计算机视觉和图像处理的开源库。用于处理图像和视频。pip install opencv-python
mtcnn人脸检测的深度学习模型pip install mtcnn
tensorflow开源的机器学习框架pip install tensorflow
mysql-connector-python连接 mysql 数据库pip install mysql-connector-python
3.1.3 目录结构说明
├─docs 存放文档
├─encodings 存放本地图像特征值
├─facenet_model 存放 facenet 权重文件
├─font 存放简体字体
├─test_faces 测试集
├─train_faces 训练集
├─src 存放代码

3.2 训练人脸

3.2.1 人脸训练集准备

train_faces 文件夹下新建 hu_ge文件夹,然后从社交网络上获取胡歌图片放进去,作为训练集。

一张人脸生成的特征值显然是不够的,因此我们需要多张人脸,不考虑过拟合的情况下,人脸越多越精确。

3.2.2 加载模型

这边加载模型是 ResNetV2,没有引用库,而是手动去构建神经网络的,我尝试去直接使用 ResNet 库没成功,部分构建代码:

def inception_resnet_v2():
	inputs = Input(shape=(160, 160, 3))
	# 第一层是一个卷积层,应用了 32 个大小为 3x3 的滤波器
	x = Conv2D(32, 3, strides=2, padding='valid', use_bias=False, name= 'Conv2d_1a_3x3') (inputs)
	# 对输入进行批量归一化
	x = BatchNormalization(axis=3, momentum=0.995, epsilon=0.001, scale=False, name='Conv2d_1a_3x3_BatchNorm')(x)
	# 应用 ReLU 激活函数
	x = Activation('relu', name='Conv2d_1a_3x3_Activation')(x)
	x = Conv2D(32, 3, strides=1, padding='valid', use_bias=False, name= 'Conv2d_2a_3x3') (x)
	x = BatchNormalization(axis=3, momentum=0.995, epsilon=0.001, scale=False, name='Conv2d_2a_3x3_BatchNorm')(x)
	x = Activation('relu', name='Conv2d_2a_3x3_Activation')(x)
	x = Conv2D(64, 3, strides=1, padding='same', use_bias=False, name= 'Conv2d_2b_3x3') (x)
	x = BatchNormalization(axis=3, momentum=0.995, epsilon=0.001, scale=False, name='Conv2d_2b_3x3_BatchNorm')(x)
	x = Activation('relu', name='Conv2d_2b_3x3_Activation')(x)
	x = MaxPooling2D(3, strides=2, name='MaxPool_3a_3x3')(x)
	x = Conv2D(80, 1, strides=1, padding='valid', use_bias=False, name= 'Conv2d_3b_1x1') (x)
	x = BatchNormalization(axis=3, momentum=0.995, epsilon=0.001, scale=False, name='Conv2d_3b_1x1_BatchNorm')(x)
	x = Activation('relu', name='Conv2d_3b_1x1_Activation')(x)
	x = Conv2D(192, 3, strides=1, padding='valid', use_bias=False, name= 'Conv2d_4a_3x3') (x)
	x = BatchNormalization(axis=3, momentum=0.995, epsilon=0.001, scale=False, name='Conv2d_4a_3x3_BatchNorm')(x)
	x = Activation('relu', name='Conv2d_4a_3x3_Activation')(x)
	x = Conv2D(256, 3, strides=2, padding='valid', use_bias=False, name= 'Conv2d_4b_3x3') (x)
	x = BatchNormalization(axis=3, momentum=0.995, epsilon=0.001, scale=False, name='Conv2d_4b_3x3_BatchNorm')(x)
	x = Activation('relu', name='Conv2d_4b_3x3_Activation')(x)

这边就涉及到神经网络比较底层的知识,我也不太懂,我就直接使用了。
加载完模型后,加载 facenet 权重文件。
最后再加载 mtcnn 来识别人脸。

face_encoder = inception_resnet_v2()
facenet_weight_path = "../facenet_model/facenet_keras_weights.h5"
face_encoder.load_weights(facenet_weight_path)

face_detector = mtcnn.MTCNN()
3.2.3 读取图片、转换颜色空间

OpenCV 读取图片默认是以 BGR 颜色空间,如果我们要给 mtcnn识别人脸,要先转为 RGB 颜色空间。

# 读取图片
img_BGR = cv2.imread(image_path)
# 将一幅图像从 BGR(蓝绿红)颜色空间转换为 RGB(红绿蓝)颜色空间
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
3.2.4 mtcnn 识别人脸具体位置

MTCNN 是一种检测图像上的人脸和面部标志的神经网络。

x = face_detector.detect_faces(img_RGB)
print(x)

mtcnn 会生成人脸框的坐标和人脸上五个关键点的坐标,分别是左眼,右眼,鼻子,嘴唇的左边界,嘴唇的右边界。

{
  'box': [468, 98, 195, 249],
  'confidence': 0.9999933242797852,
  'keypoints': {
    'left_eye': (534, 190),
    'right_eye': (624, 186),
    'nose': (590, 236),
    'mouth_left': (549, 294),
    'mouth_right': (620, 291)
  }
}

显示一下:

# 人脸的框的左上角坐标和宽高
x1, y1, width, height = x[0]['box']
x1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + width, y1 + height
# 绘制人脸框
cv2.rectangle(img_BGR, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 绘制人脸关键点
for keypoint, coordinates in x[0]['keypoints'].items():
	cv2.circle(img_BGR, coordinates, 2, (0, 0, 255), -1)
# 显示
cv2.imshow('Detected Face', img_BGR)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 裁剪出人脸部分
face = img_RGB[y1:y2, x1:x2]
3.2.5 归一化、设置图片大小、生成图像特征值

归一化,将像素值从 [0, 255] 归一化到 [0, 1],如果训练的特征分布和测试的差异很大,那么对输入数据进行归一化,可以在训练和测试过程中保持一致的特征分布。

def normalize(img):
    """
    归一化处理:将数据缩放到均值为 0,标准差为 1 的标准正态分布
    像素值通常是在 0 到 255 的范围内。例如,将像素值从 [0, 255] 归一化到 [0, 1]。

    :param img:
    :return: 归一化结果
    """
    # 获取所有像素的平均值,标准差
    mean, std = img.mean(), img.std()
    return (img - mean) / std

face_encoder.predict(face_d)[0]这个函数可以对输入的人脸图像进行特征提取,我们这边只获取单张人脸的特征,所以取下标 0。

face = normalize(face)

# 重新设置大小
face = cv2.resize(face, required_shape)
# 扩展(增加)数组的维度
face_d = np.expand_dims(face, axis=0)
encode = face_encoder.predict(face_d)[0]
encodes.append(encode)

encode 只是一张图像的特征值,我们要训练很多张才能实现泛化效果比较好的模型,因此用 encodes 存放每一张图像的特征值。

3.2.6 特征求和、存放到数据库中
if encodes:
  # 特征求和
  # 计算每一列的总和
  encode = np.sum(encodes, axis=0)
  # 将特征向量标准化为单位向量
  encode = l2_normalizer.transform(np.expand_dims(encode, axis=0))[0]

  image_feature = base64.b64encode(encode).decode('utf-8')
  # 获取标签中文名 hu_ge -> 胡歌
  label_chinese_name = get_label_chinese_name(face_names)
  encoding_dict[face_names] = encode
  save_image_feature(face_names, label_chinese_name, image_feature)

3.3 测试人脸

将需要测试的人脸图片放在 test_faces 文件夹下,这四张都是全新的图片,模型不知道的,这样才可以进行预测。

也是对每一张图像生成人脸的特征值,然后和数据库中的特征值进行比较。

dist = cosine(input_feature, image_feature)

**在机器学习中,欧氏距离用于特征空间中样本之间的相似性度量,通过 ****cosine**函数计算相似度,只要小于相似度阈值,我们就认为属于同一张人脸。

原来我是设置成 0.5,可能由于训练的样本数太少,不是冯提莫的图片也会被认为是冯提莫,造成错误识别,它的值是 0.480.49 这样,后面我改成 0.4 就好了。
冯提莫和胡歌的人脸特征我提前训练好了,因此这边可以识别到,杨幂和宋轶没有训练,所以识别不到,显示未知。

四、参考资料

  • facenet
  • mtcnn
  • Face Detection using MTCNN

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1276798.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch:么是向量嵌入?

向量嵌入定义 向量嵌入 (vector embeddings) 是一种将单词、句子和其他数据转换为捕获其含义和关系的数字的方法。 它们将不同的数据类型表示为多维空间中的点,其中相似的数据点更紧密地聚集在一起。 这些数字表示可以帮助机器更有效地理解和处理这些数据。 单词和…

vue循环v-for遍历图表

循环遍历图表 index.vue主页面 <view v-if"powerPage"><view v-for"(item, index) in powerDetailsData.addMap" :key"index"><PowerEChartsCity:echartData"powerDetailsData.addMap[index]"></PowerEChartsC…

Linux Spug自动化运维平台本地部署与公网远程访问

文章目录 前言1. Docker安装Spug2 . 本地访问测试3. Linux 安装cpolar4. 配置Spug公网访问地址5. 公网远程访问Spug管理界面6. 固定Spug公网地址 前言 Spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台&#xff0c;整合了主机管理、主机批量执行、主机在线终端、文件…

mac安装elasticsearch

下载地址&#xff1a; Past Releases of Elastic Stack Software | Elastic https://www.elastic.co/cn/downloads/past-releases#elasticsearch 选择7.10版本 进入es bin目录下执行启动命令 ./elasticsearch 会报错 ./elasticsearch-env: line 126: syntax error near u…

Deckerfile

1.简介 dockerfile 是 docker 镜像构建文件。包含用于构建 docker 镜像的指令和配置。通过Dockerfile可以自动化地构建Docker镜像&#xff0c;实现快速、一致和可重复的部署。是由一条条构建镜像所需的指令和参数构成的脚本。指令按照从上到下&#xff0c;顺序执行&#xff0c…

flutter 自定义TabBar 【top 0 级别】

flutter 自定义TabBar 【top 0 级别】 前言一、基础widget二、tab 标签三、barView总结 前言 在日常开发中&#xff0c;tab 标签选项&#xff0c;是一个我们特别常用的一个组件了&#xff0c;往往我们在一个项目中&#xff0c;有很多地方会使用到它&#xff0c;每次单独去写&am…

20、Resnet 为什么这么重要

&#xff08;本文已加入“计算机视觉入门与调优”专栏&#xff0c;点击专栏查看更多文章信息&#xff09; resnet 这一网络的重要性&#xff0c;上一节大概介绍了一下&#xff0c;可以从以下两个方面来有所体现&#xff1a;第一是 resnet 广泛的作为其他神经网络的 back bone&…

L1-012:计算指数

⭐题目描述⭐ 真的没骗你&#xff0c;这道才是简单题 —— 对任意给定的不超过 10 的正整数 n&#xff0c;要求你输出 2n。不难吧&#xff1f; 输入格式&#xff1a; 输入在一行中给出一个不超过 10 的正整数 n。 输出格式&#xff1a; 在一行中按照格式 2^n 计算结果 输出 2n…

强化学习简明教程

到目前为止&#xff0c;我们主要关注监督学习问题&#xff08;主要是分类&#xff09;。 在监督学习中&#xff0c;我们得到某种由输入/输出对组成的训练数据&#xff0c;目标是能够在学习模型后根据一些新输入来预测输出。 例如&#xff0c;我们之前研究过 MNIST 的卷积神经网…

如何在 Ubuntu 22.04中安装 Docker Compose

1 安装 pip # 下载get-pip.py脚本 wget https://bootstrap.pypa.io/pip/3.10/get-pip.py 或者 # 下载最新版本 curl https://bootstrap.pypa.io/get-pip.py --output get-pip.py# 为 Python 3 安装 pip sudo python3 get-pip.py2 安装 Pip 后&#xff0c;运行以下命令安装 Doc…

2022年03月22日 Go生态洞察:泛型介绍

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【LeetCode:1094. 拼车 | 差分数组】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【开源】基于JAVA语言的校园电商物流云平台

项目编号&#xff1a; S 034 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S034&#xff0c;文末获取源码。} 项目编号&#xff1a;S034&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快…

重要通知丨 JumpServer 开源堡垒机 V2 社区版即将停止维护

尊敬的 JumpServer 开源堡垒机用户&#xff0c;您好&#xff01; 根据《关于 JumpServer 开源堡垒机 V2 版本产品生命周期的相关说明》&#xff0c;JumpServer 开源堡垒机 V2 版本&#xff08;社区版&#xff09;将于 2023 年 12 月 31 日停止维护支持。 在过去的两年多时间里…

JVM 类的加载

面试题&#xff1a; 简述 Java 类加载机制?&#xff08;百度&#xff09; JVM类加载机制 &#xff08;滴滴&#xff09; JVM中类加载机制&#xff0c;类加载过程&#xff0c;什么是双亲委派模型&#xff1f; &#xff08;腾讯&#xff09; JVM的类加…

导游服务职业技能竞赛常用赛制和流程

近年来&#xff0c;全国各地很多职校和文旅部门举办了各类导游服务职业技能竞赛&#xff0c;我公司为其中的知识竞答、评委评分提供软件和硬件支持。下面&#xff0c;用一场导游服务职业技能竞赛赛制流程来看这类竞赛的特点。 赛制安排 赛项内容由导游知识测试、景点讲解&…

11.30BST理解,AVL树操作,定义;快速幂,二分求矩阵幂(未完)

完全二叉树结点的度可能有1&#xff0c;满二叉树的度只能为0或2 BST构建 BST是左孩子都比根节点小&#xff0c;右孩子都比根节点大 二叉搜索树的插入&#xff0c;删除&#xff0c;调整 平衡树理解 任何一个平衡二叉树&#xff0c;它的中序遍历都是一样的&#xff0c;都是有…

0基础自学编程,中文编程工具下载,中文编程工具构件之扩展系统菜单构件教程

一、前言&#xff1a; 零基础自学编程&#xff0c;中文编程工具下载&#xff0c;中文编程工具构件之扩展系统菜单构件教程 编程系统化教程链接 https://jywxz.blog.csdn.net/article/details/134073098?spm1001.2014.3001.5502 给大家分享一款中文编程工具&#xff0c;零基…

三、Zookeeper数据模型

目录 1、Znode兼具文件和目录两种特点 2、Znode具有原子性操作

GPT实战系列-大模型训练和预测,如何加速、降低显存

GPT实战系列-大模型训练和预测&#xff0c;如何加速、降低显存 不做特别处理&#xff0c;深度学习默认参数精度为浮点32位精度&#xff08;FP32&#xff09;。大模型参数庞大&#xff0c;10-1000B级别&#xff0c;如果不注意优化&#xff0c;既耗费大量的显卡资源&#xff0c;…