|
import numpy as np |
|
import open3d as o3d |
|
from scipy.spatial.transform import Rotation |
|
from scipy.linalg import orthogonal_procrustes |
|
|
|
from open3d.pipelines.registration import registration_ransac_based_on_correspondence |
|
|
|
|
|
def rigid_transform_3D(A, B): |
|
assert A.shape == B.shape, "Input arrays must have the same shape" |
|
assert A.shape[1] == 3, "Input arrays must be Nx3" |
|
|
|
N = A.shape[0] |
|
|
|
|
|
centroid_A = np.mean(A, axis=0) |
|
centroid_B = np.mean(B, axis=0) |
|
|
|
|
|
AA = A - centroid_A |
|
BB = B - centroid_B |
|
|
|
|
|
H = np.dot(AA.T, BB) |
|
|
|
|
|
U, S, Vt = np.linalg.svd(H) |
|
|
|
|
|
R = np.dot(Vt.T, U.T) |
|
|
|
|
|
if np.linalg.det(R) < 0: |
|
Vt[2, :] *= -1 |
|
R = np.dot(Vt.T, U.T) |
|
|
|
|
|
t = centroid_B - np.dot(R, centroid_A) |
|
|
|
|
|
transform_matrix = np.eye(4) |
|
transform_matrix[:3, :3] = R |
|
transform_matrix[:3, 3] = t |
|
|
|
return transform_matrix |
|
|
|
|
|
def compute_rigid_transform(points1, points2): |
|
""" |
|
计算从points1到points2的刚体变换(包括尺度、旋转和平移)。 |
|
|
|
参数: |
|
points1, points2: np.ndarray, 形状为(68, 3)的数组,分别为两组3D对应点。 |
|
|
|
返回: |
|
scale: float, 尺度因子 |
|
R: np.ndarray, 3x3的旋转矩阵 |
|
t: np.ndarray, 3维的平移向量 |
|
""" |
|
|
|
mean1 = np.mean(points1, axis=0) |
|
centered_points1 = points1 - mean1 |
|
mean2 = np.mean(points2, axis=0) |
|
centered_points2 = points2 - mean2 |
|
|
|
|
|
R, _ = orthogonal_procrustes(centered_points1, centered_points2) |
|
t = mean2 - R @ mean1 |
|
|
|
|
|
scale = np.mean(np.linalg.norm(centered_points2, axis=1) / |
|
np.linalg.norm(centered_points1, axis=1)) |
|
|
|
return scale, R, t |
|
|
|
|
|
def compute_rigid_transform_new(points_A, points_B): |
|
|
|
center_A = np.mean(points_A, axis=0) |
|
center_B = np.mean(points_B, axis=0) |
|
points_A_centered = points_A - center_A |
|
points_B_centered = points_B - center_B |
|
|
|
|
|
cov_matrix = np.dot(points_A_centered.T, points_B_centered) |
|
|
|
|
|
U, S, Vt = np.linalg.svd(cov_matrix) |
|
|
|
|
|
rotation_matrix = np.dot(Vt.T, U.T) |
|
|
|
|
|
if np.linalg.det(rotation_matrix) < 0: |
|
Vt[2,:] *= -1 |
|
rotation_matrix = np.dot(Vt.T, U.T) |
|
|
|
|
|
scale = np.trace(np.dot(points_A_centered.T, points_B_centered)) / np.trace(np.dot(points_A_centered.T, points_A_centered)) |
|
|
|
|
|
translation_vector = center_B - scale * np.dot(rotation_matrix, center_A) |
|
|
|
return scale, rotation_matrix, translation_vector |
|
|
|
|
|
|
|
|
|
|
|
obj_A = '/home/gyalex/Desktop/our_face.obj' |
|
obj_B = '/home/gyalex/Desktop/Neutral.obj' |
|
|
|
mesh_A = o3d.io.read_triangle_mesh(obj_A) |
|
mesh_B = o3d.io.read_triangle_mesh(obj_B) |
|
|
|
vertices_A = np.asarray(mesh_A.vertices) |
|
vertices_B = np.asarray(mesh_B.vertices) |
|
|
|
list_A = list() |
|
list_B = list() |
|
with open('/home/gyalex/Desktop/our_marker.txt', 'r') as f: |
|
lines_A = f.readlines() |
|
for line in lines_A: |
|
hh = line.strip().split() |
|
list_A.append(int(hh[0])) |
|
|
|
with open('/home/gyalex/Desktop/ARKit_landmarks.txt', 'r') as f: |
|
lines_B = f.readlines() |
|
for line in lines_B: |
|
hh = line.strip().split() |
|
list_B.append(int(hh[0])) |
|
|
|
A = vertices_A[list_A,:] |
|
B = vertices_B[list_B,:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pcd_source = o3d.utility.Vector3dVector(A) |
|
pcd_target = o3d.utility.Vector3dVector(B) |
|
|
|
corres_source = list() |
|
for idx in range(68): corres_source.append(idx) |
|
corres_target = list() |
|
for idx in range(68): corres_target.append(idx) |
|
|
|
|
|
corres_source_points = pcd_source |
|
corres_target_points = pcd_target |
|
|
|
corres = o3d.utility.Vector2iVector([[src, tgt] for src, tgt in zip(corres_source, corres_target)]) |
|
|
|
|
|
reg_result = registration_ransac_based_on_correspondence( |
|
pcd_source, |
|
pcd_target, |
|
corres, |
|
estimation_method=o3d.pipelines.registration.TransformationEstimationPointToPoint(), |
|
ransac_n=3, |
|
criteria=o3d.pipelines.registration.RANSACConvergenceCriteria(max_iteration=100000, epsilon=1e-6) |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a = 0 |