Spaces:
Running
Running
import numpy as np | |
import scipy | |
def generate_interpolated_path(poses, n_interp, spline_degree=5, | |
smoothness=.03, rot_weight=.1): | |
"""Creates a smooth spline path between input keyframe camera poses. | |
Spline is calculated with poses in format (position, lookat-point, up-point). | |
Args: | |
poses: (n, 3, 4) array of input pose keyframes. | |
n_interp: returned path will have n_interp * (n - 1) total poses. | |
spline_degree: polynomial degree of B-spline. | |
smoothness: parameter for spline smoothing, 0 forces exact interpolation. | |
rot_weight: relative weighting of rotation/translation in spline solve. | |
Returns: | |
Array of new camera poses with shape (n_interp * (n - 1), 3, 4). | |
""" | |
def poses_to_points(poses, dist): | |
"""Converts from pose matrices to (position, lookat, up) format.""" | |
pos = poses[:, :3, -1] | |
lookat = poses[:, :3, -1] - dist * poses[:, :3, 2] | |
up = poses[:, :3, -1] + dist * poses[:, :3, 1] | |
return np.stack([pos, lookat, up], 1) | |
def points_to_poses(points): | |
"""Converts from (position, lookat, up) format to pose matrices.""" | |
return np.array([viewmatrix(p - l, u - p, p) for p, l, u in points]) | |
def interp(points, n, k, s): | |
"""Runs multidimensional B-spline interpolation on the input points.""" | |
sh = points.shape | |
pts = np.reshape(points, (sh[0], -1)) | |
k = min(k, sh[0] - 1) | |
tck, _ = scipy.interpolate.splprep(pts.T, k=k, s=s) | |
u = np.linspace(0, 1, n, endpoint=False) | |
new_points = np.array(scipy.interpolate.splev(u, tck)) | |
new_points = np.reshape(new_points.T, (n, sh[1], sh[2])) | |
return new_points | |
### Additional operation | |
# inter_poses = [] | |
# for pose in poses: | |
# tmp_pose = np.eye(4) | |
# tmp_pose[:3] = np.concatenate([pose.R.T, pose.T[:, None]], 1) | |
# tmp_pose = np.linalg.inv(tmp_pose) | |
# tmp_pose[:, 1:3] *= -1 | |
# inter_poses.append(tmp_pose) | |
# inter_poses = np.stack(inter_poses, 0) | |
# poses, transform = transform_poses_pca(inter_poses) | |
points = poses_to_points(poses, dist=rot_weight) | |
new_points = interp(points, | |
n_interp * (points.shape[0] - 1), | |
k=spline_degree, | |
s=smoothness) | |
return points_to_poses(new_points) | |
def viewmatrix(lookdir, up, position): | |
"""Construct lookat view matrix.""" | |
vec2 = normalize(lookdir) | |
vec0 = normalize(np.cross(up, vec2)) | |
vec1 = normalize(np.cross(vec2, vec0)) | |
m = np.stack([vec0, vec1, vec2, position], axis=1) | |
return m | |
def normalize(x): | |
"""Normalization helper function.""" | |
return x / np.linalg.norm(x) |