AR Camera开发记录(三) -- 替换人脸贴图

转载:https://blog.csdn.net/torchlight2012/article/details/76119168

上一篇文章介绍了动态修改3D人脸模型的顶点要注意的问题。 
结合人脸检测技术,根据人脸关键点实时修改顶点坐标,就能让3D人脸模型跟随自己的面部变化了。 
这时候如果想让3D人脸模型换一张脸呢? 
其中一种方式就是根据旧的贴图,用Photoshop调整新的贴图的五官位置: 
这里写图片描述

给人脸模型替换新的贴图后,实现的效果如下: 
这里写图片描述

对于非人脸的素材,比如上面这只狮子的脸,可能只能这么做。 
不过对于同样是人脸的素材,则不必依靠P图,可以通过代码实现动态“换脸”。

贴图坐标的定义

为了实现换脸,首先需要了解模型的贴图坐标是如何定义的。 
用文本编辑器打开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后面每行有三组数字。每组的第一个数字是顶点坐标的序号,第二个数字是贴图坐标的序号。 
之前介绍如何修改人脸模型左眼角的顶点坐标时,已经知道左眼角的顶点坐标序号是21。 
从上面的几组数字中,找到以21为开头的一组,看到21斜杠后面是2。 
意思就是序号为21的顶点坐标,对应序号为2的贴图坐标。

再找到以”vt”开头的行:

···省略
vt 0.2147 0.6968
vt 0.3233 0.6276
vt 0.3213 0.7244
vt 0.2208 0.5305
vt 0.2612 0.3763
···省略

“vt”开头的行定义的就是贴图坐标。 
找到第二行:

vt 0.3233 0.6276

 

用Photoshop打开这张贴图,拉出标尺看就明白了: 
这里写图片描述

因此“换脸”,或者说替换人脸贴图,其实就是用人脸检测技术,获取新的人脸素材的关键点位置,再用新的关键点替换对应的贴图坐标。 
具体如何操作,请参阅项目中的LandmarkUtils

Rajawali中替换模型贴图

内置于APP中的Obj模型文件放在res/raw目录中,其贴图素材放在res/drawable-nodpi目录中。 
由于我们的“换脸”方案需要修改Obj模型文件的内容,为便于处理,将Obj模型文件复制到SD卡中。 
加载SD卡中的模型文件,与加载内置的模型文件有些区别,代码如下:

protected void initScene() {
    try {
        // 加载SD卡中的人脸模型
        // objPath是模型文件的路径
        String objPath = "xxx";
        LoaderOBJ parser = new LoaderOBJ(this, objPath);
        parser.parse();
        Object3D faceModel = parser.getParsedObject();

        // 添加模型到场景中        
        getCurrentScene().addChild(faceModel);

    } catch (ParsingException e) {
        e.printStackTrace();
    }
}

注意上面的objPath,假如模型文件的路径是/sdcard/Obj/faceModel_obj,那么objPath写“Obj/faceModel_obj”就可以了。 
因为LoaderOBJ方法最后调用的是:

public ILoader parse() throws ParsingException {
    if (mFile == null && mFileOnSDCard != null)
        mFile = new File(Environment.getExternalStorageDirectory(), mFileOnSDCard);

    if (mFile != null && RajLog.isDebugEnabled())
        RajLog.d("Parsing: " + mFile.getAbsolutePath());
    return this;
}

这个mFileOnSDCard就是上面的objPath。 
之前一时疏忽写成objPath = Environment.getExternalStorageDirectory() + “Obj/faceModel_obj”,导致报错说找不到模型文件。

接下来就是替换贴图,修改上面的代码:

// ...省略
Object3D faceModel = parser.getParsedObject();
ATexture texture = faceModel.getMaterial().getTextureList().get(0);
// 先移除旧的贴图
faceModel.getMaterial().removeTexture(texture);
// 读取新的贴图素材
String newTexture = "xxx";
Bitmap bitmap = BitmapFactory.decodeFile(newTexture);
// 替换新的贴图
faceModel.getMaterial().addTexture(new Texture("canvas", bitmap));

替换新贴图之前,还可以对bitmap做一些处理,比如调整人脸的肤色,让“换脸”效果更自然: 
这里写图片描述这里写图片描述 
左边是调整前,右边是调整后,目前调肤色效果还不太理想,暂时就不介绍了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值