AR Camera开发记录(二) -- 3D人脸模型

AR Camera开发记录(一) – Rajawali的使用末尾的部分,介绍了如何动态修改模型的顶点坐标。
那个例子是用一个最简单的矩形平面模型来说明的。
说白了就是找到需要修改的顶点,然后设置新的坐标值。
而对于3D人脸模型来说,情况要复杂一些,想找到需要的顶点相对来说比较麻烦。
本文主要说一下动态修改3D人脸模型会遇到的问题,以及在了解了这些问题之后如何自己创建3D人脸模型。

要注意的问题

首先说明下,笔者的项目中用到的3D人脸模型的格式为Obj。
在Rajawali库的wiki页面中有如下说明:

The most important thing is that the model should be triangulated.
Rajawali doesn’t accept quads, only tris. In Blender, this is an option you can select in the exporter.
In a program like MeshLab, this is done automatically.

意思就是在Rajawali中,Obj模型只支持由三角形的面组成,不支持四边形的面。

而上一篇文章用到的矩形平面模型不同,它是Rajawali内置的,支持四边形。
我们把它的顶点坐标读出来看,也确实是一个用4个顶点组成的四边形的面。
因此在处理3D人脸模型的顶点的时候就有差异了。

再来看看这张来自opengl-tutorial的教程图例:
这里写图片描述

这张图左边部分,说的是OpenGL在没有使用索引缓冲(index buffer)的情况下,每个三角形需要由3个顶点组成,两个三角形总共需要6个顶点。而右边部分使用索引缓冲,复用了公共点v1和v2,两个三角形只需4个顶点。

Rajawali解析出来的Obj模型的顶点组成是按左边的方式。
那么在修改Obj模型顶点坐标的时候就要注意了,模型中有些线段相交的地方,看上去是一个公共顶点,实际上不止一个。

下面来看看具体示例。
在Blender中创建一个由两个三角形组成的四边形:
这里写图片描述

在Rajawali中加载这个模型,然后读取各个顶点坐标,得到如下位置关系:
这里写图片描述
这里把两个三角形分开一些是为了看清楚,实际上v0和v4、v2和v5是重合在一起的。

如果像上一篇文章那样,想让左上角的顶点坐标动态变化,只修改v0是不对的。
下面看看代码:

@Override
protected void onRender(long ellapsedRealtime, double deltaTime) {
    long time = ellapsedRealtime / 10000000;
    double amp = 0.5 * Math.sin(Math.PI * time / 180.0);

    FloatBuffer vertBuffer = mGeometry3D.getVertices();
    // 修改v0的y坐标,即第1个数据,赋值为amp
    vertBuffer.put(1, (float) (amp));
    mGeometry3D.changeBufferData(mGeometry3D.getVertexBufferInfo(), vertBuffer, 0, vertBuffer.limit());
}

效果如下:
这里写图片描述

可以明显看到,只修改v0的话,只影响了左下方的三角形,右上方的三角形没有变化。
因此还得把v4也一起修改,才能达到预想的效果:

    FloatBuffer vertBuffer = mGeometry3D.getVertices();
    // 修改v0的y坐标,即第1个数据,赋值为amp
    vertBuffer.put(1, (float) (amp));
    // 修改v4的y坐标,即第13个数据,赋值为amp
    vertBuffer.put(13, (float) (amp));

修改后的效果如下:
这里写图片描述

创建3D人脸模型

搞清楚上面的问题后,我们开始创建3D人脸模型。
如何建这个人脸模型,跟使用到的人脸检测技术有关。
比如Dlib返回68个关键点,Face++或SenseTime等返回106个关键点:
这里写图片描述这里写图片描述

至于怎么根据这些关键点去构成人脸模型,估计是跟面部肌肉的牵拉有关,笔者也没搞懂,就找了别人的来参考:
这里写图片描述
视频地址

然后就是依样画葫芦,对关键点进行连线,线与线再组成面:
这里写图片描述这里写图片描述

如何获得顶点顺序

从前文可知,在Rajawali中加载这个人脸模型的话,每个相邻的三角形面相交的地方,不共用顶点。
如果想修改这个相交点的话,必须把组成这些相邻的三角形的点都找出来。人工去找显然不实际。因此本节内容主要是要解决这个问题。

