三、计算机视觉_05MTCNN人脸检测

embedded/2024/11/25 21:49:15/

0、人脸识别流程概述

人脸识别流程包括两个主要步骤:

  • Step1:人脸检测,确保我们处理的是正确的人脸区域

  • Step2:身份识别,确定该人脸的身份

0.1 人脸检测

人脸检测是从图像中定位人脸并抠出人脸区域的过程,这是人脸识别的第一步,用于确保后续的身份识别处理的是正确的人脸区域

因为人脸的类别少、形状比较固定、特征同样比较固定、周围环境也一般比较好,所以人脸检测其实是目标检测中最简单的任务

输入输出:

  • 输入:一张图像
  • 输出:所有人脸的坐标框

操作过程:

  • 抠图:用深度学习模型提取人脸图像中的特征,识别出人脸的位置,并将其抠出来
  • MTCNN:一种流行的人脸检测算法,通过三个阶段(P-NetR-NetO-Net)逐步精细化人脸检测结果

技术细节:(海选-->淘汰赛-->决赛)

  • P-Net:生成候选的人脸区域
  • R-Net:对P-Net的结果进行筛选和调整
  • O-Net:输出最终的人脸边界框和关键点位置

0.2 身份识别

身份识别是根据人脸图像判断其身份信息的过程,这一步骤通常涉及到人脸特征的提取和比较,所以比人脸检测稍复杂一点

操作过程

  • FaceNet:一种深度学习模型,用于从人脸图像中学习一个欧几里得空间中的嵌入表示,该表示可以用于直接比较人脸图像以确定身份
  • 人脸向量对比:将待识别的人脸图像通过FaceNet模型转换为向量,然后与数据库中存储的人脸向量进行比较,以确定身份

技术细节

  • 特征提取:使用FaceNet等深度学习模型提取人脸特征
  • 向量比较:使用余弦相似度等度量方法比较人脸向量的相似度
  • 阈值判断:设定一个阈值,当相似度超过这个阈值时,认为两个人脸是同一人

1、MTCNN简介

1.1 背景

MTCNN(Multi-task Cascaded Convolutional Networks)最初是在2016年由Kaipeng Zhang、Zhanpeng Zhang、Zhifeng Li 和 Yu Qiao 提出的,他们在论文《Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks》中介绍了这一算法,用于解决在无约束环境中人脸检测和对齐的挑战性问题(包括不同姿势、照明和遮挡的影响等问题)

1.2 概述

MTCNN是一种多任务级联卷积神经网络,它将人脸检测和人脸关键点定位结合起来,通过三个阶段的级联网络实现从粗到细的人脸检测过程

MTCNN的主要创新点在于将人脸检测和人脸关键点对齐相结合以提升检测指标,并对在线难样本挖掘(Online Hard Sample Mining,OHSM)算法进行了改进

1.3 网络结构

MTCNN由三个级联的网络组成:P-NetR-NetO-Net

