Open jk4011 opened 3 years ago
This is Old, but if anyone wants it, I mad a quick edit to serialiation.py to include uvs in the obj
# coding: utf-8
__author__ = 'cleardusk'
import numpy as np
import os.path as osp
import scipy.io as sio
from utils.io import _load
from .tddfa_util import _to_ctype
from .functions import get_suffix
header_temp = """ply
format ascii 1.0
element vertex {}
property float x
property float y
property float z
element face {}
property list uchar int vertex_indices
end_header
"""
make_abs_path = lambda fn: osp.join(osp.dirname(osp.realpath(__file__)), fn)
def load_uv_coords(fp):
C = sio.loadmat(fp)
uv_coords = C['UV'].copy(order='C').astype(np.float32)
return uv_coords
def process_uv(uv_coords, uv_h=256, uv_w=256):
uv_coords[:, 0] = uv_coords[:, 0] * (uv_w - 1)
uv_coords[:, 1] = uv_coords[:, 1] * (uv_h - 1)
uv_coords[:, 1] = uv_h - uv_coords[:, 1] - 1
uv_coords = np.hstack((uv_coords, np.zeros((uv_coords.shape[0], 1), dtype=np.float32))) # add z
return uv_coords
g_uv_coords = load_uv_coords(make_abs_path('../configs/BFM_UV.mat'))
indices = _load(make_abs_path('../configs/indices.npy')) # todo: handle bfm_slim
g_uv_coords = g_uv_coords[indices, :]
def ser_to_ply_single(ver_lst, tri, height, wfp, reverse=True):
suffix = get_suffix(wfp)
for i, ver in enumerate(ver_lst):
wfp_new = wfp.replace(suffix, f'_{i + 1}{suffix}')
n_vertex = ver.shape[1]
n_face = tri.shape[0]
header = header_temp.format(n_vertex, n_face)
with open(wfp_new, 'w') as f:
f.write(header + '\n')
for i in range(n_vertex):
x, y, z = ver[:, i]
if reverse:
f.write(f'{x:.2f} {height-y:.2f} {z:.2f}\n')
else:
f.write(f'{x:.2f} {y:.2f} {z:.2f}\n')
for i in range(n_face):
idx1, idx2, idx3 = tri[i] # m x 3
if reverse:
f.write(f'3 {idx3} {idx2} {idx1}\n')
else:
f.write(f'3 {idx1} {idx2} {idx3}\n')
print(f'Dump tp {wfp_new}')
def ser_to_ply_multiple(ver_lst, tri, height, wfp, reverse=True):
n_ply = len(ver_lst) # count ply
if n_ply <= 0:
return
n_vertex = ver_lst[0].shape[1]
n_face = tri.shape[0]
header = header_temp.format(n_vertex * n_ply, n_face * n_ply)
with open(wfp, 'w') as f:
f.write(header + '\n')
for i in range(n_ply):
ver = ver_lst[i]
for j in range(n_vertex):
x, y, z = ver[:, j]
if reverse:
f.write(f'{x:.2f} {height - y:.2f} {z:.2f}\n')
else:
f.write(f'{x:.2f} {y:.2f} {z:.2f}\n')
for i in range(n_ply):
offset = i * n_vertex
for j in range(n_face):
idx1, idx2, idx3 = tri[j] # m x 3
if reverse:
f.write(f'3 {idx3 + offset} {idx2 + offset} {idx1 + offset}\n')
else:
f.write(f'3 {idx1 + offset} {idx2 + offset} {idx3 + offset}\n')
print(f'Dump tp {wfp}')
def get_colors(img, ver):
h, w, _ = img.shape
ver[0, :] = np.minimum(np.maximum(ver[0, :], 0), w - 1) # x
ver[1, :] = np.minimum(np.maximum(ver[1, :], 0), h - 1) # y
ind = np.round(ver).astype(np.int32)
colors = img[ind[1, :], ind[0, :], :] / 255. # n x 3
return colors.copy()
def ser_to_obj_single(img, ver_lst, tri, height, wfp):
suffix = get_suffix(wfp)
uv_coords = g_uv_coords
n_face = tri.shape[0]
for i, ver in enumerate(ver_lst):
colors = get_colors(img, ver)
n_vertex = ver.shape[1]
wfp_new = wfp.replace(suffix, f'_{i + 1}{suffix}')
with open(wfp_new, 'w') as f:
for i in range(n_vertex):
x, y, z = ver[:, i]
f.write(
f'v {x:.2f} {height - y:.2f} {z:.2f} {colors[i, 2]:.2f} {colors[i, 1]:.2f} {colors[i, 0]:.2f}\n')
for i in range(n_vertex):
x, y = uv_coords[:, i]
f.write(
f'vt {x:.2f} {height - y:.2f} {z:.2f}\n')
for i in range(n_face):
idx1, idx2, idx3 = tri[i] # m x 3
f.write(f'f {idx3 + 1} {idx2 + 1} {idx1 + 1}\n')
print(f'Dump tp {wfp_new}')
def ser_to_obj_multiple(img, ver_lst, tri, height, wfp):
n_obj = len(ver_lst) # count obj
if n_obj <= 0:
return
uv_coords = g_uv_coords
print(uv_coords)
n_vertex = ver_lst[0].shape[1]
n_face = tri.shape[0]
with open(wfp, 'w') as f:
for i in range(n_obj):
ver = ver_lst[i]
colors = get_colors(img, ver)
print(ver)
for j in range(n_vertex):
x, y, z = ver[:, j]
f.write(
f'v {x:.2f} {height - y:.2f} {z:.2f} {colors[j, 2]:.2f} {colors[j, 1]:.2f} {colors[j, 0]:.2f}\n')
for i in range(n_obj):
ver = ver_lst[i]
for j in range(n_vertex):
x, y = uv_coords[j]
f.write(
f'vt {x:.6f} {y:.6f}\n')
for i in range(n_obj):
offset = i * n_vertex
for j in range(n_face):
idx1, idx2, idx3 = tri[j] # m x 3
f.write(f'f {idx3 + 1 + offset}/{idx3 + 1 + offset} {idx2 + 1 + offset}/{idx2 + 1 + offset} {idx1 + 1 + offset}/{idx1 + 1 + offset}\n')
print(f'Dump tp {wfp}')
ser_to_ply = ser_to_ply_multiple # ser_to_ply_single
ser_to_obj = ser_to_obj_multiple # ser_to_obj_multiple
First of all, thank you for this wonderful repository. I saved a lot of time and gained excellent results due to your effort.
But I've face a problem. It seems I can't apply uv_tex to obj file created by
demo.py
code. I found there is novt
(vertex texture) in obj file which is essential for uv_tex to be applied. Is uv_tex not purposed for obj, but for some other reasons?Thank you for reading this question!