Fine-Grained Head Pose Estimation Without Keypoints-论文解读

代码
论文

  1. Abstract
    传统的头部姿态计算方法是通过人脸上关键点求解二维到三维对应问题,因为对landmark 检测性能的依赖而导致存在不足。论文中提出一种基于多损失卷积神经网络的姿态估计方法。该方法通过联合分块姿态分类和回归,直接根据图像强度预测固有欧拉角(yaw,pitch,roll)。
  2. Introduction
    过去主要是基于discriminative/landmark和参数化外观模型parameterized appearance models方法进行人脸建模。目前,利用深度学习工具直接提取二维人脸关键点的方法因为其对遮挡和极端姿势变化的灵活性和鲁棒性成为面部表情分析的主流方法。在某些情况下头部整个姿态需要被估计,如果头部没有检测到足够多的关键点,并且三维头部模型质量以及变形计算成本高,这时候仅仅靠关键点的方法并不可用。本文提出的新方法正好可以解决这个问题,并且使用卷积神经网络从图像强度估计三维头部姿势具有更高精度。
  3. 相关工作
    在过去文献中,通常采用外观模板模型将测试图像与姿势样本进行比较以及面部探测器阵列方法(face detectors)。最近也有很多方法使用神经网络估计头部姿势,M. Patacchiola and A. Cangelosi.利用卷积神经网络回归损失训练和自适应梯度方法对头部姿态进行估计。A. Kumar, A. Alavi, and R. Chellappa.通过改进GoogleNet架构,学习有效的h-cnn回归器估计无约束人脸关键点和姿态。Hyperface是一个卷积神经网络,可以基于R-CNN的方法和改进AlexNet架构,融合了中间卷积层输出,添加全连接网络实现检测人脸,确定性别,发现landmark并且立即估计头部姿势。而用于人脸分析的All-InOne卷积神经网络增加了微笑、年龄估计和面部识别功能。Chang 等人使用一个简单的CNN回归3D头部姿态,并使用预测头部姿态用于面部对齐。Gu 等人使用VGG网络来回归头部姿态欧拉角,使用递归神经网络利用时间维度来改进姿态预测。这些方法和本文另一个区别就是数据集的处理。本文方法是在大型数据集上进行训练,并在各种外部数据集上测试网络性能,很好地展示了网络的泛化能力,可以更好地衡量模型如何在实际应用中推广。
  4. 方法


    该网络先在一个大的具有精确姿态标注的真实合成数据集上进行测试,在AFLW、AFLW2000、BIWI数据集上显示最新结果,然后在实际情况下准确地预测姿态。与landmark-to-pose方法相比,deep networks不依赖于选择头部模型、landmark检测方法、用于头部模型对齐的点子集或用于对齐2D到3D的优化方法。
    4.1多重损失法:
    在此之前的所有卷积网络预测头部姿态都是使用均方误差损失回归三个欧拉角,但是在大规模综合训练数据上并没有达到最佳效果。所以本文采用三个单独的loss,每个角度一个。每个损失都是一个二进制姿态分类和一个回归组合。每个backbone都可以通过三个全连接层扩展来预测角度,并且这三个全连接层共享网络先前的卷积层。该方法主要思想是使用稳定的softmax层和交叉熵进行分类,通过计算三个欧拉角的交叉熵损失,反向传播三个信号到网络中,计算每个输出角对二进制输出的期望值,获得细粒度预测(fine-grained predictions)然后再增加回归均方误差损失,改善细粒度预测。最后损失表现为两部分组合:
    L = H(y,yˆ)+ α · MSE(y,yˆ)
    其中y是角度的预测值,yˆ是真实值,H代表交叉熵损失。


网络结构如图所示,输入图像通过ResNet50主干网络得到特征,然后通过三个全连接层FC,作为yaw、pitch和roll的分类输入。在代码中交叉熵(CrossEntropyLoss)包含了softmax,分类时从-99到99,以3为间隔,共67个值,66个间隔,作为离散的分类,对这些使用交叉熵计算损失。再将softmax归一化后的特征作为概率和对应类别相乘求和计算期望,和实际角度计算MSE损失。
yaw, pitch, roll = model(images) # Forward pass,得到特征
loss_yaw = criterion(yaw, label_yaw) #Cross entropy loss 交叉熵分类损失,对应类别为0-65
yaw_predicted = softmax(yaw) # MSE loss 回归损失
离散型随机变量的一切可能的取值(idx_tensor)与对应的概率(yaw_predicted)乘积之和称为该离散型随机变量的数学期望:
yaw_predicted = torch.sum(yaw_predicted * idx_tensor, 1) * 3 – 99

