| | |
| |
|
| | """ |
| | functions for processing and transforming 3D facial keypoints |
| | """ |
| |
|
| | import numpy as np |
| | import torch |
| | import torch.nn.functional as F |
| |
|
| | PI = np.pi |
| |
|
| |
|
| | def headpose_pred_to_degree(pred): |
| | """ |
| | pred: (bs, 66) or (bs, 1) or others |
| | """ |
| | if pred.ndim > 1 and pred.shape[1] == 66: |
| | |
| | device = pred.device |
| | idx_tensor = [idx for idx in range(0, 66)] |
| | idx_tensor = torch.FloatTensor(idx_tensor).to(device) |
| | pred = F.softmax(pred, dim=1) |
| | degree = torch.sum(pred*idx_tensor, axis=1) * 3 - 97.5 |
| |
|
| | return degree |
| |
|
| | return pred |
| |
|
| |
|
| | def get_rotation_matrix(pitch_, yaw_, roll_): |
| | """ the input is in degree |
| | """ |
| | |
| |
|
| | |
| | pitch = pitch_ / 180 * PI |
| | yaw = yaw_ / 180 * PI |
| | roll = roll_ / 180 * PI |
| |
|
| | device = pitch.device |
| |
|
| | if pitch.ndim == 1: |
| | pitch = pitch.unsqueeze(1) |
| | if yaw.ndim == 1: |
| | yaw = yaw.unsqueeze(1) |
| | if roll.ndim == 1: |
| | roll = roll.unsqueeze(1) |
| |
|
| | |
| | bs = pitch.shape[0] |
| | ones = torch.ones([bs, 1]).to(device) |
| | zeros = torch.zeros([bs, 1]).to(device) |
| | x, y, z = pitch, yaw, roll |
| |
|
| | rot_x = torch.cat([ |
| | ones, zeros, zeros, |
| | zeros, torch.cos(x), -torch.sin(x), |
| | zeros, torch.sin(x), torch.cos(x) |
| | ], dim=1).reshape([bs, 3, 3]) |
| |
|
| | rot_y = torch.cat([ |
| | torch.cos(y), zeros, torch.sin(y), |
| | zeros, ones, zeros, |
| | -torch.sin(y), zeros, torch.cos(y) |
| | ], dim=1).reshape([bs, 3, 3]) |
| |
|
| | rot_z = torch.cat([ |
| | torch.cos(z), -torch.sin(z), zeros, |
| | torch.sin(z), torch.cos(z), zeros, |
| | zeros, zeros, ones |
| | ], dim=1).reshape([bs, 3, 3]) |
| |
|
| | rot = rot_z @ rot_y @ rot_x |
| | return rot.permute(0, 2, 1) |
| |
|