Spaces:
Runtime error
Runtime error
| import os | |
| import cv2 | |
| import numpy as np | |
| from mpl_toolkits.mplot3d import Axes3D | |
| import matplotlib.pyplot as plt | |
| import matplotlib as mpl | |
| import os | |
| os.environ['PYOPENGL_PLATFORM'] = 'egl' | |
| import pyrender | |
| import trimesh | |
| from config.config import cfg | |
| def vis_keypoints_with_skeleton(img, kps, kps_lines, kp_thresh=0.4, alpha=1): | |
| # Convert from plt 0-1 RGBA colors to 0-255 BGR colors for opencv. | |
| cmap = plt.get_cmap('rainbow') | |
| colors = [cmap(i) for i in np.linspace(0, 1, len(kps_lines) + 2)] | |
| colors = [(c[2] * 255, c[1] * 255, c[0] * 255) for c in colors] | |
| # Perform the drawing on a copy of the image, to allow for blending. | |
| kp_mask = np.copy(img) | |
| # Draw the keypoints. | |
| for l in range(len(kps_lines)): | |
| i1 = kps_lines[l][0] | |
| i2 = kps_lines[l][1] | |
| p1 = kps[0, i1].astype(np.int32), kps[1, i1].astype(np.int32) | |
| p2 = kps[0, i2].astype(np.int32), kps[1, i2].astype(np.int32) | |
| if kps[2, i1] > kp_thresh and kps[2, i2] > kp_thresh: | |
| cv2.line(kp_mask, | |
| p1, | |
| p2, | |
| color=colors[l], | |
| thickness=2, | |
| lineType=cv2.LINE_AA) | |
| if kps[2, i1] > kp_thresh: | |
| cv2.circle(kp_mask, | |
| p1, | |
| radius=3, | |
| color=colors[l], | |
| thickness=-1, | |
| lineType=cv2.LINE_AA) | |
| if kps[2, i2] > kp_thresh: | |
| cv2.circle(kp_mask, | |
| p2, | |
| radius=3, | |
| color=colors[l], | |
| thickness=-1, | |
| lineType=cv2.LINE_AA) | |
| # Blend the keypoints. | |
| return cv2.addWeighted(img, 1.0 - alpha, kp_mask, alpha, 0) | |
| def vis_keypoints(img, kps, alpha=1, radius=3, color=None): | |
| # Convert from plt 0-1 RGBA colors to 0-255 BGR colors for opencv. | |
| cmap = plt.get_cmap('rainbow') | |
| if color is None: | |
| colors = [cmap(i) for i in np.linspace(0, 1, len(kps) + 2)] | |
| colors = [(c[2] * 255, c[1] * 255, c[0] * 255) for c in colors] | |
| # Perform the drawing on a copy of the image, to allow for blending. | |
| kp_mask = np.copy(img) | |
| # Draw the keypoints. | |
| for i in range(len(kps)): | |
| p = kps[i][0].astype(np.int32), kps[i][1].astype(np.int32) | |
| if color is None: | |
| cv2.circle(kp_mask, | |
| p, | |
| radius=radius, | |
| color=colors[i], | |
| thickness=-1, | |
| lineType=cv2.LINE_AA) | |
| else: | |
| cv2.circle(kp_mask, | |
| p, | |
| radius=radius, | |
| color=color, | |
| thickness=-1, | |
| lineType=cv2.LINE_AA) | |
| # Blend the keypoints. | |
| return cv2.addWeighted(img, 1.0 - alpha, kp_mask, alpha, 0) | |
| def vis_mesh(img, mesh_vertex, alpha=0.5): | |
| # Convert from plt 0-1 RGBA colors to 0-255 BGR colors for opencv. | |
| cmap = plt.get_cmap('rainbow') | |
| colors = [cmap(i) for i in np.linspace(0, 1, len(mesh_vertex))] | |
| colors = [(c[2] * 255, c[1] * 255, c[0] * 255) for c in colors] | |
| # Perform the drawing on a copy of the image, to allow for blending. | |
| mask = np.copy(img) | |
| # Draw the mesh | |
| for i in range(len(mesh_vertex)): | |
| p = mesh_vertex[i][0].astype(np.int32), mesh_vertex[i][1].astype( | |
| np.int32) | |
| cv2.circle(mask, | |
| p, | |
| radius=1, | |
| color=colors[i], | |
| thickness=-1, | |
| lineType=cv2.LINE_AA) | |
| # Blend the keypoints. | |
| return cv2.addWeighted(img, 1.0 - alpha, mask, alpha, 0) | |
| def vis_3d_skeleton(kpt_3d, kpt_3d_vis, kps_lines, filename=None): | |
| fig = plt.figure() | |
| ax = fig.add_subplot(111, projection='3d') | |
| # Convert from plt 0-1 RGBA colors to 0-255 BGR colors for opencv. | |
| cmap = plt.get_cmap('rainbow') | |
| colors = [cmap(i) for i in np.linspace(0, 1, len(kps_lines) + 2)] | |
| colors = [np.array((c[2], c[1], c[0])) for c in colors] | |
| for l in range(len(kps_lines)): | |
| i1 = kps_lines[l][0] | |
| i2 = kps_lines[l][1] | |
| x = np.array([kpt_3d[i1, 0], kpt_3d[i2, 0]]) | |
| y = np.array([kpt_3d[i1, 1], kpt_3d[i2, 1]]) | |
| z = np.array([kpt_3d[i1, 2], kpt_3d[i2, 2]]) | |
| if kpt_3d_vis[i1, 0] > 0 and kpt_3d_vis[i2, 0] > 0: | |
| ax.plot(x, z, -y, c=colors[l], linewidth=2) | |
| if kpt_3d_vis[i1, 0] > 0: | |
| ax.scatter(kpt_3d[i1, 0], | |
| kpt_3d[i1, 2], | |
| -kpt_3d[i1, 1], | |
| c=colors[l], | |
| marker='o') | |
| if kpt_3d_vis[i2, 0] > 0: | |
| ax.scatter(kpt_3d[i2, 0], | |
| kpt_3d[i2, 2], | |
| -kpt_3d[i2, 1], | |
| c=colors[l], | |
| marker='o') | |
| x_r = np.array([0, cfg.input_shape[1]], dtype=np.float32) | |
| y_r = np.array([0, cfg.input_shape[0]], dtype=np.float32) | |
| z_r = np.array([0, 1], dtype=np.float32) | |
| if filename is None: | |
| ax.set_title('3D vis') | |
| else: | |
| ax.set_title(filename) | |
| ax.set_xlabel('X Label') | |
| ax.set_ylabel('Z Label') | |
| ax.set_zlabel('Y Label') | |
| ax.legend() | |
| plt.show() | |
| cv2.waitKey(0) | |
| def save_obj(v, f, file_name='output.obj'): | |
| obj_file = open(file_name, 'w') | |
| for i in range(len(v)): | |
| obj_file.write('v ' + str(v[i][0]) + ' ' + str(v[i][1]) + ' ' + | |
| str(v[i][2]) + '\n') | |
| for i in range(len(f)): | |
| obj_file.write('f ' + str(f[i][0] + 1) + '/' + str(f[i][0] + 1) + ' ' + | |
| str(f[i][1] + 1) + '/' + str(f[i][1] + 1) + ' ' + | |
| str(f[i][2] + 1) + '/' + str(f[i][2] + 1) + '\n') | |
| obj_file.close() | |
| def perspective_projection(vertices, cam_param): | |
| # vertices: [N, 3] | |
| # cam_param: [3] | |
| fx, fy = cam_param['focal'] | |
| cx, cy = cam_param['princpt'] | |
| vertices[:, 0] = vertices[:, 0] * fx / vertices[:, 2] + cx | |
| vertices[:, 1] = vertices[:, 1] * fy / vertices[:, 2] + cy | |
| return vertices | |
| def render_mesh(img, mesh, face, cam_param, mesh_as_vertices=False): | |
| if mesh_as_vertices: | |
| # to run on cluster where headless pyrender is not supported for A100/V100 | |
| vertices_2d = perspective_projection(mesh, cam_param) | |
| img = vis_keypoints(img, | |
| vertices_2d, | |
| alpha=0.8, | |
| radius=2, | |
| color=(0, 0, 255)) | |
| else: | |
| # mesh | |
| mesh = trimesh.Trimesh(mesh, face) | |
| rot = trimesh.transformations.rotation_matrix(np.radians(180), | |
| [1, 0, 0]) | |
| mesh.apply_transform(rot) | |
| material = pyrender.MetallicRoughnessMaterial( | |
| metallicFactor=0.0, | |
| alphaMode='OPAQUE', | |
| baseColorFactor=(1.0, 1.0, 0.9, 1.0)) | |
| mesh = pyrender.Mesh.from_trimesh(mesh, | |
| material=material, | |
| smooth=False) | |
| scene = pyrender.Scene(ambient_light=(0.3, 0.3, 0.3)) | |
| scene.add(mesh, 'mesh') | |
| focal, princpt = cam_param['focal'], cam_param['princpt'] | |
| camera = pyrender.IntrinsicsCamera(fx=focal[0], | |
| fy=focal[1], | |
| cx=princpt[0], | |
| cy=princpt[1]) | |
| scene.add(camera) | |
| # renderer | |
| renderer = pyrender.OffscreenRenderer(viewport_width=img.shape[1], | |
| viewport_height=img.shape[0], | |
| point_size=1.0) | |
| # light | |
| light = pyrender.DirectionalLight(color=[1.0, 1.0, 1.0], intensity=0.8) | |
| light_pose = np.eye(4) | |
| light_pose[:3, 3] = np.array([0, -1, 1]) | |
| scene.add(light, pose=light_pose) | |
| light_pose[:3, 3] = np.array([0, 1, 1]) | |
| scene.add(light, pose=light_pose) | |
| light_pose[:3, 3] = np.array([1, 1, 2]) | |
| scene.add(light, pose=light_pose) | |
| # render | |
| rgb, depth = renderer.render(scene, flags=pyrender.RenderFlags.RGBA) | |
| rgb = rgb[:, :, :3].astype(np.float32) | |
| valid_mask = (depth > 0)[:, :, None] | |
| # save to image | |
| img = rgb * valid_mask + img * (1 - valid_mask) | |
| return img | |