昇腾NPU人脸仿射变换性能优化

举报
李万俊 发表于 2021/10/21 19:30:52 2021/10/21
【摘要】 人脸仿射变换是人脸识别过程中常见人脸对齐的一处理手段。本文介绍利用Atlas的内置的算子实现在芯片上完成人脸仿射变换的计算过程。

人脸仿射变换是人脸识别过程中常见人脸对齐的一处理手段。本文介绍利用Atlas的内置的算子实现在芯片上完成人脸仿射变换的计算过程。

 

在人脸识别过程中,典型的流程先是对用一个目标检测模型检测画面是否包含人脸,如果是则把人脸从画面中扣出,由于在现实中捕获到的画面,人脸的姿态并不一定是正对镜头,所以需要做人脸对齐,把俯视、仰视等姿态矫正为正视的形态。

仿射变换是人脸对齐的一种方法,基本原理就是对在二维的平面里面做平移、变换、旋转等操作。由于我们客户通过模型获得到人脸的特征关键点,通过平移转换关键点就可以获得到对齐的人脸。

仿射变换的计算公式为


但是这里就不展开公式的说明,如果想深入了解,推荐阅读这篇文章 https://www.cnblogs.com/shine-lee/p/10950963.html

在实际项目中,我们只需要了解已知道人脸的关键点,通过这个公式达成人脸对齐的结果。

案例分享 

以下图为例子,

人脸对齐.jpg


画面中的人物侧身,第一步通过模型把人脸目标检测出来

人脸对齐_头像.jpg


找出画面中人脸的关键点,如下图

人脸对齐_头像1.jpg


通过5个关键点的位置,我们计算平移参数,然后通过仿射变换公式计算图片最终得到转换后的坐标

人脸对齐_头像3.jpg


 

在常见的GPU方案中,这个计算过程通常都是由CPU完成的。一张JPEG的图片需要先使用OpenCV解码成Bitmap位图,解码完成的BitmapHost保存一个副本,另外一份送入到GPU做模型推理,检测到人脸获取人脸区域框坐标以及关键坐标点返回到Host

Host通过对图片裁切,做仿射变换最后得到矫正的图片再送入GPU做下一步操作,整个如下图

GPU流程图.jpg


 

虽然仿射变换的计算资源消耗非常小,但是这个方案图片的搬移拷贝是一个相对耗时的操作,并且由于在CPU侧解码数据膨胀数倍再搬移到GPU,做完仿射变换后又做一次搬移,这部分会消耗非常多的资源。

 

对于这种场景昇腾NPU有什么更好的方案呢?

在昇腾NPU方案中,我们可以利用NPU上的媒体处理硬件模块DVPP,以及内置的SpatialTransformer算子结合把整个流程都在芯片内完成。

第一步需要先用昇腾ATC工具把内置的SpatialTransformer算子转换成OM文件,最后通过单算子调用的方式来完成人脸仿射变换。整体的流程如下

NPU方案.jpg


Host端把待处理的图片送入到NPU上,调用DVPP模型对图片解码,解码完成后送入人脸检测模型做推理得到人脸的矩形框坐标以及关键点坐标。Host侧获取推理结果,计算出人脸需要偏移的参数,Host调用DVPP图片裁切Crop的接口裁切图片,然后做为输入参数单算子调用SpatialTransformer

 

下面是详细的操作步骤

  • 使用ATC把内置算子SpatialTransformer转换成OM

SpatialTransformer的参数参考

https://support.huaweicloud.com/oplist-cann503alpha2infer/operatorlist_0056.html

算子SpatialTransformer需要输入两个参数

  • 参数x代表输入的图片,NCHW数据排布,数据类型是fp16或者fp32
  • 参数theta 代表的人脸的6个变换的参数θ
  • 输出参数y代表的是NCHW的张量

 

对于参数x,由于经过DVPP解码后的图片是YUV420SP的格式,在单算子调用时候需要AIPP做色域转换和归一化处理 

参数theta可以通过算子的属性描述,theta_1_1theta_1_2theta_1_3theta_2_1theta_2_2theta_2_3 一共6个 ,如果6个算子全部在属性里面设置那么,参数theta就不需要填写,这个方法的缺点是6个参数都是固定的不可以修改。

那么参数theta如何使用?实际它是描述参数的shape,格式是[n,size]

这个n代表的是batch sizesize代表参数的大小。举个例子,[1,2]标示batch size1 2标示有2theta参数的数组。

再举个例子,如theta_1_2=1theta_2_1=2theta_2_2=3theta_2_3=4 注意观察到这里4个参数通过算子的属性设置好了,但是有两个theta_1_1theta_1_3没有设置,那么我们输入参数thetashape [1,2] 其中2标示有2个参数,最后输入的数值如果是input theta=[9,8]9对应theta_1_18对应theta_1_3 则最终的theta: 9,1,8,2,3,4

 

同理,如果6theta都是动态需要参数输入,则参数theta 标示[1,6],我们在入参的数值只需要输入一个6个长度的数组

下面是SpatialTransformer单算子调用的参考文件,输入的是48x48的图片以及 数组长度为6theta参数

[
    {
      "op": "SpatialTransformer",
      "input_desc": [
        {
          "format": "NCHW",
          "shape": [1,3,48,48],
          "type": "float16"
        },
        {
          "format": "ND",
          "shape": [1,6],
          "type": "float16"
        }
      ],
      "output_desc": [
        {
          "format": "NCHW",
          "shape": [1,3,48,48],
          "type": "float16"
        }
      ]
    }
]

 使用ATC转换令转换单算子

 

atc --singleop=./op_list.json --output=./op_model --insert_op_conf=./aipp.cfg --soc_version=Ascend310

 

特别需要注意的是:目前SpatialTransformer对应CANN的最低版本要求是CANN 5.0.3 低于此版本的无法运行

 

  • 单算子调用

单算子调用的代码比较多,无法这里列出,需要参考

https://support.huaweicloud.com/aclcppdevg-cann503alpha2infer/atlasdevelopment_01_0103.html

 

 

最后,一些工程实现的细节

由于画面中检测出来的人脸框大小不固定,然后我们在单算子转换时候却是固定shape输入,比较简单的办法是设计多个不同参数的输入,比如40x40 48x48等待每个不同尺寸重新生成一个单算子模型

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。