1. 人脸关键点检测介绍

人脸关键点检测是检测人脸上的一些特征,通常检测点的数量为5,68,98点。
其流程为:输入一张图片->网络模型->关键点。
此博客以68点为例实现人脸关键点检测。
如图:

实现步骤:

  1. 获得到人脸图片以及其关键点坐标,也就是数据集。
  2. 数据处理
  3. 构建网络模型
  4. 训练模型
  5. 预测图片

2. 数据集

链接:https://pan.baidu.com/s/14W6OIU3h3FVwSEoEmlx8xA 提取码:bj9n
或者登录:https://aistudio.baidu.com/aistudio/datasetdetail/69065

3. 数据预处理

灰度化和数据归一化
由于是对人脸的特征点进行预测,对颜色是不敏感的,所以我们可以把图片进行灰度化处理,然后对图片进行归一化,再将将坐标点放缩到 [-1, 1]加快模型训练速度。
Resize和RandomCrop
将图片调整为指定大小并随机位置裁剪输入的图像,也就是数据增强。

4. 构建网络模型

我们使用mobilenetv2作为主干网络进行特征提取,只需在网络模型后面增加一层ReLU函数和一层输出为68的点的线性层即可。


from tensorflow.keras.layers import (Activation, BatchNormalization, Conv2D, DepthwiseConv2D, Dropout,ZeroPadding2D, Add, Dense,GlobalAveragePooling2D, Input, Reshape
)
from tensorflow.keras.models import Model
from tensorflow.keras import backend as Kdef correct_pad(inputs, kernel_size):img_dim = 1input_size = K.int_shape(inputs)[img_dim:(img_dim + 2)] # 224, 224if isinstance(kernel_size, int):kernel_size = (kernel_size, kernel_size) # 1,1if input_size[0] is None:adjust = (1, 1)else:adjust = (1 - input_size[0] % 2, 1 - input_size[1] % 2) # 1, 1correct = (kernel_size[0] // 2, kernel_size[1] // 2) # 0,0return ((correct[0] - adjust[0], correct[0]), (correct[1] - adjust[1], correct[1]))# 保证特征层为8得倍数
def _make_divisible(v, divisor=8, min_value=None):if min_value is None:min_value = divisornew_v = max(min_value, int(v + divisor / 2) // divisor * divisor)if new_v < 0.9 * v:new_v += divisorreturn new_vdef relu6(x):return K.relu(x, max_value=6)def Conv2D_block(inputs, filters, kernel_size=(3, 3), strides=(1, 1)):x = Conv2D(filters=filters, kernel_size=kernel_size, padding='valid',use_bias=False, strides=strides)(inputs)x = BatchNormalization(epsilon=1e-3,momentum=0.999)(x)x = Activation(relu6)(x)return xdef bottleneck(inputs, expansion, stride, alpha, filters):in_channels = K.int_shape(inputs)[-1]pointwise_conv_filters = int(filters * alpha)pointwise_filters = _make_divisible(pointwise_conv_filters, 8)x = inputs# 数据扩充x = Conv2D(expansion * in_channels,kernel_size=1,padding='same',use_bias=False,activation=None)(x)x = BatchNormalization(epsilon=1e-3,momentum=0.999)(x)x = Activation(relu6)(x)if stride == 2:x = ZeroPadding2D(padding=correct_pad(x, 3))(x)# 深度卷积x = DepthwiseConv2D(kernel_size=3,strides=stride,activation=None,use_bias=False,padding='same' if stride == 1 else 'valid')(x)x = BatchNormalization(epsilon=1e-3,momentum=0.999)(x)x = Activation(relu6)(x)# 1x1卷积用于改变通道数x = Conv2D(pointwise_filters,kernel_size=1,padding='same',use_bias=False,activation=None)(x)x = BatchNormalization(epsilon=1e-3,momentum=0.999)(x)if (in_channels == pointwise_filters) and stride == 1:return Add()([inputs, x])return xdef MobilenetV2(inputs, alpha=1.0, dropout=1e-3, classes=17):first_block_filters = _make_divisible(32 * alpha, 8)x = ZeroPadding2D(padding=correct_pad(inputs, 3))(inputs)x = Conv2D_block(x, filters=first_block_filters, kernel_size=3, strides=(2, 2))x = bottleneck(x, filters=16, alpha=alpha, stride=1, expansion=1)x = bottleneck(x, filters=24, alpha=alpha, stride=2, expansion=6)x = bottleneck(x, filters=24, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=32, alpha=alpha, stride=2, expansion=6)x = bottleneck(x, filters=32, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=32, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=64, alpha=alpha, stride=2, expansion=6)x = bottleneck(x, filters=64, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=64, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=64, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=96, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=96, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=96, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=160, alpha=alpha, stride=2, expansion=6)x = bottleneck(x, filters=160, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=160, alpha=alpha, stride=1, expansion=6)x = bottleneck(x, filters=320, alpha=alpha, stride=1, expansion=6)if alpha > 1.0:last_block_filters = _make_divisible(1280 * alpha, 8)else:last_block_filters = 1280x = Conv2D_block(x, filters=last_block_filters, kernel_size=1, strides=(1, 1))x = GlobalAveragePooling2D()(x)    x = Dropout(dropout, name='dropout')(x)x = Dense(1000)(x)x = Dense(512)(x)x = Activation('relu')(x)x = Dense(classes)(x)return xif __name__ == '__main__':inputs = Input(shape=(224,224,1))classes = 136model = Model(inputs=inputs, outputs=MobilenetV2(inputs=inputs, classes=classes))model.summary()

5. 训练模型

评估指标

人脸关键点一般是NMS作为评估指标,即所有预测点和真实标签之间的L2 Norm,在除以关键点的个数x两只眼睛的距离

            e=∑i=1N∣∣xi−xi∗∣∣2N×de=\frac{\sum^N_{i=1}||x_i - x^*_i||_2}{N \times d}e=N×d∑i=1N​∣∣xi​−xi∗​∣∣2​​

其中:
xix_ixi​为预测第iii个的坐标。
xi∗x^*_ixi∗​为第iii个真实标签。
ddd为距离,两眼瞳孔距离或者两眼外眼角距离。

def nme(y_true, y_pred):y_true = np.array(y_true, np.float32).reshape((-1, 2))y_pred = np.array(y_pred, np.float32).reshape((-1, 2))interocular = np.linalg.norm(y_true[36, ] - y_true[45, ])rmse = np.sum(np.linalg.norm(y_pred - y_true, axis=1)) / (interocular * y_pred.shape[0])return rmse

损失函数

使用SmoothL1Loss。

SmoothL1Loss对于离群点更加鲁棒,回归更好。

import tensorflow as tfdef SmoothL1Loss(delta=1.0):def _SmoothL1Loss(y_true, y_pred):loss = tf.keras.losses.huber(y_true, y_pred, delta=delta)loss = tf.reduce_mean(loss)return lossreturn _SmoothL1Loss

6. 预测图片

效果如下:

7. 代码仓库

gitee地址:https://gitee.com/Hao_gg/facekeypoints-tf2
github地址:https://github.com/hao-ux/facekeypoints-tf2

tensorflow2.x实现人脸关键点检测相关推荐

  1. Tensorflow2实现人脸关键点检测算法PFLD——一个精度高,速度快,模型小的人脸关键点检测模型

    1. 前言 最近,学了人脸关键点检测算法,发现一个比较好的人脸关键点检测模型,打算学一学,让我们来看看算法是如何实现的吧! 论文地址:https://arxiv.org/pdf/1902.10859. ...

  2. 【机器视觉案例】(11) 眨眼计数器,人脸关键点检测,附python完整代码

    各位同学好,今天和大家分享一下如何使用 mediapipe+opencv 实现眨眼计数器.先放张图看效果. 下图左侧为视频图像,右侧为平滑后的人眼开合比曲线.以左眼为例,若眼眶上下边界的距离与左右边界 ...

  3. 「每周CV论文推荐」 初学深度学习人脸关键点检测必读文章

    人脸关键点检测是人脸图像中重要的基石,今天给大家介绍入门深度学习人脸关键点检测必读的文章. 作者&编辑 | 言有三 1 DCNN Cascade 听这个名字就知道是一个很早期的,使用Casca ...

  4. python人脸识别、人脸关键点检测、性别检测

    python人脸识别.人脸关键点检测.性别检测 文章目录 根据人脸预测年龄性别和情绪 (python + keras)(三) 一款入门级的人脸.视频.文字检测以及识别的项目. age-gender-e ...

  5. CNN人脸关键点检测

    CNN人脸关键点检测 参考文献<Deep Convolutional Network Cascade for Facial Point Detection>\ 摘要 提出一种利用精心设计的 ...

  6. 使用OpenCV进行人脸关键点检测

    使用OpenCV进行人脸关键点检测 1 双脸效果 2 单脸效果

  7. 人脸识别,人脸关键点检测算法

    from http://blog.csdn.net/sloanqin/article/details/48193119 1 Face++:http://www.faceplusplus.com.cn/ ...

  8. 【CV秋季划】人脸关键点检测,人脸识别视频更新

    本次给大家带来的是有三AI-CV秋季划-人脸算法组的视频,包括人脸关键点检测,人脸识别两期的内容,如果你还不知道有三AI-CV秋季划-人脸算法组是什么,可以看下面的视频和图文. 点击边框调出视频工具条 ...

  9. 【每周CV论文推荐】 初学深度学习人脸关键点检测必读文章

    欢迎来到<每周CV论文推荐>.在这个专栏里,还是本着有三AI一贯的原则,专注于让大家能够系统性完成学习,所以我们推荐的文章也必定是同一主题的. 人脸关键点检测是人脸图像中重要的基石,今天给 ...

最新文章

  1. c++重载(以运算符重载为主)
  2. 技术系列课|“主动降噪”到底有多厉害?
  3. 删除表报正在使用_U盘拔出要不要点quot;安全删除USB硬件quot;退出?
  4. 一个简单的parser
  5. C++学习之路 | PTA乙级—— 1017 A除以B (20分)(精简)
  6. 如何通过svg代码还原图片_如何通过nginx反向代理来调试代码?
  7. 近9分的生信杂志发了一篇Venn图工具大比拼
  8. python爬虫去重_Python网络爬虫(7):URL去重
  9. 纺织品GRSlogo使用标准 GRS认证的详情概括
  10. 使用R进行pubmed爬虫
  11. 中兴通讯携手CLAA合作伙伴,开创共享共建物联网新时代
  12. 解决Word导出PDF显示有批注的问题
  13. 汇编命令及OD常用命令及断点设置
  14. 惠斯登电桥传感器电路设计技巧,了解一下?
  15. 人工智能行业研究:史上最伟大的科技革命
  16. IPAD密码试错停用了怎么办?教你用正规iTunes刷机恢复,解决忘记密码的问题!以及C盘瘦身的最实用技巧
  17. 电脑直接安装apk至手机(usb连接)
  18. 数据结构——用栈实现后缀表达式的计算
  19. webpack 处理字体_如何在webpack中更优雅的处理字体图标
  20. 高低温真空磁场探针台T8-EM5的技术参数

热门文章

  1. 硬盘SMART参数(05,C5)与(C7)解惑
  2. Redis 中的 集合(Set)SREM:从集合中移除元素 忽略不存在的元素
  3. HDU-圆桌会议问题
  4. pythonrequests请求https错误_如何解决python之requests安全证书(HTTPS请求)问题?
  5. 绘画教程:日式温泉场景怎么画?露天浴场的正确画法!
  6. 让 QQ 邮箱更好用,支持桌面通知
  7. 西门子PLC中的累加器 ACCU1/2的个人理解
  8. python如何裁剪图像
  9. vue项目json格式化显示
  10. 任务栏WPS出现多窗口预览?下载这个注册表就对了