预测值的总的期望和真实值计算回归损失:
loss_reg_yaw = reg_criterion(yaw_predicted, label_yaw_cont)
4.2 数据集处理:
首先使用AFLW2000数据集作为首选测试集,其次,使用设备记录不同受试者不同头部姿态视频,收集为BIWI数据集,将三维模型拟合到每个个体点云上,跟踪头部旋转生成姿态标注。采用300W-LP数据集综合扩展数据训练landmark检测模型,所有的图像都被扭曲改变脸部姿态。
4.3 低分辨率的影响:
在目前进行的对低分辨率对广泛使用的地标探测器和最先进的探测器的影响研究中,认为低分辨率会降低landmark的检测性能,因为在估计关键点时需要访问在低分辨率下消失的特征。除此之外对于远处的头部姿态估计还没有什么研究进展,如何使用深度学习讨论低分辨率头部姿态也还处于空白。直接根据图像强度预测姿态的深度网络提供了一个很好的候选方法,可以通过智能修改网络或增加训练数据建立鲁棒性。本文提出的方法就提高对低分辨率图像的鲁棒性,通过随即下采样和上采样增加数据,使网络学习不同分辨率,同时还通过模糊图像增加数据。
5. 实验结果
实验对不同的姿态估计数据集和landmark检测数据集进行了测试。结果表明,当分辨率较低时,即使landmark探测器是最先进的,使用深度网络的整体姿态方法也要优于landmark-to-pose方法。在AFLW2000和BIWI数据集上评估了论文方法,完成细粒度的姿态估计任务,并与使用两种不同的地标探测器FAN和Dlib以及groundtruth landmarks(仅适用于AFLW2000)从地标估计的姿态进行了比较。AFLW2000图像很小,在脸部周围裁剪。对于BIWI,运行了一个更快的R-CNN人脸检测器,它在更广泛的人脸数据集上进行训练,并部署在Docker容器中。最后还从AFLW2000的groundtruth landmarks中提取姿态。除此之外,还运行了3DDFA,它通过卷积神经网络将三维人脸模型直接拟合到RGB图像中。3DDFA的主要任务是使用一个密集的三维模型来对齐面部的标志点。
本文提出的方法大大缩小了RGBD方法和ResNet50之间的差距。Pitch估计仍然落后,部分原因是在300W-LP数据集中缺少大量的极端pitch示例。预计猜测是可以通过增加可用数据缩小差距。
6. 结论
本文证明了一个多损失深度网络可以直接准确并且鲁棒地从图像强度中预测头部姿态。而且这种网络优于使用最先进的路标检测方法的landmark-to-pose方法。同时还证明了所提出的方法在数据集上是通用的,并且在检测路标时,更优于将头部姿态作为子目标的网络。在分辨低的情况下,landmark-to-pose性能效果不佳,但如果适当增加训练数据,多损失网络更具有鲁棒性。
附录代码:测试指定文件目录下图片中人脸姿态欧拉角估计,输出三个角度

