Face3D学习笔记(3)3DMM示例源码解析【上】准备工作

举报
ESRSchao 发表于 2022/11/25 22:03:48 2022/11/25
【摘要】 【摘要】 Face3D 是博主做本科毕设时的灵感来源,相对于现在各式各样的深度学习人脸重建方法,Face3D 中所使用的3DMM模型以及利用二维特征点进行三维人脸拟合时所使用的黄金标准算法展示了经典算法的精简有效。 本系列文章系博主在CSDN原文章上的整合修改,如有疑问可以随时交流。 PS:封面图来源是个人十分喜欢的画师ちょん*,侵删。

写在前面

3DMM代码部分是人脸重建程序的核心部分,这部分因为当年是边写程序边写的所以分成了四个片段发出来,这篇文章是第一个片段。

  • 为了保证整个示例项目更加直观,方便理解,在展示一些函数的源码时会使用numpy版本进行展示,而在示例程序中并未使用numpy版本的库,在Cython版本与numpy版本出现差异的原码前会有标注,希望读者留意。

准备工作

3DMM的例程里面需要用到BFM模型,这些数据需要自行下载,下面是下载教程:

准备 BFM 数据

1.下载原始BFM模型

网站: https://faces.dmi.unibas.ch/bfm/main.php?nav=1-2&id=downloads
网站界面将上面的框全部打勾后在下方填上自己的姓名机构和接受数据的邮箱再填一下验证码就可以了。
然后填写的邮箱会收到这样一封邮件:

邮件会给你一个用户名和密码,用户名就是邮箱,密码是随机的,复制这俩然后打开上面的链接,填写信息之后就可以下载了。
下载好的文件解压缩,在里面找到01_MorphabelModel.mat
文件
然后在face3d/examples/Data/BFM目录下新建一个文件夹raw,再将01_MorphabelModel.mat复制到raw/

2.从 3DDFA和 HFPE下载额外的 BFM 信息

网站: http://www.cbsr.ia.ac.cn/users/xiangyuzhu/projects/3DDFA/main.htm
打开后在这里
下载

下载图中的[Face Profiling] 和 [3DDFA]

另一个网站: http://www.cbsr.ia.ac.cn/users/xiangyuzhu/projects/HPEN/main.htm
打开后找到Downloads:
下载

下载第一个[HPEN]

将下载好的三个压缩包解压,分别在里面找到如下文件:
model_info.mat
Model_Expression.mat
Model_face_contour_trimed.mat
Model_tri_mouth.mat
Modelplus_nose_hole.mat
Modelplus_parallel.mat
vertex_code.mat

然后在face3d/examples/Data/BFM目录下新建一个文件夹3ddfa
将上述文件拷贝进去。

3.从3DMMasSTN下载UV

网站: https://github.com/anilbas/3DMMasSTN/blob/master/util/BFM_UV.mat
下载点击download下载后解压,在face3d/examples/Data/BFM目录下新建一个文件夹stn,再将BFM_UV.mat复制到stn/

4.生成模型数据
在BFM目录下创建Out文件夹
在 Matlab 中打开文件generate.m并运行,我用的MATLAB R2018a,这个.m文件有不少地方==有问题==,修正后得到Out文件夹里面的三个输出,Out输出我会放在这,但是其他部分因为隐私条款暂不提供,请自行下载调试(可以找作者私聊)。

此外,修改后的generate.m代码如下:

% addpath(genpath(pwd))
% --> model

%% load raw BFM models
load('raw/01_MorphableModel.mat');

%% load 3ddfa data
% 1. load bfm information. trim 
load('3ddfa/model_info.mat');
trimIndex_f = [3*trimIndex-2, 3*trimIndex-1, 3*trimIndex]';
trimIndex_f = trimIndex_f(:);

model.shapeMU = shapeMU(trimIndex_f,:);
model.shapePC = shapePC(trimIndex_f, :);
model.shapeEV = shapeEV;
model.texMU = texMU(trimIndex_f, :);
model.texPC = texPC(trimIndex_f, :);
model.texEV = texEV;
model.tri = tri;
model.kpt_ind = keypoints;

model_info.kpt_ind = keypoints;
model_info.trimIndex = trimIndex;
model_info.symlist = symlist;
model_info.symlist_tri = symlist_tri;
%segbin: nose eyes mouth rest
model_info.segbin = segbin(trimIndex, :)';
model_info.segbin_tri = segbin_tri';

% 2. load expression
load('3ddfa/Model_Expression.mat');
model.expMU = mu_exp;
model.expPC = w_exp;
model.expEV = sigma_exp;

% 3. load mouth tri
load('3ddfa/Model_tri_mouth.mat');
model.tri_mouth = tri_mouth;
model_info.tri_mouth = tri_mouth;

% 4. face contour 
load('3ddfa/Model_face_contour_trimed.mat');
model_info.face_contour = face_contour;
model_info.face_contour_line = face_contour_line;
model_info.face_contour_front = face_contour_front;
model_info.face_contour_front_line = face_contour_front_line;

% 5. nose hole
load('3ddfa/Modelplus_nose_hole.mat');
model_info.nose_hole = nose_hole;
model_info.nose_hole_right = nose_hole_right;
model_info.nose_hole_left = nose_hole_left;

% 6. parallel for key points
load('3ddfa/Modelplus_parallel.mat')
model_info.parallel = parallel;
model_info.parallel_face_contour = parallel_face_contour;

% 7. pncc
copyfile('C:\Users\����\Desktop\BFM\3ddfa\vertex_code.mat', 'Out/pncc_code.mat') %这里用的是绝对路径,请自行更改

%% load 3DMMasSTN UV coords
load('stn/BFM_UV.mat');
uv_coords = UV(trimIndex, :)';

% modify bad vers
bad_ind = [10032, 10155, 10280];
round1 = [10033, 10158 ];
round2 = [10534, 10157, 10661];
round3 = [10916, 10286];
uv_coords(:, bad_ind(1)) = mean(uv_coords(:, round1), 2);
uv_coords(:, bad_ind(2)) = mean(uv_coords(:, round2), 2);
uv_coords(:, bad_ind(3)) = mean(uv_coords(:, round3), 2);

model_info.uv_coords = uv_coords';
UV = model_info.uv_coords;

% modify tri mouth
tm_inner = model.tri_mouth;
tm_inner_add =[6420 6542 6664;  %% add inner mouth triangles
                        6420 6294 6167;
                        6167 6297 6420;
                        6167 6297 6296;
                        6167 6296 6295;
                        6167 6295 6039;
                        6168 6295 6039];   
ind_bad = 38;
all_ind = 1:size(tm_inner, 2);
tm_inner = tm_inner(:, setdiff(all_ind, bad_ind));
tm_inner = [tm_inner tm_inner_add'];
model_info.tri_mouth = tm_inner;
model.tri_mouth = tm_inner;

% save
clearvars -except model model_info UV

save 'C:\Users\����\Desktop\BFM\Out\BFM.mat' model %这里用的是绝对路径,请自行更改
save 'C:\Users\����\Desktop\BFM\Out\BFM_info.mat' model_info %这里用的是绝对路径,请自行更改
save 'C:\Users\����\Desktop\BFM\Out\BFM_UV.mat' UV %这里用的是绝对路径,请自行更改
% copyfile('3ddfa/pncc_code.mat', 'Out/pncc_code.mat')

至此,准备工作完成。可以运行2_3dmm.py得到下面三个图像输出结果:
1
2
3
由于这部分是作者要研究的核心部分,所以将分片进行,下面将从原理出发逐步分析源码,期待大家关注。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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