Spaces:
Configuration error
Configuration error
# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. | |
import math | |
import numpy as np | |
import sys | |
import os | |
from render.camera import Camera | |
from render.color_render import ColorRender | |
import trimesh | |
import cv2 | |
import os | |
import argparse | |
from termcolor import colored | |
width = 512 | |
height = 512 | |
def normalize_v3(arr): | |
''' Normalize a numpy array of 3 component vectors shape=(n,3) ''' | |
lens = np.sqrt(arr[:, 0]**2 + arr[:, 1]**2 + arr[:, 2]**2) | |
eps = 0.00000001 | |
lens[lens < eps] = eps | |
arr[:, 0] /= lens | |
arr[:, 1] /= lens | |
arr[:, 2] /= lens | |
return arr | |
def compute_normal(vertices, faces): | |
# Create a zeroed array with the same type and shape as our vertices i.e., per vertex normal | |
norm = np.zeros(vertices.shape, dtype=vertices.dtype) | |
# Create an indexed view into the vertex array using the array of three indices for triangles | |
tris = vertices[faces] | |
# Calculate the normal for all the triangles, by taking the cross product of the vectors v1-v0, and v2-v0 in each triangle | |
n = np.cross(tris[::, 1] - tris[::, 0], tris[::, 2] - tris[::, 0]) | |
# n is now an array of normals per triangle. The length of each normal is dependent the vertices, | |
# we need to normalize these, so that our next step weights each normal equally. | |
normalize_v3(n) | |
# now we have a normalized array of normals, one per triangle, i.e., per triangle normals. | |
# But instead of one per triangle (i.e., flat shading), we add to each vertex in that triangle, | |
# the triangles' normal. Multiple triangles would then contribute to every vertex, so we need to normalize again afterwards. | |
# The cool part, we can actually add the normals through an indexed view of our (zeroed) per vertex normal array | |
norm[faces[:, 0]] += n | |
norm[faces[:, 1]] += n | |
norm[faces[:, 2]] += n | |
normalize_v3(norm) | |
return norm | |
def make_rotate(rx, ry, rz): | |
sinX = np.sin(rx) | |
sinY = np.sin(ry) | |
sinZ = np.sin(rz) | |
cosX = np.cos(rx) | |
cosY = np.cos(ry) | |
cosZ = np.cos(rz) | |
Rx = np.zeros((3, 3)) | |
Rx[0, 0] = 1.0 | |
Rx[1, 1] = cosX | |
Rx[1, 2] = -sinX | |
Rx[2, 1] = sinX | |
Rx[2, 2] = cosX | |
Ry = np.zeros((3, 3)) | |
Ry[0, 0] = cosY | |
Ry[0, 2] = sinY | |
Ry[1, 1] = 1.0 | |
Ry[2, 0] = -sinY | |
Ry[2, 2] = cosY | |
Rz = np.zeros((3, 3)) | |
Rz[0, 0] = cosZ | |
Rz[0, 1] = -sinZ | |
Rz[1, 0] = sinZ | |
Rz[1, 1] = cosZ | |
Rz[2, 2] = 1.0 | |
R = np.matmul(np.matmul(Rz, Ry), Rx) | |
return R | |
parser = argparse.ArgumentParser() | |
parser.add_argument('-ww', '--width', type=int, default=512) | |
parser.add_argument('-hh', '--height', type=int, default=512) | |
parser.add_argument('--exp_name', type=str) | |
parser.add_argument('--dataset', type=str) | |
parser.add_argument('--mesh_ind', type=int, default=0) | |
args = parser.parse_args() | |
renderer = ColorRender(width=args.width, height=args.height) | |
cam = Camera(width=1.0, height=args.height / args.width) | |
cam.ortho_ratio = 1.2 | |
cam.near = -100 | |
cam.far = 10 | |
data_root = 'data/result/if_nerf/{}/mesh'.format( | |
args.exp_name) | |
obj_path = os.path.join(data_root, '{:04d}.ply'.format(args.mesh_ind)) | |
mesh_render_dir = os.path.join(data_root, 'mesh{}_render'.format(args.mesh_ind)) | |
os.system('mkdir -p {}'.format(mesh_render_dir)) | |
obj_files = [obj_path] | |
if args.dataset == 'zju_mocap': | |
R = make_rotate(0, math.radians(0), 0) # zju-mocap | |
else: | |
R = make_rotate(0, math.radians(90), math.radians(90)) # people-snapshot | |
print(colored('the results are saved at {}'.format(mesh_render_dir), 'yellow')) | |
for i, obj_path in enumerate(obj_files): | |
print(obj_path) | |
obj_file = obj_path.split('/')[-1] | |
file_name = obj_file[:-4] | |
if not os.path.exists(obj_path): | |
continue | |
mesh = trimesh.load(obj_path) | |
vertices = mesh.vertices | |
faces = mesh.faces | |
rot = np.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]]) | |
vertices = np.dot(vertices, rot.T) | |
mesh.vertices = vertices | |
vertices = np.matmul(vertices, R.T) | |
bbox_max = vertices.max(0) | |
bbox_min = vertices.min(0) | |
# notice that original scale is discarded to render with the same size | |
vertices -= 0.5 * (bbox_max + bbox_min)[None, :] | |
vertices /= bbox_max[1] - bbox_min[1] | |
normals = compute_normal(vertices, faces) | |
renderer.set_mesh(vertices, faces, 0.5 * normals + 0.5, faces) | |
self_rot = make_rotate(i, math.radians(-90), 0) | |
vertices = np.matmul(vertices, self_rot.T) | |
cnt = 0 | |
for j in range(0, 361, 4): | |
cam.center = np.array([0, 0, 0]) | |
cam.eye = np.array([ | |
2.0 * math.sin(math.radians(0)), 0, 2.0 * math.cos(math.radians(0)) | |
]) + cam.center | |
self_rot = make_rotate(i, math.radians(-4), 0) | |
vertices = np.matmul(vertices, self_rot.T) | |
normals = compute_normal(vertices, faces) | |
renderer.set_mesh(vertices, faces, 0.5 * normals + 0.5, faces) | |
renderer.set_camera(cam) | |
renderer.display() | |
img = renderer.get_color(0) | |
img = cv2.cvtColor(img, cv2.COLOR_RGBA2BGRA) | |
img = img[..., :3] | |
cv2.imwrite(os.path.join(mesh_render_dir, '%d.jpg' % cnt), 255 * img) | |
cnt += 1 | |