| | |
| | |
| | |
| |
|
| | from typing import List, Tuple |
| | import numpy as np |
| | from mGPT.utils.joints import mmm_kinematic_tree, mmm_to_smplh_scaling_factor |
| |
|
| | mmm_colors = ['black', 'magenta', 'red', 'green', 'blue'] |
| |
|
| |
|
| | def init_axis(fig, title, radius=1.5, dist=10): |
| | ax = fig.add_subplot(1, 1, 1, projection='3d') |
| | ax.view_init(elev=20., azim=-60) |
| |
|
| | fact = 2 |
| | ax.set_xlim3d([-radius / fact, radius / fact]) |
| | ax.set_ylim3d([-radius / fact, radius / fact]) |
| | ax.set_zlim3d([0, radius]) |
| |
|
| | ax.set_aspect('auto') |
| | ax.set_xticklabels([]) |
| | ax.set_yticklabels([]) |
| | ax.set_zticklabels([]) |
| |
|
| | ax.set_axis_off() |
| |
|
| | ax.dist = dist |
| | ax.grid(b=False) |
| |
|
| | ax.set_title(title, loc='center', wrap=True) |
| | return ax |
| |
|
| |
|
| | def plot_floor(ax, minx, maxx, miny, maxy, minz): |
| | from mpl_toolkits.mplot3d.art3d import Poly3DCollection |
| | |
| | verts = [ |
| | [minx, miny, minz], |
| | [minx, maxy, minz], |
| | [maxx, maxy, minz], |
| | [maxx, miny, minz] |
| | ] |
| | xz_plane = Poly3DCollection([verts], zorder=1) |
| | xz_plane.set_facecolor((0.5, 0.5, 0.5, 1)) |
| | ax.add_collection3d(xz_plane) |
| |
|
| | |
| | radius = max((maxx - minx), (maxy - miny)) |
| |
|
| | |
| | minx_all = (maxx + minx) / 2 - radius |
| | maxx_all = (maxx + minx) / 2 + radius |
| |
|
| | miny_all = (maxy + miny) / 2 - radius |
| | maxy_all = (maxy + miny) / 2 + radius |
| |
|
| | verts = [ |
| | [minx_all, miny_all, minz], |
| | [minx_all, maxy_all, minz], |
| | [maxx_all, maxy_all, minz], |
| | [maxx_all, miny_all, minz] |
| | ] |
| | xz_plane = Poly3DCollection([verts], zorder=1) |
| | xz_plane.set_facecolor((0.5, 0.5, 0.5, 0.5)) |
| | ax.add_collection3d(xz_plane) |
| | return ax |
| |
|
| |
|
| | def update_camera(ax, root, radius=1.5): |
| | fact = 2 |
| | ax.set_xlim3d([-radius / fact + root[0], radius / fact + root[0]]) |
| | ax.set_ylim3d([-radius / fact + root[1], radius / fact + root[1]]) |
| |
|
| |
|
| | def render_animation(joints: np.ndarray, output: str = "notebook", title: str = "", |
| | fps: float = 12.5, |
| | kinematic_tree: List[List[int]] = mmm_kinematic_tree, |
| | colors: List[str] = mmm_colors, |
| | figsize: Tuple[int] = (4, 4), |
| | fontsize: int = 15): |
| | import matplotlib.pyplot as plt |
| | from matplotlib.animation import FuncAnimation |
| | import matplotlib.patheffects as pe |
| | plt.rcParams.update({'font.size': fontsize}) |
| |
|
| | |
| | x, y, z = 0, 1, 2 |
| |
|
| | |
| | |
| | joints = joints.copy()[..., [2, 0, 1]] * mmm_to_smplh_scaling_factor |
| |
|
| | |
| | fig = plt.figure(figsize=figsize) |
| | ax = init_axis(fig, title) |
| |
|
| | |
| | trajectory = joints[:, 0, [x, y]] |
| | avg_segment_length = np.mean(np.linalg.norm(np.diff(trajectory, axis=0), axis=1)) + 1e-3 |
| | draw_offset = int(25 / avg_segment_length) |
| | spline_line, = ax.plot(*trajectory.T, zorder=10, color="white") |
| |
|
| | |
| | minx, miny, _ = joints.min(axis=(0, 1)) |
| | maxx, maxy, _ = joints.max(axis=(0, 1)) |
| | plot_floor(ax, minx, maxx, miny, maxy, 0) |
| |
|
| | |
| | height_offset = np.min(joints[:, :, z]) |
| | joints = joints.copy() |
| | joints[:, :, z] -= height_offset |
| |
|
| | |
| | lines = [] |
| | initialized = False |
| |
|
| | def update(frame): |
| | nonlocal initialized |
| | skeleton = joints[frame] |
| |
|
| | root = skeleton[0] |
| | update_camera(ax, root) |
| |
|
| | for index, (chain, color) in enumerate(zip(reversed(kinematic_tree), reversed(colors))): |
| | if not initialized: |
| | lines.append(ax.plot(skeleton[chain, x], |
| | skeleton[chain, y], |
| | skeleton[chain, z], linewidth=8.0, color=color, zorder=20, |
| | path_effects=[pe.SimpleLineShadow(), pe.Normal()])) |
| |
|
| | else: |
| | lines[index][0].set_xdata(skeleton[chain, x]) |
| | lines[index][0].set_ydata(skeleton[chain, y]) |
| | lines[index][0].set_3d_properties(skeleton[chain, z]) |
| |
|
| | left = max(frame - draw_offset, 0) |
| | right = min(frame + draw_offset, trajectory.shape[0]) |
| |
|
| | spline_line.set_xdata(trajectory[left:right, 0]) |
| | spline_line.set_ydata(trajectory[left:right, 1]) |
| | spline_line.set_3d_properties(np.zeros_like(trajectory[left:right, 0])) |
| | initialized = True |
| |
|
| | fig.tight_layout() |
| | frames = joints.shape[0] |
| | anim = FuncAnimation(fig, update, frames=frames, interval=1000 / fps, repeat=False) |
| |
|
| | if output == "notebook": |
| | from IPython.display import HTML |
| | HTML(anim.to_jshtml()) |
| | else: |
| | anim.save(output, writer='ffmpeg', fps=fps) |
| |
|
| | plt.close() |
| |
|