Skip to content

Commit 513f4bc

Browse files
committed
Make LBS support batch dynamic landmarks
1 parent 3ebce70 commit 513f4bc

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
1111
AUTHOR = 'Vassilis Choutas'
1212
REQUIRES_PYTHON = '>=3.7.0'
13-
VERSION = '0.1.5'
13+
VERSION = '0.1.6'
1414

1515
here = os.path.abspath(os.path.dirname(__file__))
1616

smplx/body_models.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -825,9 +825,11 @@ def forward(self, betas=None, global_orient=None, body_pose=None,
825825
self.dynamic_lmk_bary_coords,
826826
self.neck_kin_chain, dtype=self.dtype)
827827

828-
lmk_faces_idx = torch.cat([lmk_faces_idx, dyn_lmk_faces_idx], 1)
828+
lmk_faces_idx = torch.cat([lmk_faces_idx.expand(batch_size, -1),
829+
dyn_lmk_faces_idx], 1)
829830
lmk_bary_coords = torch.cat(
830-
[lmk_bary_coords, dyn_lmk_bary_coords], 1)
831+
[lmk_bary_coords.expand(batch_size, -1, -1),
832+
dyn_lmk_bary_coords], 1)
831833

832834
landmarks = vertices2landmarks(vertices, self.faces_tensor,
833835
lmk_faces_idx,

smplx/lbs.py

+43-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,40 @@
3030
def find_dynamic_lmk_idx_and_bcoords(vertices, pose, dynamic_lmk_faces_idx,
3131
dynamic_lmk_b_coords,
3232
neck_kin_chain, dtype=torch.float32):
33+
''' Compute the faces, barycentric coordinates for the dynamic landmarks
34+
35+
36+
To do so, we first compute the rotation of the neck around the y-axis
37+
and then use a pre-computed look-up table to find the faces and the
38+
barycentric coordinates that will be used.
39+
40+
Special thanks to Soubhik Sanyal ([email protected])
41+
for providing the original TensorFlow implementation and for the LUT.
42+
43+
Parameters
44+
----------
45+
vertices: torch.tensor BxVx3, dtype = torch.float32
46+
The tensor of input vertices
47+
pose: torch.tensor Bx(Jx3), dtype = torch.float32
48+
The current pose of the body model
49+
dynamic_lmk_faces_idx: torch.tensor L, dtype = torch.long
50+
The look-up table from neck rotation to faces
51+
dynamic_lmk_b_coords: torch.tensor Lx3, dtype = torch.float32
52+
The look-up table from neck rotation to barycentric coordinates
53+
neck_kin_chain: list
54+
A python list that contains the indices of the joints that form the
55+
kinematic chain of the neck.
56+
dtype: torch.dtype, optional
57+
58+
Returns
59+
-------
60+
dyn_lmk_faces_idx: torch.tensor, dtype = torch.long
61+
A tensor of size BxL that contains the indices of the faces that
62+
will be used to compute the current dynamic landmarks.
63+
dyn_lmk_b_coords: torch.tensor, dtype = torch.float32
64+
A tensor of size BxL that contains the indices of the faces that
65+
will be used to compute the current dynamic landmarks.
66+
'''
3367

3468
batch_size = vertices.shape[0]
3569

@@ -84,12 +118,17 @@ def vertices2landmarks(vertices, faces, lmk_faces_idx, lmk_bary_coords):
84118
# Extract the indices of the vertices for each face
85119
# BxLx3
86120
batch_size, num_verts = vertices.shape[:2]
121+
device = vertices.device
122+
87123
lmk_faces = torch.index_select(faces, 0, lmk_faces_idx.view(-1)).view(
88-
1, -1, 3).repeat([batch_size, 1, 1])
89-
lmk_faces += torch.arange(batch_size, dtype=torch.long).view(-1, 1, 1).to(
90-
device=vertices.device) * num_verts
124+
batch_size, -1, 3)
125+
126+
lmk_faces += torch.arange(
127+
batch_size, dtype=torch.long, device=device).view(-1, 1, 1) * num_verts
128+
129+
lmk_vertices = vertices.view(-1, 3)[lmk_faces].view(
130+
batch_size, -1, 3, 3)
91131

92-
lmk_vertices = vertices.view(-1, 3)[lmk_faces]
93132
landmarks = torch.einsum('blfi,blf->bli', [lmk_vertices, lmk_bary_coords])
94133
return landmarks
95134

0 commit comments

Comments
 (0)