(1)P-Net(Proposal Network):这是第一阶段,用于快速生成候选的人脸框(Bounding Boxes),特点:纯卷积网络,无全链接(精髓所在

P-Net接收输入图像,通过卷积层提取特征,然后利用几个简单的卷积层进行人脸分类和边框回归

P-Net会输出大量的候选框,这些候选框可能包含人脸,但也可能包含大量误检

(2)R-Net(Refine Network):这是第二阶段,用于对P-Net输出的候选框进行进一步筛选和调整

R-Net接收P-Net的候选框作为输入,通过更复杂的网络结构,对候选框进行更加细致的分类和边框回归

R-Net会去除大部分误检的候选框,并调整剩余候选框的位置和大小,使其更接近真实的人脸位置

(3)O-Net(Output Network):这是第三阶段,也是最复杂的网络

O-Net接收R-Net输出的候选框,通过更深层次的卷积神经网络处理人脸区域,优化人脸位置和姿态,并进行最终的人脸分类、边框回归以及人脸关键点的定位

O-Net的输出通常还可以用于后续的人脸识别、表情分析等任务

1.4 推理逻辑

MTCNN的推理逻辑如下:

Step1:输入一张图片(不限尺寸)MTCNN接受任意尺寸的输入图片

Step2:构建图像金字塔:为了检测不同尺度的人脸,MTCNN构建了一个图像金字塔,它会生成一系列不同尺寸的图像,以覆盖不同大小的人脸

Step3:遍历金字塔,取出每一个级别的图像:对于图像金字塔中的每个级别的图像,MTCNN执行以下步骤:

  • 把图像输入P-Net,得到P-Net的输出P-NetMTCNN的第一个阶段,它快速生成大量候选的人脸框,并给出人脸分类和边界框回归的初步预测

  • P-Net的输出,resize 24 × 24,输入R-Net,得到R-Net的输出P-Net的输出经过筛选和调整大小后,输入到R-Net,这是一个更为精细的网络,用于进一步筛选和调整人脸框的位置和大小

  • R-Net的输出,resize 48 × 48,输入O-Net,得到O-Net的输出R-Net的输出再次经过筛选和调整大小后,输入到O-Net,这是最终阶段的网络,用于精确地确定人脸框的位置和大小,并预测人脸关键点的位置

1.5 特点

  • 高效性:通过级联的网络结构,MTCNN能够在保证检测精度的同时,显著提高检测速度
  • 灵活性MTCNN可以适应不同尺寸和分辨率的输入图像,具有较强的鲁棒性

2、MTCNN关键技术

MTCNN在人脸检测中使用了图像金字塔、IOU和NMS这几个关键技术,以下是相关介绍:

2.1 图像金字塔

MTCNN利用图像金字塔技术来检测不同尺寸的人脸

由于P-Net的建议框大小是固定的,只能检测12x12像素范围内的人脸,为了能够检测到更大尺寸的人脸,MTCNN回通过不断缩小图片以适应建议框的大小,形成图像金字塔,当下一次图像的最小边长小于12像素时,停止缩放,这样不仅可以在不同尺度的图像上进行人脸检测,还可以提高检测的准确性和鲁棒性

2.2 IOU(交并比)

IOU在MTCNN中用于计算两个边界框之间的重叠程度,MTCNNO-Net阶段采用了两种方式计算IOU,以提高检测的准确性:

  • 方式一:交集比并集(也就是【交集】除以【并集】)

  • 方式二:交集比最小集(也就是【交集】除以【最小集】)

在处理大框套小框的情况时,第二种方式的IOU计算可以避免误检,因为这种方式更倾向于保留IOU值小的框(即:非重叠的框)

2.3 NMS(非极大值抑制)

NMS在MTCNN中用于去除预测结果中重复的边界框,保留最具代表性的边界框,以提高检测的准确性和效率

P-NetR-NetO-Net的每个阶段后,都会应用NMS来筛选出最终的边界框,其工作原理如下:

  • Step1:根据每个边界框的置信度进行排序

  • Step2:选择置信度最高的边界框,计算它与其他所有边界框的IOU

  • Step3:如果IOU超过预设的阈值,则认为这两个框表示的是同一个目标

  • Step4:在确定两个边界框表示同一个目标后,NMS算法会保留置信度(即检测到目标的概率)较高的那个边界框,并“抑制”或删除置信度较低的那个边界框

  • Step5:重复上述过程,直到所有边界框都被处理,得到最终的边界框

MTCNN论文中提到了RNet和ONet的NMS阈值,默认分别为0.7,这些阈值可以根据实际需要进行调整,从而控制边界框的重叠程度

3、P-Net网络结构分析与实现

P-Net的具体网络结构如下:

  • 输入层:12x12像素的RGB三通道彩色图像

  • 第一层卷积:使用10个3x3的卷积核,步长为1,边缘填充数为0,输出10x10x10的特征图【(12 + 2*0 - 3) / 1 + 1 = 10】

  • 第一层池化:3x3的最大池化,步长为2,边缘填充数为1,输出10x5x5的特征图【(10 + 2*1 - 3) / 2 + 1 = 5】

  • 第二层卷积:使用16个3x3的卷积核,步长为1,边缘填充数为0,输出16x3x3的特征图【(5 + 2*0 - 3) / 1 + 1 = 3】

  • 第三层卷积:使用32个3x3的卷积核,步长为1,边缘填充数为0,输出32x1x1的特征图【(3 + 2*0 - 3) / 1 + 1 = 1】

  • 输出层:

    • face classification(人脸分类,卷积):使用2个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • bounding box regression(边界框回归,卷积):使用4个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • Facial landmark localization(面部标志点坐标):使用10个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

P-Net的网络结构实现:

# 引入pytorch和nn神经网络
import torch
import torch.nn as nnclass PNet(nn.Module):"""自定义一个PNet网络"""def __init__(self, in_channels=3, n_classes=32):super().__init__()self.feature_extractor = nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=10, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=10),nn.PReLU(),nn.MaxPool2d(kernel_size=3,stride=2, padding=1),nn.Conv2d(in_channels=10, out_channels=16, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=16),nn.PReLU(),nn.Conv2d(in_channels=16, out_channels=n_classes, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=n_classes),nn.PReLU())# 人脸概率输出self.cls_out = nn.Conv2d(in_channels=n_classes, out_channels=2, kernel_size=1, stride=1, padding=0)# 人脸框输出self.reg_out = nn.Conv2d(in_channels=n_classes, out_channels=4, kernel_size=1, stride=1, padding=0)# 人脸关键点坐标输出self.local_out = nn.Conv2d(in_channels=n_classes, out_channels=10, kernel_size=1, stride=1, padding=0)def forward(self, x):"""前向传播"""# 1. 先做特征抽取x = self.feature_extractor(x)# 2. 再做分类回归cls_out = self.cls_out(x)reg_out = self.reg_out(x)local_out = self.local_out(x)return cls_out, reg_out, local_out