import sys, os, argparse
from functools import partialimport numpy as np
import cv2
import matplotlib.pyplot as pltimport math
import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
import torch.backends.cudnn as cudnn
import torchvision
import torch.nn.functional as F
from PIL import Image
import matplotlib.image as mp
from skimage import img_as_ubyteimport hopenetfrom torch.backends import cudnn
from torchvision import transforms
import utilsdef parse_args():"""Parse input arguments."""parser = argparse.ArgumentParser(description='Head pose estimation using the Hopenet network.')parser.add_argument('--gpu', dest='gpu_id', help='GPU device id to use [0]', default=-1, type=int)parser.add_argument('--snapshot', dest='snapshot', help='Path of model snapshot.',default='I:/GLJ/aliment/hopenet/output/snapshots/hopenet_robust_alpha1.pkl', type=str)args = parser.parse_args()return argsif __name__ == '__main__':args = parse_args()gpu = args.gpu_idif gpu >= 0:cudnn.enabled = True# ResNet50 structuremodel = hopenet.Hopenet(torchvision.models.resnet.Bottleneck, [3, 4, 6, 3], 66)  # 载入模型print('Loading snapshot.')if gpu >= 0:saved_state_dict = torch.load(args.snapshot)else:saved_state_dict = torch.load(args.snapshot, map_location=torch.device('cpu'))  # 无GPU的话,载入模型参数到CPU中model.load_state_dict(saved_state_dict)transformations = transforms.Compose([transforms.Resize(224),transforms.CenterCrop(224), transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])if gpu >= 0:model.cuda(gpu)model.eval()  # Change model to 'eval' mode (BN uses moving mean/var).total = 0idx_tensor = [idx for idx in range(66)]idx_tensor = torch.FloatTensor(idx_tensor)if gpu >= 0:idx_tensor = idx_tensor.cuda(gpu)yaw_error = .0pitch_error = .0roll_error = .0l1loss = torch.nn.L1Loss(size_average=False)# img_path = '7.jpg'# frame = cv2.imread(img_path, 1)# cv2_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)img_path = './Pose_input/'out_path = './Pose_output/'filelist = os.listdir(img_path)total_num = len(filelist)for i in range(total_num):# cv2_img = cv2.imread(os.path.join(img_path))cv2_img = img_path + str(i + 1) + '.jpg'cv2_img = mp.imread(cv2_img)img = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB)img = Image.fromarray(img)img = transformations(img)  # Transformimg_shape = img.size()img = img.view(1, img_shape[0], img_shape[1], img_shape[2])  # NCHW# img = torch.tensor(img)if gpu >= 0:img = img.cuda(gpu)yaw, pitch, roll = model(img)  # 得到特征 Forward pass_, yaw_bpred = torch.max(yaw.data, 1)_, pitch_bpred = torch.max(pitch.data, 1)_, roll_bpred = torch.max(roll.data, 1)# 特征归一化yaw_predicted = utils.softmax_temperature(yaw.data, 1)pitch_predicted = utils.softmax_temperature(pitch.data, 1)roll_predicted = utils.softmax_temperature(roll.data, 1)# 得到期望,将期望变换到连续值的度数yaw_predicted = torch.sum(yaw_predicted * idx_tensor, 1).cpu() * 3 - 99pitch_predicted = torch.sum(pitch_predicted * idx_tensor, 1).cpu() * 3 - 99roll_predicted = torch.sum(roll_predicted * idx_tensor, 1).cpu() * 3 - 99rows = cv2_img.shape[0]cols = cv2_img.shape[1]cv2_img = utils.draw_axis(cv2_img, yaw_predicted, pitch_predicted, roll_predicted, tdx=rows / 2,tdy=cols / 2, size=150)print(yaw_predicted.item(), pitch_predicted.item(), roll_predicted.item())# out_path = 'I:/GLJ/aliment/hopenet/output/Pose_output/'# cv2.imwrite('{}.png'.format(os.path.splitext(out_path)[0]), frame)out_img = out_path + str(i + 1) + '.png'result_img = Image.fromarray(cv2_img)result_img.save(out_img)# cv2.imwrite('{}.png'.format(os.path.splitext(out_path)[0]), cv2_img)

跑代码 一些坑
知乎解读

