IsshikiHugh's picture
feat: CPU demo
5ac1897
from lib.kits.basic import *
from lib.body_models.skel_utils.definition import JID2QIDS
def gmof(x, sigma=100):
'''
Geman-McClure error function, to be used as a robust loss function.
'''
x_squared = x ** 2
sigma_squared = sigma ** 2
return (sigma_squared * x_squared) / (sigma_squared + x_squared)
def compute_rel_change(prev_val: float, curr_val: float) -> float:
'''
Compute the relative change between two values.
Copied from:
https://github.com/vchoutas/smplify-x
### Args:
- prev_val: float
- curr_val: float
### Returns:
- float
'''
return np.abs(prev_val - curr_val) / max([np.abs(prev_val), np.abs(curr_val), 1])
INVALID_JIDS = [37, 38] # These joints are not reliable.
def get_kp_active_j_masks(parts:Union[str, List[str]], device='cuda'):
# Generate the masks performed on the keypoints to mask the loss.
act_jids = get_kp_active_jids(parts)
masks = torch.zeros(44).to(device)
masks[act_jids] = 1.0
return masks
def get_kp_active_jids(parts:Union[str, List[str]]):
if isinstance(parts, str):
if parts == 'all':
return get_kp_active_jids(['torso', 'limbs', 'head'])
elif parts == 'hips':
return [8, 9, 12, 27, 28, 39]
elif parts == 'torso-lite':
return [2, 5, 9, 12]
elif parts == 'torso':
return [1, 2, 5, 8, 9, 12, 27, 28, 33, 34, 37, 39, 40, 41]
elif parts == 'limbs':
return get_kp_active_jids(['limbs_proximal', 'limbs_distal'])
elif parts == 'head':
return [0, 15, 16, 17, 18, 38, 42, 43]
elif parts == 'limbs_proximal':
return [3, 6, 10, 13, 26, 29, 32, 35]
elif parts == 'limbs_distal':
return [4, 7, 11, 14, 19, 20, 21, 22, 23, 24, 25, 30, 31, 36]
else:
raise ValueError(f'Unsupported parts: {parts}')
else:
jids = []
for part in parts:
jids.extend(get_kp_active_jids(part))
jids = set(jids) - set(INVALID_JIDS)
return sorted(list(jids))
def get_params_active_j_masks(parts:Union[str, List[str]], device='cuda'):
# Generate the masks performed on the keypoints to mask the loss.
act_jids = get_params_active_jids(parts)
masks = torch.zeros(24).to(device)
masks[act_jids] = 1.0
return masks
def get_params_active_jids(parts:Union[str, List[str]]):
if isinstance(parts, str):
if parts == 'all':
return get_params_active_jids(['torso', 'limbs', 'head'])
elif parts == 'torso-lite':
return get_params_active_jids('torso')
elif parts == 'hips': # Enable `hips` if `poses_orient` is enabled.
return [0]
elif parts == 'torso':
return [0, 11]
elif parts == 'limbs':
return get_params_active_jids(['limbs_proximal', 'limbs_distal'])
elif parts == 'head':
return [12, 13]
elif parts == 'limbs_proximal':
return [1, 6, 14, 15, 19, 20]
elif parts == 'limbs_distal':
return [2, 3, 4, 5, 7, 8, 9, 10, 16, 17, 18, 21, 22, 23]
else:
raise ValueError(f'Unsupported parts: {parts}')
else:
qids = []
for part in parts:
qids.extend(get_params_active_jids(part))
return sorted(list(set(qids)))
def get_params_active_q_masks(parts:Union[str, List[str]], device='cuda'):
# Generate the masks performed on the keypoints to mask the loss.
act_qids = get_params_active_qids(parts)
masks = torch.zeros(46).to(device)
masks[act_qids] = 1.0
return masks
def get_params_active_qids(parts:Union[str, List[str]]):
act_jids = get_params_active_jids(parts)
qids = []
for act_jid in act_jids:
qids.extend(JID2QIDS[act_jid])
return sorted(list(set(qids)))
def estimate_kp2d_scale(
kp2d : torch.Tensor,
edge_idxs : List[Tuple[int, int]] = [[5, 12], [2, 9]], # shoulders to hips
):
diff2d = []
for edge in edge_idxs:
diff2d.append(kp2d[:, edge[0]] - kp2d[:, edge[1]]) # list of (B, 2)
scale2d = torch.stack(diff2d, dim=1).norm(dim=-1) # (B, E)
return scale2d.mean(dim=1) # (B,)
@torch.no_grad()
def guess_cam_z(
pd_kp3d : torch.Tensor,
gt_kp2d : torch.Tensor,
focal_length : float,
edge_idxs : List[Tuple[int, int]] = [[5, 12], [2, 9]], # shoulders to hips
):
'''
Initializes the camera depth translation (i.e. z value) according to the ground truth 2D
keypoints and the predicted 3D keypoints.
Modified from: https://github.com/vchoutas/smplify-x/blob/68f8536707f43f4736cdd75a19b18ede886a4d53/smplifyx/fitting.py#L36-L110
### Args
- pd_kp3d: torch.Tensor, (B, J, 3)
- gt_kp2d: torch.Tensor, (B, J, 2)
- Without confidence.
- focal_length: float
- edge_idxs: List[Tuple[int, int]], default=[[5, 12], [2, 9]], i.e. shoulders to hips
- Identify the edge to evaluate the scale of the entity.
'''
diff3d, diff2d = [], []
for edge in edge_idxs:
diff3d.append(pd_kp3d[:, edge[0]] - pd_kp3d[:, edge[1]]) # list of (B, 3)
diff2d.append(gt_kp2d[:, edge[0]] - gt_kp2d[:, edge[1]]) # list of (B, 2)
diff3d = torch.stack(diff3d, dim=1) # (B, E, 3)
diff2d = torch.stack(diff2d, dim=1) # (B, E, 2)
length3d = diff3d.norm(dim=-1) # (B, E)
length2d = diff2d.norm(dim=-1) # (B, E)
height3d = length3d.mean(dim=1) # (B,)
height2d = length2d.mean(dim=1) # (B,)
z_estim = focal_length * (height3d / height2d) # (B,)
return z_estim # (B,)