|
""" |
|
This script is borrowed from https://github.com/mkocabas/VIBE |
|
Adhere to their licence to use this script |
|
It has been modified |
|
""" |
|
|
|
import os |
|
import math |
|
import trimesh |
|
|
|
import pyrender |
|
import numpy as np |
|
from pyrender.constants import RenderFlags |
|
|
|
|
|
|
|
|
|
|
|
SMPL_MODEL_DIR = "data/smpl_data/" |
|
|
|
|
|
def get_smpl_faces(): |
|
return np.load(os.path.join(SMPL_MODEL_DIR, "smplfaces.npy")) |
|
|
|
|
|
class WeakPerspectiveCamera(pyrender.Camera): |
|
def __init__(self, |
|
scale, |
|
translation, |
|
znear=pyrender.camera.DEFAULT_Z_NEAR, |
|
zfar=None, |
|
name=None): |
|
super(WeakPerspectiveCamera, self).__init__( |
|
znear=znear, |
|
zfar=zfar, |
|
name=name, |
|
) |
|
self.scale = scale |
|
self.translation = translation |
|
|
|
def get_projection_matrix(self, width=None, height=None): |
|
P = np.eye(4) |
|
P[0, 0] = self.scale[0] |
|
P[1, 1] = self.scale[1] |
|
P[0, 3] = self.translation[0] * self.scale[0] |
|
P[1, 3] = -self.translation[1] * self.scale[1] |
|
P[2, 2] = -1 |
|
return P |
|
|
|
|
|
class Renderer: |
|
def __init__(self, background=None, resolution=(224, 224), bg_color=[0, 0, 0, 0.5], orig_img=False, wireframe=False, cam_pose=np.eye(4)): |
|
width, height = resolution |
|
self.background = np.zeros((height, width, 3)) |
|
self.resolution = resolution |
|
|
|
self.faces = get_smpl_faces() |
|
self.orig_img = orig_img |
|
self.wireframe = wireframe |
|
self.renderer = pyrender.OffscreenRenderer( |
|
viewport_width=self.resolution[0], |
|
viewport_height=self.resolution[1], |
|
point_size=0.5 |
|
) |
|
|
|
|
|
self.scene = pyrender.Scene(bg_color=bg_color, ambient_light=(0.4, 0.4, 0.4)) |
|
|
|
light = pyrender.PointLight(color=[1.0, 1.0, 1.0], intensity=4) |
|
|
|
|
|
light_pose = np.eye(4) |
|
light_pose[:3, 3] = [0, -1, 1] |
|
self.scene.add(light, pose=np.dot(cam_pose,light_pose).copy()) |
|
|
|
light_pose[:3, 3] = [0, 1, 1] |
|
self.scene.add(light, pose=np.dot(cam_pose,light_pose).copy()) |
|
|
|
light_pose[:3, 3] = [1, 1, 2] |
|
self.scene.add(light, pose=np.dot(cam_pose,light_pose).copy()) |
|
|
|
"""ok |
|
light_pose = np.eye(4) |
|
light_pose[:3, 3] = [0, -1, 1] |
|
self.scene.add(light, pose=light_pose) |
|
|
|
light_pose[:3, 3] = [0, 1, 1] |
|
self.scene.add(light, pose=light_pose) |
|
|
|
light_pose[:3, 3] = [1, 1, 2] |
|
self.scene.add(light, pose=light_pose) |
|
""" |
|
|
|
|
|
|
|
""" |
|
light_pose = np.eye(4) |
|
light_pose[:3, 3] = [0, -1, 1] |
|
self.scene.add(light, pose=light_pose) |
|
|
|
light_pose[:3, 3] = [0, 1, 1] |
|
self.scene.add(light, pose=light_pose) |
|
|
|
light_pose[:3, 3] = [1, 1, 2] |
|
self.scene.add(light, pose=light_pose) |
|
""" |
|
|
|
def render(self, img, verts, cam, angle=None, axis=None, mesh_filename=None, color=[1.0, 1.0, 0.9], |
|
cam_pose=np.eye(4)): |
|
mesh = trimesh.Trimesh(vertices=verts, faces=self.faces, process=False) |
|
Rx = trimesh.transformations.rotation_matrix(math.radians(180), [1, 0, 0]) |
|
|
|
mesh.apply_transform(Rx) |
|
|
|
if mesh_filename is not None: |
|
mesh.export(mesh_filename) |
|
|
|
if angle and axis: |
|
R = trimesh.transformations.rotation_matrix(math.radians(angle), axis) |
|
mesh.apply_transform(R) |
|
|
|
sx, sy, tx, ty = cam |
|
|
|
camera = WeakPerspectiveCamera( |
|
scale=[sx, sy], |
|
translation=[tx, ty], |
|
zfar=100000. |
|
) |
|
|
|
material = pyrender.MetallicRoughnessMaterial( |
|
metallicFactor=0.0, |
|
|
|
alphaMode='OPAQUE', |
|
baseColorFactor=(color[0], color[1], color[2], 1.0) |
|
) |
|
|
|
mesh = pyrender.Mesh.from_trimesh(mesh, material=material) |
|
|
|
mesh_node = self.scene.add(mesh, 'mesh') |
|
|
|
cam_node = self.scene.add(camera, pose=cam_pose) |
|
|
|
if self.wireframe: |
|
render_flags = RenderFlags.RGBA | RenderFlags.ALL_WIREFRAME |
|
else: |
|
render_flags = RenderFlags.RGBA |
|
|
|
rgb, _ = self.renderer.render(self.scene, flags=render_flags) |
|
if rgb.shape[-1]==3: |
|
|
|
|
|
valid_mask = (rgb[:, :, -1] > 0)[:, :, np.newaxis] |
|
output_img = rgb * valid_mask + (1 - valid_mask) * img |
|
elif rgb.shape[-1]==4: |
|
|
|
|
|
|
|
|
|
valid_mask = (rgb[:, :, -1] > 128)[:, :] |
|
output_img = np.copy(rgb) |
|
output_img[:, :, -1] *= valid_mask |
|
|
|
else: |
|
raise ValueError(f"rgb shape {rgb.shape[-1]} is not correct!") |
|
image = output_img.astype(np.uint8) |
|
|
|
self.scene.remove_node(mesh_node) |
|
self.scene.remove_node(cam_node) |
|
|
|
return image |
|
|
|
|
|
def get_renderer(width, height, cam_pose): |
|
renderer = Renderer(resolution=(width, height), |
|
bg_color=[1, 1, 1, 0.5], |
|
orig_img=False, |
|
wireframe=False, |
|
cam_pose=cam_pose) |
|
return renderer |
|
|