Hopenet人脸姿态估计相关推荐

  1. 无需人脸检测,实时6自由度3维人脸姿态估计img2pose

    效果图: 提出了一种实时的6自由度3D人脸姿态估计方法,其不依赖于人脸检测和关键点对齐.我们观察到直接估计6自由度刚体变换是一个比在3D人脸对齐中广泛使用的关键点检测更简单的问题.基于此我们做出了一下 ...

  2. 无需人脸检测,实时3维人脸姿态估计img2pose 2020

    提出了一种实时的6自由度3D人脸姿态估计方法,其不依赖于人脸检测和关键点对齐.我们观察到直接估计6自由度刚体变换是一个比在3D人脸对齐中广泛使用的关键点检测更简单的问题.基于此我们做出了一下几个贡献( ...

  3. 跳过人脸检测和关键点定位,Facebook等提出实时3D人脸姿态估计新方法

    本文转载自机器之心. 来自 Facebook AI 和美国圣母大学的研究者提出了一种 6 自由度的实时 3D 人脸姿态估计技术,可以不依赖人脸检测和人脸关键点定位独立运行. 人脸检测是给照片中的每个人 ...

  4. 人脸姿态估计(计算欧拉角)

    1.什么是人脸姿态估计问题 人脸姿态估计主要是获得脸部朝向的角度信息.一般可以用旋转矩阵.旋转向量.四元数或欧拉角表示(这四个量也可以互相转换).一般而言,欧拉角可读性更好一些,使用更为广泛.本文获得 ...

  5. 人脸姿态估计预研(二)

    人脸姿态估计预研(二) 1. 背景 为什么要写第二篇,因为第一篇写的很简单,自己的思考部分比较少,并且还有一些细节需要补充 2. 算法部分 2.1 到底使用多少个点? 这个确实是一个比较实在的问题,因 ...

  6. 人脸姿态估计(代码已跑通)

    人脸姿态估计主要是获得脸部朝向的角度信息.一般可以用旋转矩阵.旋转向量.四元数或欧拉角表示(这四个量也可以互相转换).一般而言,欧拉角可读性更好一些,使用更为广泛.本文获得的人脸姿态信息用三个欧拉角( ...

  7. 七点人脸姿态估计_Github开源库简单配置即可上线的3D人脸检测工具箱

    [导读]人脸识别/检测是计算机视觉方向的一个基础的任务.小编在Github中找到了一个轻松配置即可上线使用的3D人脸检测工具箱,该工具箱包括多种特性:2D稀疏点.稠密点.3D.深度图.PNCC.UV纹 ...

  8. 68个关键点如何提高人脸姿态检测的准确性?

    68个关键点如何提高人脸姿态检测的准确性? 随着深度学习技术的发展,人脸姿态估计逐渐成为计算机视觉领域的一个重要研究方向.而68个关键点是目前应用广泛的一种人脸姿态检测方法,它可以获取面部各个部位的坐 ...

  9. WACV 2021 论文大盘点-姿态估计篇

    本篇继续总结姿态估计相关论文, 3D 的占大多数,有 3D 姿势.形状估计,还有 3D 手部姿势估计.还有人脸姿态估计.跨物种姿态估计等. 共计 13 篇,如有遗漏,欢迎补充. 下载包含这些论文的 W ...

最新文章

  1. 大学计算机基础知识点_自学录——大学计算机基础
  2. mysql_08_子查询
  3. 10 Reasons Why Your Projects Should Use the Dojo
  4. uaredirect.js
  5. runtest的选项应用
  6. (王道408考研数据结构)第三章栈和队列-第四节:特殊矩阵压缩方式
  7. leetcode_Basic Calculator II
  8. 投简历没回音?你没写到点子上,HR当然不看
  9. OpenGL ES总结(五)OpenGL ES中pipeLine机制
  10. python将音频转换成文字_用Python将音频内容转换为文本格式
  11. His系统数据库服务器关系,his系统数据库服务器
  12. MacOS Aria2GUI配置
  13. m180n 如何设置网络打印_不难!简单几步教你搞定网络打印机添加设置
  14. 服务器电脑怎么样装系统,如何给服务器安装系统,是不是和PC机一样安装?
  15. 利用遥感影像阴影建筑物高度计算
  16. Ubuntu查看当前IP地址
  17. 实现iOS系统相机九宫格滤镜的思路
  18. 查看onedrive教育版或企业版的容量(有福利)
  19. 08_EMS项目之需求分析与界面搭建
  20. 互动百科与百度的百科大战对网络营销的影响

热门文章

  1. 将当前项目目录下的所有“.txt“文件复制一份,复制文件的名字格式:原文件名“_cp.txt“.
  2. 手机连上wifi却上不了网的原因
  3. python 生成器 是否为空 判断 generator
  4. SQLServer常用运维SQL整理(2)
  5. linux模块builtin是什么意思,使用linux的builtin命令执行bash内建命令
  6. Linux-系统管理-日志管理
  7. IOS视频编辑功能详解下篇-视频裁剪、视频拼接、音视频的处理
  8. 后台: sku商品多规格
  9. 如何点击按钮弹出新窗口,输入数据后返回并刷新页面
  10. react 路由鉴权