NeuralBody / lib /utils /render_utils.py
pengsida
initial commit
1ba539f
raw
history blame
5.13 kB
import numpy as np
import json
import os
import cv2
from lib.config import cfg
from lib.utils.if_nerf import if_nerf_data_utils as if_nerf_dutils
def normalize(x):
return x / np.linalg.norm(x)
def viewmatrix(z, up, pos):
vec2 = normalize(z)
vec0_avg = up
vec1 = normalize(np.cross(vec2, vec0_avg))
vec0 = normalize(np.cross(vec1, vec2))
m = np.stack([vec0, vec1, vec2, pos], 1)
return m
def ptstocam(pts, c2w):
tt = np.matmul(c2w[:3, :3].T, (pts-c2w[:3, 3])[..., np.newaxis])[..., 0]
return tt
def load_cam(ann_file):
if ann_file.endswith('.json'):
annots = json.load(open(ann_file, 'r'))
cams = annots['cams']['20190823']
else:
annots = np.load(ann_file, allow_pickle=True).item()
cams = annots['cams']
K = []
RT = []
lower_row = np.array([[0., 0., 0., 1.]])
for i in range(len(cams['K'])):
K.append(np.array(cams['K'][i]))
K[i][:2] = K[i][:2] * cfg.ratio
r = np.array(cams['R'][i])
t = np.array(cams['T'][i]) / 1000.
r_t = np.concatenate([r, t], 1)
RT.append(np.concatenate([r_t, lower_row], 0))
return K, RT
def get_center_rayd(K, RT):
H, W = int(cfg.H * cfg.ratio), int(cfg.W * cfg.ratio)
RT = np.array(RT)
ray_o, ray_d = if_nerf_dutils.get_rays(H, W, K,
RT[:3, :3], RT[:3, 3])
return ray_d[H // 2, W // 2]
def gen_path(RT, center=None):
lower_row = np.array([[0., 0., 0., 1.]])
# transfer RT to camera_to_world matrix
RT = np.array(RT)
RT[:] = np.linalg.inv(RT[:])
RT = np.concatenate([RT[:, :, 1:2], RT[:, :, 0:1],
-RT[:, :, 2:3], RT[:, :, 3:4]], 2)
up = normalize(RT[:, :3, 0].sum(0)) # average up vector
z = normalize(RT[0, :3, 2])
vec1 = normalize(np.cross(z, up))
vec2 = normalize(np.cross(up, vec1))
z_off = 0
if center is None:
center = RT[:, :3, 3].mean(0)
z_off = 1.3
c2w = np.stack([up, vec1, vec2, center], 1)
# get radii for spiral path
tt = ptstocam(RT[:, :3, 3], c2w).T
rads = np.percentile(np.abs(tt), 80, -1)
rads = rads * 1.3
rads = np.array(list(rads) + [1.])
render_w2c = []
for theta in np.linspace(0., 2 * np.pi, cfg.num_render_views + 1)[:-1]:
# camera position
cam_pos = np.array([0, np.sin(theta), np.cos(theta), 1] * rads)
cam_pos_world = np.dot(c2w[:3, :4], cam_pos)
# z axis
z = normalize(cam_pos_world -
np.dot(c2w[:3, :4], np.array([z_off, 0, 0, 1.])))
# vector -> 3x4 matrix (camera_to_world)
mat = viewmatrix(z, up, cam_pos_world)
mat = np.concatenate([mat[:, 1:2], mat[:, 0:1],
-mat[:, 2:3], mat[:, 3:4]], 1)
mat = np.concatenate([mat, lower_row], 0)
mat = np.linalg.inv(mat)
render_w2c.append(mat)
return render_w2c
def read_voxel(frame, args):
voxel_path = os.path.join(args['data_root'], 'voxel', args['human'],
'{}.npz'.format(frame))
voxel_data = np.load(voxel_path)
occupancy = np.unpackbits(voxel_data['compressed_occupancies'])
occupancy = occupancy.reshape(cfg.res, cfg.res,
cfg.res).astype(np.float32)
bounds = voxel_data['bounds'].astype(np.float32)
return occupancy, bounds
def image_rays(RT, K, bounds):
H = cfg.H * cfg.ratio
W = cfg.W * cfg.ratio
ray_o, ray_d = if_nerf_dutils.get_rays(H, W, K,
RT[:3, :3], RT[:3, 3])
ray_o = ray_o.reshape(-1, 3).astype(np.float32)
ray_d = ray_d.reshape(-1, 3).astype(np.float32)
near, far, mask_at_box = if_nerf_dutils.get_near_far(bounds, ray_o, ray_d)
near = near.astype(np.float32)
far = far.astype(np.float32)
ray_o = ray_o[mask_at_box]
ray_d = ray_d[mask_at_box]
center = (bounds[0] + bounds[1]) / 2
scale = np.max(bounds[1] - bounds[0])
return ray_o, ray_d, near, far, center, scale, mask_at_box
def get_image_rays0(RT0, RT, K, bounds):
"""
Use RT to get the mask_at_box and fill this region with rays emitted from view RT0
"""
H = cfg.H * cfg.ratio
ray_o, ray_d = if_nerf_dutils.get_rays(H, H, K,
RT[:3, :3], RT[:3, 3])
ray_o = ray_o.reshape(-1, 3).astype(np.float32)
ray_d = ray_d.reshape(-1, 3).astype(np.float32)
near, far, mask_at_box = if_nerf_dutils.get_near_far(bounds, ray_o, ray_d)
ray_o, ray_d = if_nerf_dutils.get_rays(H, H, K,
RT0[:3, :3], RT0[:3, 3])
ray_d = ray_d.reshape(-1, 3).astype(np.float32)
ray_d = ray_d[mask_at_box]
return ray_d
def save_img(img, frame_root, index, mask_at_box):
H = int(cfg.H * cfg.ratio)
rgb_pred = img['rgb_map'][0].detach().cpu().numpy()
mask_at_box = mask_at_box.reshape(H, H)
img_pred = np.zeros((H, H, 3))
img_pred[mask_at_box] = rgb_pred
img_pred[:, :, [0, 1, 2]] = img_pred[:, :, [2, 1, 0]]
print("saved frame %d" % index)
cv2.imwrite(os.path.join(frame_root, '%d.jpg' % index), img_pred * 255)