Yuliang commited on
Commit
f4e5ac5
1 Parent(s): 487ee6d

Da-pose to A-pose

Browse files
Files changed (2) hide show
  1. apps/avatarizer.py +25 -16
  2. lib/smplx/body_models.py +18 -0
apps/avatarizer.py CHANGED
@@ -64,7 +64,7 @@ smpl_model = smplx.create(
64
  smpl_out_lst = []
65
 
66
  # obtain the pose params of T-pose, DA-pose, and the original pose
67
- for pose_type in ["t-pose", "da-pose", "pose"]:
68
  smpl_out_lst.append(
69
  smpl_model(
70
  body_pose=smplx_param["body_pose"],
@@ -88,7 +88,7 @@ for pose_type in ["t-pose", "da-pose", "pose"]:
88
  # 3. ECON (w/o hands & over-streched faces) + SMPL-X (w/ hands & registered inpainting parts)
89
  # ------------------------------------------------------------------------------------------- #
90
 
91
- smpl_verts = smpl_out_lst[2].vertices.detach()[0]
92
  smpl_tree = cKDTree(smpl_verts.cpu().numpy())
93
  dist, idx = smpl_tree.query(econ_obj.vertices, k=5)
94
 
@@ -96,7 +96,7 @@ if not osp.exists(f"{prefix}_econ_da.obj") or not osp.exists(f"{prefix}_smpl_da.
96
 
97
  # t-pose for ECON
98
  econ_verts = torch.tensor(econ_obj.vertices).float()
99
- rot_mat_t = smpl_out_lst[2].vertex_transformation.detach()[0][idx[:, 0]]
100
  homo_coord = torch.ones_like(econ_verts)[..., :1]
101
  econ_cano_verts = torch.inverse(rot_mat_t) @ torch.cat([econ_verts, homo_coord],
102
  dim=1).unsqueeze(-1)
@@ -104,13 +104,13 @@ if not osp.exists(f"{prefix}_econ_da.obj") or not osp.exists(f"{prefix}_smpl_da.
104
  econ_cano = trimesh.Trimesh(econ_cano_verts, econ_obj.faces)
105
 
106
  # da-pose for ECON
107
- rot_mat_da = smpl_out_lst[1].vertex_transformation.detach()[0][idx[:, 0]]
108
  econ_da_verts = rot_mat_da @ torch.cat([econ_cano_verts, homo_coord], dim=1).unsqueeze(-1)
109
  econ_da = trimesh.Trimesh(econ_da_verts[:, :3, 0].cpu(), econ_obj.faces)
110
 
111
  # da-pose for SMPL-X
112
  smpl_da = trimesh.Trimesh(
113
- smpl_out_lst[1].vertices.detach()[0], smpl_model.faces, maintain_orders=True, process=False
114
  )
115
  smpl_da.export(f"{prefix}_smpl_da.obj")
116
 
@@ -199,7 +199,7 @@ econ_posedirs = (
199
  econ_J_regressor /= econ_J_regressor.sum(dim=1, keepdims=True).clip(min=1e-10)
200
  econ_lbs_weights /= econ_lbs_weights.sum(dim=1, keepdims=True)
201
 
202
- rot_mat_da = smpl_out_lst[1].vertex_transformation.detach()[0][idx[:, 0]]
203
  econ_da_verts = torch.tensor(econ_da.vertices).float()
204
  econ_cano_verts = torch.inverse(rot_mat_da) @ torch.cat([
205
  econ_da_verts, torch.ones_like(econ_da_verts)[..., :1]
@@ -211,7 +211,7 @@ econ_cano_verts = econ_cano_verts[:, :3, 0].double()
211
  # use original pose to animate ECON reconstruction
212
  # ----------------------------------------------------
213
 
214
- new_pose = smpl_out_lst[2].full_pose
215
  # new_pose[:, :3] = 0.
216
 
217
  posed_econ_verts, _ = general_lbs(
@@ -222,7 +222,6 @@ posed_econ_verts, _ = general_lbs(
222
  parents=smpl_model.parents,
223
  lbs_weights=econ_lbs_weights
224
  )
225
-
226
  aligned_econ_verts = posed_econ_verts[0].detach().cpu().numpy()
227
  aligned_econ_verts += smplx_param["transl"].cpu().numpy()
228
  aligned_econ_verts *= smplx_param["scale"].cpu().numpy() * np.array([1.0, -1.0, -1.0])
@@ -322,14 +321,17 @@ texture_npy = uv_rasterizer.get_texture(
322
  torch.tensor(final_colors).unsqueeze(0).float() / 255.0,
323
  )
324
 
325
- Image.fromarray((texture_npy * 255.0).astype(np.uint8)).save(f"{cache_path}/texture.png")
 
 
326
 
327
  # UV mask for TEXTure (https://readpaper.com/paper/4720151447010820097)
328
- texture_npy[texture_npy.sum(axis=2) == 0.0] = 1.0
329
- Image.fromarray((texture_npy * 255.0).astype(np.uint8)).save(f"{cache_path}/mask.png")
 
330
 
331
- # generate da-pose vertices
332
- new_pose = smpl_out_lst[1].full_pose
333
  new_pose[:, :3] = 0.
334
 
335
  posed_econ_verts, _ = general_lbs(
@@ -342,7 +344,14 @@ posed_econ_verts, _ = general_lbs(
342
  )
343
 
344
  # export mtl file
345
- mtl_string = f"newmtl mat0 \nKa 1.000000 1.000000 1.000000 \nKd 1.000000 1.000000 1.000000 \nKs 0.000000 0.000000 0.000000 \nTr 1.000000 \nillum 1 \nNs 0.000000\nmap_Kd texture.png"
346
- with open(f"{cache_path}/material.mtl", 'w') as file:
347
- file.write(mtl_string)
 
 
 
 
 
 
 
348
  export_obj(posed_econ_verts[0].detach().cpu().numpy(), f_np, vt, ft, f"{cache_path}/mesh.obj")
 
64
  smpl_out_lst = []
65
 
66
  # obtain the pose params of T-pose, DA-pose, and the original pose
67
+ for pose_type in ["a-pose", "t-pose", "da-pose", "pose"]:
68
  smpl_out_lst.append(
69
  smpl_model(
70
  body_pose=smplx_param["body_pose"],
 
88
  # 3. ECON (w/o hands & over-streched faces) + SMPL-X (w/ hands & registered inpainting parts)
89
  # ------------------------------------------------------------------------------------------- #
90
 
91
+ smpl_verts = smpl_out_lst[3].vertices.detach()[0]
92
  smpl_tree = cKDTree(smpl_verts.cpu().numpy())
93
  dist, idx = smpl_tree.query(econ_obj.vertices, k=5)
94
 
 
96
 
97
  # t-pose for ECON
98
  econ_verts = torch.tensor(econ_obj.vertices).float()
99
+ rot_mat_t = smpl_out_lst[3].vertex_transformation.detach()[0][idx[:, 0]]
100
  homo_coord = torch.ones_like(econ_verts)[..., :1]
101
  econ_cano_verts = torch.inverse(rot_mat_t) @ torch.cat([econ_verts, homo_coord],
102
  dim=1).unsqueeze(-1)
 
104
  econ_cano = trimesh.Trimesh(econ_cano_verts, econ_obj.faces)
105
 
106
  # da-pose for ECON
107
+ rot_mat_da = smpl_out_lst[2].vertex_transformation.detach()[0][idx[:, 0]]
108
  econ_da_verts = rot_mat_da @ torch.cat([econ_cano_verts, homo_coord], dim=1).unsqueeze(-1)
109
  econ_da = trimesh.Trimesh(econ_da_verts[:, :3, 0].cpu(), econ_obj.faces)
110
 
111
  # da-pose for SMPL-X
112
  smpl_da = trimesh.Trimesh(
113
+ smpl_out_lst[2].vertices.detach()[0], smpl_model.faces, maintain_orders=True, process=False
114
  )
115
  smpl_da.export(f"{prefix}_smpl_da.obj")
116
 
 
199
  econ_J_regressor /= econ_J_regressor.sum(dim=1, keepdims=True).clip(min=1e-10)
200
  econ_lbs_weights /= econ_lbs_weights.sum(dim=1, keepdims=True)
201
 
202
+ rot_mat_da = smpl_out_lst[2].vertex_transformation.detach()[0][idx[:, 0]]
203
  econ_da_verts = torch.tensor(econ_da.vertices).float()
204
  econ_cano_verts = torch.inverse(rot_mat_da) @ torch.cat([
205
  econ_da_verts, torch.ones_like(econ_da_verts)[..., :1]
 
211
  # use original pose to animate ECON reconstruction
212
  # ----------------------------------------------------
213
 
214
+ new_pose = smpl_out_lst[3].full_pose
215
  # new_pose[:, :3] = 0.
216
 
217
  posed_econ_verts, _ = general_lbs(
 
222
  parents=smpl_model.parents,
223
  lbs_weights=econ_lbs_weights
224
  )
 
225
  aligned_econ_verts = posed_econ_verts[0].detach().cpu().numpy()
226
  aligned_econ_verts += smplx_param["transl"].cpu().numpy()
227
  aligned_econ_verts *= smplx_param["scale"].cpu().numpy() * np.array([1.0, -1.0, -1.0])
 
321
  torch.tensor(final_colors).unsqueeze(0).float() / 255.0,
322
  )
323
 
324
+ gray_texture = texture_npy.copy()
325
+ gray_texture[texture_npy.sum(axis=2) == 0.0] = 0.5
326
+ Image.fromarray((gray_texture * 255.0).astype(np.uint8)).save(f"{cache_path}/texture.png")
327
 
328
  # UV mask for TEXTure (https://readpaper.com/paper/4720151447010820097)
329
+ white_texture = texture_npy.copy()
330
+ white_texture[texture_npy.sum(axis=2) == 0.0] = 1.0
331
+ Image.fromarray((white_texture * 255.0).astype(np.uint8)).save(f"{cache_path}/mask.png")
332
 
333
+ # generate a-pose vertices
334
+ new_pose = smpl_out_lst[0].full_pose
335
  new_pose[:, :3] = 0.
336
 
337
  posed_econ_verts, _ = general_lbs(
 
344
  )
345
 
346
  # export mtl file
347
+ with open(f"{cache_path}/material.mtl", 'w') as fp:
348
+ fp.write(f'newmtl mat0 \n')
349
+ fp.write(f'Ka 1.000000 1.000000 1.000000 \n')
350
+ fp.write(f'Kd 1.000000 1.000000 1.000000 \n')
351
+ fp.write(f'Ks 0.000000 0.000000 0.000000 \n')
352
+ fp.write(f'Tr 1.000000 \n')
353
+ fp.write(f'illum 1 \n')
354
+ fp.write(f'Ns 0.000000 \n')
355
+ fp.write(f'map_Kd texture.png \n')
356
+
357
  export_obj(posed_econ_verts[0].detach().cpu().numpy(), f_np, vt, ft, f"{cache_path}/mesh.obj")
lib/smplx/body_models.py CHANGED
@@ -1262,6 +1262,24 @@ class SMPLX(SMPLH):
1262
 
1263
  if pose_type == "t-pose":
1264
  full_pose *= 0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1265
  elif pose_type == "da-pose":
1266
  body_pose = torch.zeros_like(body_pose).view(body_pose.shape[0], -1, 3)
1267
  body_pose[:, 0] = torch.tensor([0., 0., 30 * np.pi / 180.])
 
1262
 
1263
  if pose_type == "t-pose":
1264
  full_pose *= 0.0
1265
+ elif pose_type == "a-pose":
1266
+ body_pose = torch.zeros_like(body_pose).view(body_pose.shape[0], -1, 3)
1267
+ body_pose[:, 15] = torch.tensor([0., 0., -45 * np.pi / 180.])
1268
+ body_pose[:, 16] = torch.tensor([0., 0., 45 * np.pi / 180.])
1269
+ body_pose = body_pose.view(body_pose.shape[0], -1)
1270
+
1271
+ full_pose = torch.cat(
1272
+ [
1273
+ global_orient * 0.,
1274
+ body_pose,
1275
+ jaw_pose * 0.,
1276
+ leye_pose * 0.,
1277
+ reye_pose * 0.,
1278
+ left_hand_pose * 0.,
1279
+ right_hand_pose * 0.,
1280
+ ],
1281
+ dim=1,
1282
+ )
1283
  elif pose_type == "da-pose":
1284
  body_pose = torch.zeros_like(body_pose).view(body_pose.shape[0], -1, 3)
1285
  body_pose[:, 0] = torch.tensor([0., 0., 30 * np.pi / 180.])