fasd / tddfa /utils /uv.py
ozyman's picture
added depth model
ddadf19
raw
history blame
2.92 kB
# coding: utf-8
__author__ = 'cleardusk'
import sys
sys.path.append('..')
import cv2
import numpy as np
import os.path as osp
import scipy.io as sio
from Sim3DR import rasterize
from utils.functions import plot_image
from utils.io import _load
from utils.tddfa_util import _to_ctype
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 get_colors(img, ver):
# nearest-neighbor sampling
[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, :], :] # n x 3
return colors
def bilinear_interpolate(img, x, y):
"""
https://stackoverflow.com/questions/12729228/simple-efficient-bilinear-interpolation-of-images-in-numpy-and-python
"""
x0 = np.floor(x).astype(np.int32)
x1 = x0 + 1
y0 = np.floor(y).astype(np.int32)
y1 = y0 + 1
x0 = np.clip(x0, 0, img.shape[1] - 1)
x1 = np.clip(x1, 0, img.shape[1] - 1)
y0 = np.clip(y0, 0, img.shape[0] - 1)
y1 = np.clip(y1, 0, img.shape[0] - 1)
i_a = img[y0, x0]
i_b = img[y1, x0]
i_c = img[y0, x1]
i_d = img[y1, x1]
wa = (x1 - x) * (y1 - y)
wb = (x1 - x) * (y - y0)
wc = (x - x0) * (y1 - y)
wd = (x - x0) * (y - y0)
return wa[..., np.newaxis] * i_a + wb[..., np.newaxis] * i_b + wc[..., np.newaxis] * i_c + wd[..., np.newaxis] * i_d
def uv_tex(img, ver_lst, tri, uv_h=256, uv_w=256, uv_c=3, show_flag=False, wfp=None):
uv_coords = process_uv(g_uv_coords.copy(), uv_h=uv_h, uv_w=uv_w)
res_lst = []
for ver_ in ver_lst:
ver = _to_ctype(ver_.T) # transpose to m x 3
colors = bilinear_interpolate(img, ver[:, 0], ver[:, 1]) / 255.
# `rasterize` here serves as texture sampling, may need to optimization
res = rasterize(uv_coords, tri, colors, height=uv_h, width=uv_w, channel=uv_c)
res_lst.append(res)
# concat if there more than one image
res = np.concatenate(res_lst, axis=1) if len(res_lst) > 1 else res_lst[0]
if wfp is not None:
cv2.imwrite(wfp, res)
print(f'Save visualization result to {wfp}')
if show_flag:
plot_image(res)
return res