|
| 1 | +from scipy.io import loadmat, savemat |
| 2 | +import numpy as np |
| 3 | +from array import array |
| 4 | + |
| 5 | +# load expression basis |
| 6 | + |
| 7 | + |
| 8 | +def LoadExpBasis(): |
| 9 | + n_vertex = 53215 |
| 10 | + Expbin = open('BFM/Exp_Pca.bin', 'rb') |
| 11 | + exp_dim = array('i') |
| 12 | + exp_dim.fromfile(Expbin, 1) |
| 13 | + expMU = array('f') |
| 14 | + expPC = array('f') |
| 15 | + expMU.fromfile(Expbin, 3*n_vertex) |
| 16 | + expPC.fromfile(Expbin, 3*exp_dim[0]*n_vertex) |
| 17 | + |
| 18 | + expPC = np.array(expPC) |
| 19 | + expPC = np.reshape(expPC, [exp_dim[0], -1]) |
| 20 | + expPC = np.transpose(expPC) |
| 21 | + |
| 22 | + expEV = np.loadtxt('BFM/std_exp.txt') |
| 23 | + |
| 24 | + return expPC, expEV |
| 25 | + |
| 26 | +# transfer original BFM09 to our face model |
| 27 | + |
| 28 | + |
| 29 | +def transferBFM09(): |
| 30 | + original_BFM = loadmat('BFM/01_MorphableModel.mat') |
| 31 | + shapePC = original_BFM['shapePC'] # shape basis |
| 32 | + shapeEV = original_BFM['shapeEV'] # corresponding eigen value |
| 33 | + shapeMU = original_BFM['shapeMU'] # mean face |
| 34 | + texPC = original_BFM['texPC'] # texture basis |
| 35 | + texEV = original_BFM['texEV'] # eigen value |
| 36 | + texMU = original_BFM['texMU'] # mean texture |
| 37 | + |
| 38 | + expPC, expEV = LoadExpBasis() |
| 39 | + |
| 40 | + # transfer BFM09 to our face model |
| 41 | + |
| 42 | + idBase = shapePC*np.reshape(shapeEV, [-1, 199]) |
| 43 | + idBase = idBase/1e5 # unify the scale to decimeter |
| 44 | + idBase = idBase[:, :80] # use only first 80 basis |
| 45 | + |
| 46 | + exBase = expPC*np.reshape(expEV, [-1, 79]) |
| 47 | + exBase = exBase/1e5 # unify the scale to decimeter |
| 48 | + exBase = exBase[:, :64] # use only first 64 basis |
| 49 | + |
| 50 | + texBase = texPC*np.reshape(texEV, [-1, 199]) |
| 51 | + texBase = texBase[:, :80] # use only first 80 basis |
| 52 | + |
| 53 | + # our face model is cropped align face landmarks which contains only 35709 vertex. |
| 54 | + # original BFM09 contains 53490 vertex, and expression basis provided by JuYong contains 53215 vertex. |
| 55 | + # thus we select corresponding vertex to get our face model. |
| 56 | + |
| 57 | + index_exp = loadmat('BFM/BFM_front_idx.mat') |
| 58 | + index_exp = index_exp['idx'].astype( |
| 59 | + np.int32) - 1 # starts from 0 (to 53215) |
| 60 | + |
| 61 | + index_shape = loadmat('BFM/BFM_exp_idx.mat') |
| 62 | + index_shape = index_shape['trimIndex'].astype( |
| 63 | + np.int32) - 1 # starts from 0 (to 53490) |
| 64 | + index_shape = index_shape[index_exp] |
| 65 | + |
| 66 | + idBase = np.reshape(idBase, [-1, 3, 80]) |
| 67 | + idBase = idBase[index_shape, :, :] |
| 68 | + idBase = np.reshape(idBase, [-1, 80]) |
| 69 | + |
| 70 | + texBase = np.reshape(texBase, [-1, 3, 80]) |
| 71 | + texBase = texBase[index_shape, :, :] |
| 72 | + texBase = np.reshape(texBase, [-1, 80]) |
| 73 | + |
| 74 | + exBase = np.reshape(exBase, [-1, 3, 64]) |
| 75 | + exBase = exBase[index_exp, :, :] |
| 76 | + exBase = np.reshape(exBase, [-1, 64]) |
| 77 | + |
| 78 | + meanshape = np.reshape(shapeMU, [-1, 3])/1e5 |
| 79 | + meanshape = meanshape[index_shape, :] |
| 80 | + meanshape = np.reshape(meanshape, [1, -1]) |
| 81 | + |
| 82 | + meantex = np.reshape(texMU, [-1, 3]) |
| 83 | + meantex = meantex[index_shape, :] |
| 84 | + meantex = np.reshape(meantex, [1, -1]) |
| 85 | + |
| 86 | + # other info contains triangles, region used for computing photometric loss, |
| 87 | + # region used for skin texture regularization, and 68 landmarks index etc. |
| 88 | + other_info = loadmat('BFM/facemodel_info.mat') |
| 89 | + frontmask2_idx = other_info['frontmask2_idx'] |
| 90 | + skinmask = other_info['skinmask'] |
| 91 | + keypoints = other_info['keypoints'] |
| 92 | + point_buf = other_info['point_buf'] |
| 93 | + tri = other_info['tri'] |
| 94 | + tri_mask2 = other_info['tri_mask2'] |
| 95 | + |
| 96 | + # save our face model |
| 97 | + savemat('BFM/BFM09_model_info.mat', {'meanshape': meanshape, 'meantex': meantex, 'idBase': idBase, 'exBase': exBase, 'texBase': texBase, |
| 98 | + 'tri': tri, 'point_buf': point_buf, 'tri_mask2': tri_mask2, 'keypoints': keypoints, 'frontmask2_idx': frontmask2_idx, 'skinmask': skinmask}) |
| 99 | + |
| 100 | + |
| 101 | +if __name__ == '__main__': |
| 102 | + transferBFM09() |
0 commit comments