基于卷积网络的轻量级人脸关键点检测--惠晓伟

惠晓伟. 基于卷积网络的轻量级人脸关键点检测[D]. 黑龙江:哈尔滨工业大学,2018.

文章是一篇硕士论文,实现了一个以SqueezeNet为基础网络,基于多任务并行机制和网络预训练的77点人脸关键点检测网络,同时引入:

  • 区域注意力机制:本质时损失函数的权值自适应,有效缓解损失函数不平衡问题
  • 区域融合:吸收检测网络中global和local输出,并对结果进行继承,提高精度


0. 总结

1. 数据集

数据集使用300W数据集,但是300W数据集只有68关键点,所以添加了额头的9个点,共77个点。
在这里插入图片描述
为什么要包含额头关键点?

  • 没有额头的脸不算完美
  • 一些任务:皱纹检测、皮肤油干性分类等对额头有较高的相应

2. 第一次改进

  • 改进标准化均方误差
  • 改进人脸对齐方法
  • 使用预训练模型训练关键点检测算法

人脸关键点是一个多输出回归任务,为了更好的描述误差,使用的评价指标是传统均方误差衍生过来的标准化均方误差(NME),并且针对77关键点进行了改进。

为了简化模型,算法设计上,将主流的人脸检测和人脸对齐串行方案修改为多任务网络的并行机制。

为了提升精度,提出了一种基于网络微调的预训练方案。

2.1 改进的标准化均方误差

在这里插入图片描述
公式(3-2)是两眼之间的距离,参考这篇文章,实际上就是通过眼睛周围的关键点计算均值,得到瞳孔坐标点的纵坐标和横坐标。得到两个瞳孔的关键点坐标,再计算两瞳孔之间的距离。计算两个瞳孔间的距离使用的欧氏距离,也就是中学学的计算两点间的距离,但是加了根号的数值会增加计算量,所以使用欧氏距离的平方。

公式(3-3)是改进的标准化均方误差。 D D D为整个数据集。首先计算77个关键点预测值和真实值之间的平方 L 2 L_2 L2范数和。为了解决不同图像大小、不同人脸大小造成的损失不均衡问题,要对损失做标准化:除以双眼之间的距离,以此实现标准化。

因为整个脸和双眼睛的距离是有一定比例关系了,在图像中脸大则双眼距离宽,脸小则双眼距离小,所以无论图像种人脸大或者小,除以双眼间距后,就能避免当计算大小人脸误差时波动太大的情况。

2.2 人脸对齐

2.2.1 传统人脸对齐

人脸对齐可以保留人脸图像在空间上的对称性(比如左右眼睛、左右嘴巴),使得输入数据更加满足同计算同分布的前提,网络特征提取有会更有规律可循,泛化能力更强。
在这里插入图片描述
人脸对齐的本质原理其实就是仿射变换。只不过对于仿射变换需要的变换矩阵由卷积神经网络去回归得到。
在这里插入图片描述
如图,首先是人脸检测和人脸裁剪。对齐参数计算网络实际上就是回归仿射变换矩阵参数M的卷积神经网络,得到变换矩阵M(就是对齐参数)后,对原始人脸进行仿射变换,就得到对齐人类。

2.2.2 传统人脸对齐的弊端

  • 串行执行,复杂度高
    从上图可以看出人脸检测和人脸对齐的计算是串行执行的,并且得到变换矩阵后的仿射变换是元素级运算,时间和模型的复杂度大
  • 回归任务准确度难以保障
    人脸对齐的参数是通过回归网络来拟合的,回归是一种对数据敏感的任务,其得到的对其参数的准确度难以保障。
  • 人脸对齐和关键点检测串行,难以训练
    人脸对齐可以看成一个独立部分的卷积神经网络,但是在整个网络种的损失是利用关键点计算的误差进行训练,其对人脸对齐这个网络part的指导意义较小,难以训练好。

文中使用了MTCNN这个多任务框架来实现人脸检测和人脸对齐的多任务网络,方法图:
在这里插入图片描述
具体详情见论文。

2.3 基于并行机制和预训练的77关键点检测算法

本次实验使用的数据是77关键点的300W数据集,包含9个额头的人工标注关键点。
在这里插入图片描述
如图,红色框部分是人脸对齐,绿色框是关键点检测部分。

  • 首先使用多任务网络并行地进行人脸检测和对其角度回归。,然后使用图像地仿射变换将人脸对齐
  • 将对齐地人脸图像送入77点检测网络初步获取关键点位置。
  • 损失函数,由于数据集的监督信息对应的是原始人脸图像的关键点位置,所以要将预测结果做一次仿射变换回到原始的人脸位置。(因为关键点label是定位在原图上的,所以结果也应该仿射回原图,然后计算Loss)

