|
import torch |
|
import numpy as np |
|
import neural_renderer as nr |
|
from core import path_config |
|
|
|
from models import SMPL |
|
|
|
|
|
class PartRenderer(): |
|
"""Renderer used to render segmentation masks and part segmentations. |
|
Internally it uses the Neural 3D Mesh Renderer |
|
""" |
|
def __init__(self, focal_length=5000., render_res=224): |
|
|
|
self.focal_length = focal_length |
|
self.render_res = render_res |
|
|
|
self.neural_renderer = nr.Renderer( |
|
dist_coeffs=None, |
|
orig_size=self.render_res, |
|
image_size=render_res, |
|
light_intensity_ambient=1, |
|
light_intensity_directional=0, |
|
anti_aliasing=False |
|
) |
|
self.faces = torch.from_numpy(SMPL(path_config.SMPL_MODEL_DIR).faces.astype(np.int32) |
|
).cuda() |
|
textures = np.load(path_config.VERTEX_TEXTURE_FILE) |
|
self.textures = torch.from_numpy(textures).cuda().float() |
|
self.cube_parts = torch.cuda.FloatTensor(np.load(path_config.CUBE_PARTS_FILE)) |
|
|
|
def get_parts(self, parts, mask): |
|
"""Process renderer part image to get body part indices.""" |
|
bn, c, h, w = parts.shape |
|
mask = mask.view(-1, 1) |
|
parts_index = torch.floor(100 * parts.permute(0, 2, 3, 1).contiguous().view(-1, 3)).long() |
|
parts = self.cube_parts[parts_index[:, 0], parts_index[:, 1], parts_index[:, 2], None] |
|
parts *= mask |
|
parts = parts.view(bn, h, w).long() |
|
return parts |
|
|
|
def __call__(self, vertices, camera): |
|
"""Wrapper function for rendering process.""" |
|
|
|
cam_t = torch.stack( |
|
[ |
|
camera[:, 1], camera[:, 2], 2 * self.focal_length / |
|
(self.render_res * camera[:, 0] + 1e-9) |
|
], |
|
dim=-1 |
|
) |
|
batch_size = vertices.shape[0] |
|
K = torch.eye(3, device=vertices.device) |
|
K[0, 0] = self.focal_length |
|
K[1, 1] = self.focal_length |
|
K[2, 2] = 1 |
|
K[0, 2] = self.render_res / 2. |
|
K[1, 2] = self.render_res / 2. |
|
K = K[None, :, :].expand(batch_size, -1, -1) |
|
R = torch.eye(3, device=vertices.device)[None, :, :].expand(batch_size, -1, -1) |
|
faces = self.faces[None, :, :].expand(batch_size, -1, -1) |
|
parts, _, mask = self.neural_renderer( |
|
vertices, |
|
faces, |
|
textures=self.textures.expand(batch_size, -1, -1, -1, -1, -1), |
|
K=K, |
|
R=R, |
|
t=cam_t.unsqueeze(1) |
|
) |
|
parts = self.get_parts(parts, mask) |
|
return mask, parts |
|
|