Spaces:
Sleeping
Sleeping
# Modified from https://github.com/zhan-xu/RigNet | |
import numpy as np | |
##### for quantitative calculation | |
def chamfer_dist(pt1, pt2): | |
pt1 = pt1[np.newaxis, :, :] | |
pt2 = pt2[:, np.newaxis, :] | |
dist = np.sqrt(np.sum((pt1 - pt2) ** 2, axis=2)) | |
min_left = np.mean(np.min(dist, axis=0)) | |
min_right = np.mean(np.min(dist, axis=1)) | |
return (min_left + min_right) / 2 | |
def oneway_chamfer(pt_src, pt_dst): | |
pt1 = pt_src[np.newaxis, :, :] | |
pt2 = pt_dst[:, np.newaxis, :] | |
dist = np.sqrt(np.sum((pt1 - pt2) ** 2, axis=2)) | |
avg_dist = np.mean(np.min(dist, axis=0)) | |
return avg_dist | |
def joint2bone_chamfer_dist(joints1, bones1, joints2, bones2): | |
bone_sample_1 = sample_skel(joints1, bones1) | |
bone_sample_2 = sample_skel(joints2, bones2) | |
dist1 = oneway_chamfer(joints1, bone_sample_2) | |
dist2 = oneway_chamfer(joints2, bone_sample_1) | |
return (dist1 + dist2) / 2 | |
def bone2bone_chamfer_dist(joints1, bones1, joints2, bones2): | |
bone_sample_1 = sample_skel(joints1, bones1) | |
bone_sample_2 = sample_skel(joints2, bones2) | |
return chamfer_dist(bone_sample_1, bone_sample_2) | |
def sample_bone(p_pos, ch_pos): | |
ray = ch_pos - p_pos | |
bone_length = np.linalg.norm(p_pos - ch_pos) | |
num_step = np.round(bone_length / 0.005).astype(int) | |
i_step = np.arange(0, num_step + 1) | |
unit_step = ray / (num_step + 1e-30) | |
unit_step = np.repeat(unit_step[np.newaxis, :], num_step + 1, axis=0) | |
res = p_pos + unit_step * i_step[:, np.newaxis] | |
return res | |
def sample_skel(joints, bones): | |
bone_sample = [] | |
for parent_idx, child_idx in bones: | |
p_pos = joints[parent_idx] | |
ch_pos = joints[child_idx] | |
res = sample_bone(p_pos, ch_pos) | |
bone_sample.append(res) | |
if bone_sample: | |
bone_sample = np.concatenate(bone_sample, axis=0) | |
else: | |
bone_sample = np.empty((0, 3)) | |
return bone_sample |