我们先来看看这个人脸模型的顶点顺序。
这里笔者用了另一个软件MeshLab来查看。
打开模型以后,点击上方工具栏的Render,再在其下拉菜单中点击ShowLabels,就会显示模型每个顶点的序号:
这里写图片描述
这里的序号起始是从0开始的。从图中可知模型左眼角的顶点序号是20。

我们再用文本编辑器打开Obj模型文件,找到以“f”开头的部分:

...省略...
f 23/1/1 21/2/1 31/3/1
f 23/1/2 24/4/2 21/2/2
f 24/4/3 25/5/3 21/2/3
f 25/5/4 26/6/4 21/2/4
f 21/2/5 26/6/5 6/7/5
...省略...

每一行f描述一个面由哪些点组成的。
f后面有三组数字,每组由三个数字组成,以斜杠隔开。
每组的第一个数字是顶点的序号,第二个数字是贴图坐标点的序号,第三个数字是顶点法线的序号。

我们暂时只关注第一个数字,即顶点的序号。这里的序号起始是从1开始的。
以第一行数据为例:

f 23/1/1 21/2/1 31/3/1

表示由第23、21和31的顶点组成一个三角面。
也就是上图这个位置的面:
这里写图片描述

以此类推,结合Obj文件和MeshLab可以看到,人脸模型的左眼角位置,是9个三角形的公共点。
也就是说,要在Rajawali中修改这个位置的顶点的话,需要改9个点:
这里写图片描述

先人工找一下这9个点。
把Obj文件中以”f”开头的行找出来,去掉其他部分,只保留顶点序号:

...省略...
23
21
31
23
24
21
24
25
21
25
26
21
21
26
6
...省略...

那么含有21(左眼角位置)的点的顺序就是:
2,6,9,12,13…省略

要人工找这9个点的顺序就太费劲了,但如果用代码来找的话,其实也很简单。
笔者用Python写了两个方法来找:

# 获取顶点列表
# path是Obj文件的路径
def read_obj_indices(path):
    indices = []
    with open(path, 'r') as f:
        lines = f.readlines()

        for line in lines:
            data = line.split()
            prefix = data[0]
            # 获取以'f'开头的行
            if prefix.startswith('f', 0, len(prefix)):
                # 去掉'f'
                data.remove('f')
                for element in data:
                    # 找到第一个'/'的位置
                    pos = element.index('/')
                    # 截取'/'之前的部分,即顶点的序号
                    element = element[0:pos]
                    indices.append(element)

    return indices
# 对顶点序号进行排序
# indicess是上一个方法获取的顶点列表
# size是顶点数量
def order_obj_indices(indices, size):
    lists = [[] for t in range(size)]

    i = 1
    for index in indices:
        lists[int(index) - 1].append(i)
        i += 1

    for element in lists:
        print element

用上面的方法排序后打印出来,找到第21行对比:

[2, 6, 9, 12, 13, 69, 70, 74, 114]

与人工找的顶点顺序是一致的。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ARFoundation是一个用于在移动设备上创建现实增强应用程序的开发框架。人脸跟踪编程是ARFoundation系列教程中的一部分。 人脸跟踪是通过相机捕捉实时视频流并使用AR技术来检测和跟踪人脸的过程。这个过程涉及到计算机视觉和人工智能的技术,可以在移动设备上实时地识别人脸,进而应用各种效果和交互。 在ARFoundation系列教程中学习人脸跟踪编程,你将学习如何使用ARFoundation和Unity引擎来构建具有人脸追踪功能的应用程序。教程会向你介绍如何在Unity中创建一个AR项目,并使用ARFoundation的API来实现人脸追踪功能。 首先,你需要在Unity中导入ARFoundation库并设置相机权限。然后,你可以创建一个3D模型来代表人脸,并将其与人脸跟踪的数据进行关联。在跟踪开始后,你可以通过获取人脸的特征点信息和姿势来实时地更新模型的位置和角度。 此外,你还可以根据人脸的表情特征,例如眨眼、微笑等,来触发应用程序中的效果或交互。例如,你可以通过检测到用户眨眼的动作来实现快门的触发,拍摄照片或录制视频。 通过学习ARFoundation系列教程中的人脸跟踪编程,你将能够掌握如何使用AR技术在移动设备上实现实时人脸跟踪功能。这将为你开发创新的增强现实应用程序提供基础,并且能够为用户提供更加沉浸式和交互性的体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值