4、R-Net网络结构分析与实现

R-Net的具体网络结构如下:

  • 输入层:24x24像素的RGB三通道彩色图像

  • 第一层卷积:使用28个3x3的卷积核,步长为1,边缘填充数为0,输出28x22x22的特征图【(24 + 2*0 - 3) / 1 + 1 = 22】

  • 第一层池化:3x3的最大池化,步长为2,边缘填充数为1,输出28x11x11的特征图【(22 + 2*1 - 3) / 2 + 1 = 11】

  • 第二层卷积:使用48个3x3的卷积核,步长为1,边缘填充数为0,输出48x9x9的特征图【(11 + 2*0 - 3) / 1 + 1 = 9】

  • 第二层池化:3x3的最大池化,步长为2,边缘填充数为0,输出48x4x4的特征图【(9 + 2*0 - 3) / 2 + 1 = 4】

  • 第三层卷积:使用64个2x2的卷积核,步长为1,边缘填充数为0,输出64x3x3的特征图【(4 + 2*0 - 2) / 1 + 1 = 3】

  • 展平+全连接:将64x3x3的特征图展平,连接到128维向量

  • 输出层:

    • face classification(人脸分类,卷积):使用2个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • bounding box regression(边界框回归,卷积):使用4个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • Facial landmark localization(面部标志点坐标):使用10个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

R-Net的网络结构实现:

# 引入pytorch和nn神经网络
import torch
import torch.nn as nnclass RNet(nn.Module):"""自定义一个RNet网络"""def __init__(self, in_channels=3, n_classes=128):super().__init__()self.feature_extractor = nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=28, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=28),nn.PReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=False),nn.Conv2d(in_channels=28, out_channels=48, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=48),nn.PReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=False),nn.Conv2d(in_channels=48, out_channels=64, kernel_size=2, stride=1, padding=0),nn.BatchNorm2d(num_features=64),nn.PReLU(),nn.Flatten(),nn.Linear(in_features=3 * 3 * 64, out_features=n_classes))# 人脸概率输出self.cls_out = nn.Conv2d(in_channels=n_classes, out_channels=2, kernel_size=1, stride=1, padding=0)# 人脸框输出self.reg_out = nn.Conv2d(in_channels=n_classes, out_channels=4, kernel_size=1, stride=1, padding=0)# 人脸关键点坐标输出self.local_out = nn.Conv2d(in_channels=n_classes, out_channels=10, kernel_size=1, stride=1, padding=0)def forward(self, x):"""前向传播"""# 1. 先做特征抽取x = self.feature_extractor(x)# 2. 再做分类回归cls_out = self.cls_out(x)reg_out = self.reg_out(x)local_out = self.local_out(x)return cls_out, reg_out, local_out

5、O-Net网络结构分析与实现