为了提高77关键点的检测精度,还采用了预训练的68点检测模型和网络微调的方案:复制训练好的模型的前 n n n层,前 n n n层是特征提取层,将其他层随机初始化。在训练时可以分为冻结前 n n n层和不冻结前 n n n层(即微调)。本设计使用微调模式(不冻结前 n n n层)效果更好,原因如下:

  • 网络特征之间是有联系的,冻结会强制将网络分开,造成信息传递断层,不利于整个网络内的信息传递
  • 无法确定 n n n的最佳值,也就是不知道冻结层数n=几时,效果最好,需要耗时进行对比实验验证
  • 预训练是68点关键点,本设计是77点关键点,那么可能预训练网络更多关注68点,没有使用68点以外的监督信息,则这个预训练模型可能并不能更好的提取额外的9个关键点特征。所以如果冻结网络,则可能很难练出9个额头关键点的有效特征。

2.4 实验

2.4.1 网络结构和超参数

  • 人脸关键点检测部分的网络结构如下:
    在这里插入图片描述
  • 超参数:
    在这里插入图片描述

2.4.2 实验结果

  • 人脸对齐方法的模型储存空间对比
    在这里插入图片描述

  • 关键点检测误差(NME)
    在这里插入图片描述

3. 第二次改进

  • 修改轻量级网络结构,进行实验(使用SqueezeNet为关键点检测骨干网络)
  • 针对损失不均衡问题,引入区域注意力机制
  • 使用区域融合,吸收全局输出和局部输出优势,进行继承,进一步提高精度

3.1 骨干网络

文章介绍了MobileNet、SqueezeNet、ShuffleNet等轻量级网络,从下图可以看出,效果最好的其实是SqueezeNet,模型也是最小的。主要是ShuffleNet和MobileNet用来做速度提升,SqueezeNet却可以用来做特征提取。
在这里插入图片描述
用SqueezeNet为骨干网络的网络结构:
在这里插入图片描述

  • 网络开始时使用7*7卷积核,快速缩小特征图
  • 用平均池化替换全连接层
  • 对第一层输出添加了批正则化(BN层),缓解对Dropout层依赖,加快收敛速度

实验结果:
在这里插入图片描述

3.2 基于区域注意力和区域融合的轻量检测算法

3.2.1 区域注意力

人脸关键点检测的一个问题是,关键点的分布不均匀,有密集的区域,也有疏散的区域。如果使用MSE作为损失指标(对所有关键点的损失求均值),则对疏散区域的关键点训练效果更好,密集区域的关键点得不到充分的训练。区域注意力是则是为了缓解损失函数不均衡问题。

使用上式中的评价指标,会造成稠密分布的关键点的训练效果欠佳。在这里插入图片描述
一个直观的解决方法是对稠密关键点在损失函数中的权重,网络在训练时也要接受稠密分布关键点的约束,这样稠密关键点就可以得到更好的学习。区域注意力就是权值自适应。
本文的区域注意力设计如下:
在这里插入图片描述
上述两个FC层比一个FC层的优势在于:

  • 能产生更多的非线性操作
  • 更好拟合通道间的数据相关性
  • 很大程度减少参数量和计算量

效果:
在这里插入图片描述

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,以下是一个基于OpenCV和Python实现的CNN卷积神经网络人脸识别代码示例: ```python # 导入必要的库 import cv2 import numpy as np from keras.models import load_model # 加载已训练好的模型 model = load_model('model.h5') # 加载人脸级联分类器 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # 定义标签名称 labels_dict = {0: 'person1', 1: 'person2'} # 捕获视频流 cap = cv2.VideoCapture(0) while True: # 读取视频流的帧 ret, frame = cap.read() # 将图像转换为灰度图像 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 检测人脸 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5) # 处理每个检测到的人脸 for (x, y, w, h) in faces: # 提取人脸ROI roi_gray = gray[y:y + h, x:x + w] roi_gray = cv2.resize(roi_gray, (48, 48), interpolation=cv2.INTER_AREA) # 预处理图像数据 roi = np.array(roi_gray) roi = roi.reshape(-1, 48, 48, 1) roi = roi.astype('float32') roi /= 255 # 进行预测 predictions = model.predict(roi) label = np.argmax(predictions) # 在视频流中绘制人脸区域和标签 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(frame, labels_dict[label], (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2, cv2.LINE_AA) # 显示视频流的帧 cv2.imshow('Face Recognition', frame) # 按下q键退出程序 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放视频流和窗口 cap.release() cv2.destroyAllWindows() ``` 这是一个基于OpenCV和Keras框架实现的人脸识别例子,其中使用了一个训练好的CNN卷积神经网络模型,以及OpenCV的人脸级联分类器来检测人脸。你可以将此代码作为一个起点,并进行修改以满足你的具体需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是一个对称矩阵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值