|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Literal |
|
import tyro |
|
import numpy as np |
|
from PIL import Image |
|
from pathlib import Path |
|
import torch |
|
import nvdiffrast.torch as dr |
|
from vhap.util.render_uvmap import render_uvmap_vtex |
|
from vhap.model.flame import FlameHead |
|
|
|
|
|
FLAME_UV_MASK_FOLDER = "asset/flame/uv_masks" |
|
FLAME_UV_MASK_NPZ = "asset/flame/uv_masks.npz" |
|
|
|
|
|
def main( |
|
use_opengl: bool = False, |
|
device: Literal['cuda', 'cpu'] = 'cuda', |
|
): |
|
n_shape = 300 |
|
n_expr = 100 |
|
print("Initializing FLAME model") |
|
flame_model = FlameHead(n_shape, n_expr, add_teeth=True) |
|
|
|
flame_model = FlameHead( |
|
n_shape, |
|
n_expr, |
|
add_teeth=True, |
|
).cuda() |
|
|
|
faces = flame_model.faces.int().cuda() |
|
verts_uv = flame_model.verts_uvs.cuda() |
|
|
|
faces_uv = flame_model.textures_idx.int().cuda() |
|
col_idx = faces_uv |
|
|
|
|
|
glctx = dr.RasterizeGLContext() if use_opengl else dr.RasterizeCudaContext() |
|
|
|
h, w = 2048, 2048 |
|
resolution = (h, w) |
|
|
|
if not Path(FLAME_UV_MASK_FOLDER).exists(): |
|
Path(FLAME_UV_MASK_FOLDER).mkdir(parents=True) |
|
|
|
|
|
masks = {} |
|
for region, vt_mask in flame_model.mask.vt: |
|
v_color = torch.zeros(verts_uv.shape[0], 1).to(device) |
|
v_color[vt_mask] = 1 |
|
|
|
alpha = render_uvmap_vtex(glctx, verts_uv, faces_uv, v_color, col_idx, resolution)[0] |
|
alpha = alpha.flip(0) |
|
|
|
mask = (alpha > 0.5) |
|
mask = mask.squeeze(-1).cpu().numpy() |
|
masks[region] = mask |
|
|
|
print(f"Saving uv mask for {region}...") |
|
|
|
|
|
|
|
img = mask |
|
img = Image.fromarray((img * 255).astype(np.uint8)) |
|
img.save(Path(FLAME_UV_MASK_FOLDER) / f"{region}.png") |
|
|
|
print(f"Saving uv mask into: {FLAME_UV_MASK_NPZ}") |
|
np.savez_compressed(FLAME_UV_MASK_NPZ, **masks) |
|
|
|
|
|
if __name__ == "__main__": |
|
tyro.cli(main) |