O-Net的具体网络结构如下:

  • 输入层:48x48像素的RGB三通道彩色图像

  • 第一层卷积:使用32个3x3的卷积核,步长为1,边缘填充数为0,输出32x46x46的特征图【(48 + 2*0 - 3) / 1 + 1 = 46】

  • 第一层池化:3x3的最大池化,步长为2,边缘填充数为1,输出32x23x23的特征图【(46 + 2*1 - 3) / 2 + 1 = 23】

  • 第二层卷积:使用64个3x3的卷积核,步长为1,边缘填充数为0,输出64x21x21的特征图【(23 + 2*0 - 3) / 1 + 1 =21】

  • 第二层池化:3x3的最大池化,步长为2,边缘填充数为0,输出64x10x10的特征图【(21 + 2*0 - 3) / 2 + 1 = 10】

  • 第三层卷积:使用64个3x3的卷积核,步长为1,边缘填充数为0,输出64x8x8的特征图【(10 + 2*0 - 3) / 1 + 1 =8】

  • 第三层池化:2x2的最大池化,步长为2,边缘填充数为0,输出64x4x4的特征图【(8 + 2*0 - 2) / 2 + 1 = 4】

  • 第四层卷积:使用128个2x2的卷积核,步长为1,边缘填充数为0,输出128x3x3的特征图【(4 + 2*0 - 2) / 1 + 1 = 3】

  • 展平+全连接:将128x3x3的特征图展平,连接到256维向量

  • 输出层:

    • face classification(人脸分类,卷积):使用2个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • bounding box regression(边界框回归,卷积):使用4个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • Facial landmark localization(面部标志点坐标):使用10个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

O-Net的网络结构实现:

# 引入pytorch和nn神经网络
import torch
import torch.nn as nnclass ONet(nn.Module):"""自定义一个ONet网络"""def __init__(self, in_channels=3, n_classes=256):super().__init__()self.feature_extractor = nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=32, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=32),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=False),nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=False),nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=64),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=False),nn.Conv2d(in_channels=64, out_channels=128, kernel_size=2, stride=1, padding=0),nn.BatchNorm2d(num_features=128),nn.ReLU(),nn.Flatten(),nn.Linear(in_features=3 * 3 * 128, out_features=n_classes))# 人脸概率输出self.cls_out = nn.Conv2d(in_channels=n_classes, out_channels=2, kernel_size=1, stride=1, padding=0)# 人脸框输出self.reg_out = nn.Conv2d(in_channels=n_classes, out_channels=4, kernel_size=1, stride=1, padding=0)# 人脸关键点坐标输出self.local_out = nn.Conv2d(in_channels=n_classes, out_channels=10, kernel_size=1, stride=1, padding=0)def forward(self, x):"""前向传播"""# 1. 先做特征抽取x = self.feature_extractor(x)# 2. 再做分类回归cls_out = self.cls_out(x)reg_out = self.reg_out(x)local_out = self.local_out(x)return cls_out, reg_out, local_out

http://www.ppmy.cn/embedded/140486.html

相关文章

Flutter踩坑记录(一)debug运行生成的项目,不能手动点击运行

问题 IOS14设备,切后台划掉,二次启动崩溃。 原因 IOS14以上 flutter 不支持debugger模式下的二次启动 。 要二次启动需要以release方式编译工程安装至手机。 操作步骤 清理项目:在命令行中运行flutter clean来清理之前的构建文件。重新构…

贪心算法(2)

目录 K次取反后最大化的数组和 题解: 代码: 按身高排序(田忌赛马的预备) 题解: 代码: 方法一: 方法二: 优势洗牌(田忌赛马) 题解: 代…

Java项目实战II基于微信小程序的南宁周边乡村游平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着城市化…

Python 编程开发(01):Bash 命令行基本操作

Bash 是一种功能强大的 shell 语言(或命令行语言),广泛用于 Unix 和 Unix-like 操作系统,如 Linux 和 macOS。它提供了一个交互式界面,允许用户输入命令以执行各种操作,如文件管理、程序执行、网络配置等。…

MySQL 数据库连接池爆满问题排查与解决

目录 MySQL 数据库连接池爆满问题排查与解决 一、问题影响 二、问题确认 三、收集信息 四、SQL 语句分析 五、应用层代码分析 六、连接池配置检查 七、监控工具使用 八、案例分析 在实际的应用开发中,我们可能会遇到 MySQL 数据库连接池爆满的情况。这种情…

node.js中使用express.static()托管静态资源

express.static()定义 express.static(root, [options])是一个中间件函数,负责为Express应用提供静态资源服务。它允许你指定一个或多个目录作为静态资源的根目录,当客户端请求这些资源时,Express会查找并返回对应的文件。 安装express npm i…

周末总结(2024/11/24)

工作 人际关系核心实践: 要学会随时回应别人的善意,执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己,抬高别人(无阴阳气息) 朋友圈点赞控制在5min以内,职场社交不要放在5min以外 职场的人际关系在面对利…

计算机网络(14)ip地址超详解

先看图: 注意看第三列蓝色标注的点不会改变,A类地址第一个比特只会是0,B类是10,C类是110,D类是1110,E类是1111. IPv4地址根据其用途和网络规模的不同,分为五个主要类别(A、B、C、D、…