RBF在人脸动画中的运用

Posted by Packy on April 27, 2018

标签(空格分隔): 插值


RBF怎么用于facial animation

在通过face-fit获取人脸的特征点后,需要驱动模型运动来实现facial animation。今天和师兄讨论了一下,先实现三维点的驱动,通过face-fit获取到的特征点,然后人工添加其他点,通过特征点的运动,来插值出其他点的运动。

RBF插值的目的不是插值出特征点外的其他点,而是通过特征点的运动(e.g. $(\overrightarrow{\Delta x},\overrightarrow{\Delta y})$)来插值出其他非特征点的运动。

这几天一直卡在特征点的运动和插值上,怎么驱动三维人脸模型运动?这个问题先放到后面解决吧,这几天把rbf弄好。

初步的想法:

  1. 记录当前帧$(x_{current},y_{current},z_{current})$处相较于前一帧$(x_{pre},y_{pre},z_{pre})$的变化量,即$(\overrightarrow{\Delta x},\overrightarrow{\Delta y})$, 我们考虑由于变化幅度比较小,Z轴坐标不变化,$(\overrightarrow{\Delta x},\overrightarrow{\Delta y}) = (x_{current} - x_{pre}, y_{current} - y_{pre})$

  2. 可以得到一个$(x,y)$向$(\overrightarrow{\Delta x},\overrightarrow{\Delta y})$的映射函数,因为考虑到人脸的运动是可以分解为(x,y)的移动,两者应该是独立的(有个专业术语叫什么来着),所以可以分别对$f(x) = \overrightarrow{\Delta x}$ 和$f(y) = \overrightarrow{\Delta y}$进行一次一维rbf就可以得到拟合后的rbf函数,即可预测出任意(x,y)处的位移向量,但是这个方法的局限是,(x,y)的取值范围必须覆盖预测的点,比如x,从左边脸颊到右边脸颊的点可以覆盖到,但是y,只能覆盖从下巴到眉毛的y值,所以不能用来预测额头部位的特征点位移,但是由于本模型不考虑额头,所以问题应该不大,以上都是最近的一点想法,还没有得到实际验证,近段时间尽力完成吧!!

由于跟踪的特征点的数目不是很多,所以要对面部三维曲面的点进行扩充,由于人脸具有一定的对称性,先处理半边, 可以把两个对称点看做一组,然后进行线性插值即可,步长可以根据所需要插值的点的个数确定。这样可以获取到构成三维面部模型当前帧的所有点(特征点+插值点)。

后续(2018-4-27)

其实很快RBF的第一个版本就做出来了,思路和之前想的是一样的,在特征点之间先线性插值,增加一些非特征点,然后将特征点用RBF训练,得到的函数再来预测其他非特征点的运动,能明显的看到,非特征点的运动和特征点非常相似,具有特征点同样的能够表达“特征”的性质,所以理论上只要将模型上的所有点都用RBF预测一遍就能达到基本的插值效果。

之后将RBF运用到三维模型上,主要要解决的问题有两个:

  1. 如何修改模型的三维坐标(z轴不改变)
  2. 如何将所有点的信息传输到服务器(模型运动端)

在模型驱动方面,本项目使用的是Unity3d作为驱动平台,在unity3d中,模型可以以GameObject类存储,只要获取到其Mesh,就可以遍历Mesh中的三维向量。通过绑定特征点三维向量与通过RBF预测其他三维向量的位移,可以生成较为流畅的人脸动画。而RBF预测点的信息,考虑到网络通信的能力,不可能将所有点的坐标都传输到服务端,所以只需要传输RBF的参数就可以实现在异地预测点的位移。

在实践中遇到了一些实现细节的坑,比如RBF网络的训练,是通过特征点构成的$f(x) = \overrightarrow{\Delta x}$ 和$f(y) = \overrightarrow{\Delta y}$函数进行训练,得到拟合函数的的RBF参数。但是训练时,不能与之前所述的直接将像素坐标作为$x   y$进行训练, 因为我们是要用特征点的运动来预测模型上点的运动,有一个尺度变换问题,所以不能将 raw pixel infomation 放入RBF网络训练,而是需要将原始的像素坐标转换,得到相对坐标。本文的做法是每一帧计算RBF参数前,首先计算人脸的质心坐标$(x_{center},y_{center})$,然后所有点的坐标都减去质心坐标,得到一个相对于人脸质心的相对坐标。