给出两个点集A和B,求解点集之间的刚体变化,包含scale,rotation,translate。使其A经过变换之后,可以和B在空间上对齐。
SVD可以用于求解上述问题。
假设有A点集
A
∈
R
n
×
3
A \in R^{n\times 3}
A∈Rn×3, B点集
B
∈
R
n
×
3
B \in R^{n \times 3}
B∈Rn×3,优化的目标是:
a
r
g
m
i
n
R
,
t
∣
∣
R
×
A
+
T
−
B
∣
∣
\underset{R, t}{argmin} \, ||R \times A + T - B||
R,targmin∣∣R×A+T−B∣∣
比如说有两个脸的mesh
他们在空间中不能对的上,贴合程度不高。通过标定一些固定点
即额头的这些点,之所以选择这些点,因为他们基本不随着脸部运动而变化。
然后将选出来的两个点集分别作为src,dst。将src向dst对齐。
def slove_RT_by_SVD(src, dst):
src_mean = src.mean(axis=0, keepdims=True)
dst_mean = dst.mean(axis=0, keepdims=True)
src = src - src_mean # n, 3
dst = dst - dst_mean
H = np.transpose(src) @ dst
U, S, Vt = np.linalg.svd(H)
R = Vt.T @ U.T
if np.linalg.det(R) < 0:
print("Reflection detected")
Vt[2, :] *= -1
R = Vt.T & U.T
t = -R @ src_mean.T + dst_mean.T # 3, 1
return R, t
之所以判断行列式,其原因去参考的【原版原理介绍】中寻找。
然后就能得到极其贴合的两个mesh