Spaces:
Sleeping
Sleeping
import torch | |
import numpy as np | |
from sklearn.metrics.pairwise import cosine_similarity | |
from pytorch3d.renderer import ( | |
PerspectiveCameras, | |
look_at_view_transform | |
) | |
# customized | |
import sys | |
sys.path.append(".") | |
from lib.constants import VIEWPOINTS | |
# ---------------- UTILS ---------------------- | |
def degree_to_radian(d): | |
return d * np.pi / 180 | |
def radian_to_degree(r): | |
return 180 * r / np.pi | |
def xyz_to_polar(xyz): | |
""" assume y-axis is the up axis """ | |
x, y, z = xyz | |
theta = 180 * np.arccos(z) / np.pi | |
phi = 180 * np.arccos(y) / np.pi | |
return theta, phi | |
def polar_to_xyz(theta, phi, dist): | |
""" assume y-axis is the up axis """ | |
theta = degree_to_radian(theta) | |
phi = degree_to_radian(phi) | |
x = np.sin(phi) * np.sin(theta) * dist | |
y = np.cos(phi) * dist | |
z = np.sin(phi) * np.cos(theta) * dist | |
return [x, y, z] | |
# ---------------- VIEWPOINTS ---------------------- | |
def filter_viewpoints(pre_viewpoints: dict, viewpoints: dict): | |
""" return the binary mask of viewpoints to be filtered """ | |
filter_mask = [0 for _ in viewpoints.keys()] | |
for i, v in viewpoints.items(): | |
x_v, y_v, z_v = polar_to_xyz(v["azim"], 90 - v["elev"], v["dist"]) | |
for _, pv in pre_viewpoints.items(): | |
x_pv, y_pv, z_pv = polar_to_xyz(pv["azim"], 90 - pv["elev"], pv["dist"]) | |
sim = cosine_similarity( | |
np.array([[x_v, y_v, z_v]]), | |
np.array([[x_pv, y_pv, z_pv]]) | |
)[0, 0] | |
if sim > 0.9: | |
filter_mask[i] = 1 | |
return filter_mask | |
def init_viewpoints(mode, sample_space, init_dist, init_elev, principle_directions, | |
use_principle=True, use_shapenet=False, use_objaverse=False): | |
if mode == "predefined": | |
( | |
dist_list, | |
elev_list, | |
azim_list, | |
sector_list | |
) = init_predefined_viewpoints(sample_space, init_dist, init_elev) | |
elif mode == "hemisphere": | |
( | |
dist_list, | |
elev_list, | |
azim_list, | |
sector_list | |
) = init_hemisphere_viewpoints(sample_space, init_dist) | |
else: | |
raise NotImplementedError() | |
# punishments for views -> in case always selecting the same view | |
view_punishments = [1 for _ in range(len(dist_list))] | |
if use_principle: | |
( | |
dist_list, | |
elev_list, | |
azim_list, | |
sector_list, | |
view_punishments | |
) = init_principle_viewpoints( | |
principle_directions, | |
dist_list, | |
elev_list, | |
azim_list, | |
sector_list, | |
view_punishments, | |
use_shapenet, | |
use_objaverse | |
) | |
return dist_list, elev_list, azim_list, sector_list, view_punishments | |
def init_principle_viewpoints( | |
principle_directions, | |
dist_list, | |
elev_list, | |
azim_list, | |
sector_list, | |
view_punishments, | |
use_shapenet=False, | |
use_objaverse=False | |
): | |
if use_shapenet: | |
key = "shapenet" | |
pre_elev_list = [v for v in VIEWPOINTS[key]["elev"]] | |
pre_azim_list = [v for v in VIEWPOINTS[key]["azim"]] | |
pre_sector_list = [v for v in VIEWPOINTS[key]["sector"]] | |
num_principle = 10 | |
pre_dist_list = [dist_list[0] for _ in range(num_principle)] | |
pre_view_punishments = [0 for _ in range(num_principle)] | |
elif use_objaverse: | |
key = "objaverse" | |
pre_elev_list = [v for v in VIEWPOINTS[key]["elev"]] | |
pre_azim_list = [v for v in VIEWPOINTS[key]["azim"]] | |
pre_sector_list = [v for v in VIEWPOINTS[key]["sector"]] | |
num_principle = 10 | |
pre_dist_list = [dist_list[0] for _ in range(num_principle)] | |
pre_view_punishments = [0 for _ in range(num_principle)] | |
else: | |
num_principle = 6 | |
pre_elev_list = [v for v in VIEWPOINTS[num_principle]["elev"]] | |
pre_azim_list = [v for v in VIEWPOINTS[num_principle]["azim"]] | |
pre_sector_list = [v for v in VIEWPOINTS[num_principle]["sector"]] | |
pre_dist_list = [dist_list[0] for _ in range(num_principle)] | |
pre_view_punishments = [0 for _ in range(num_principle)] | |
dist_list = pre_dist_list + dist_list | |
elev_list = pre_elev_list + elev_list | |
azim_list = pre_azim_list + azim_list | |
sector_list = pre_sector_list + sector_list | |
view_punishments = pre_view_punishments + view_punishments | |
return dist_list, elev_list, azim_list, sector_list, view_punishments | |
def init_predefined_viewpoints(sample_space, init_dist, init_elev): | |
viewpoints = VIEWPOINTS[sample_space] | |
assert sample_space == len(viewpoints["sector"]) | |
dist_list = [init_dist for _ in range(sample_space)] # always the same dist | |
elev_list = [viewpoints["elev"][i] for i in range(sample_space)] | |
azim_list = [viewpoints["azim"][i] for i in range(sample_space)] | |
sector_list = [viewpoints["sector"][i] for i in range(sample_space)] | |
return dist_list, elev_list, azim_list, sector_list | |
def init_hemisphere_viewpoints(sample_space, init_dist): | |
""" | |
y is up-axis | |
""" | |
num_points = 2 * sample_space | |
ga = np.pi * (3. - np.sqrt(5.)) # golden angle in radians | |
flags = [] | |
elev_list = [] # degree | |
azim_list = [] # degree | |
for i in range(num_points): | |
y = 1 - (i / float(num_points - 1)) * 2 # y goes from 1 to -1 | |
# only take the north hemisphere | |
if y >= 0: | |
flags.append(True) | |
else: | |
flags.append(False) | |
theta = ga * i # golden angle increment | |
elev_list.append(radian_to_degree(np.arcsin(y))) | |
azim_list.append(radian_to_degree(theta)) | |
radius = np.sqrt(1 - y * y) # radius at y | |
x = np.cos(theta) * radius | |
z = np.sin(theta) * radius | |
elev_list = [elev_list[i] for i in range(len(elev_list)) if flags[i]] | |
azim_list = [azim_list[i] for i in range(len(azim_list)) if flags[i]] | |
dist_list = [init_dist for _ in elev_list] | |
sector_list = ["good" for _ in elev_list] # HACK don't define sector names for now | |
return dist_list, elev_list, azim_list, sector_list | |
# ---------------- CAMERAS ---------------------- | |
def init_camera(dist, elev, azim, image_size, device): | |
R, T = look_at_view_transform(dist, elev, azim) | |
image_size = torch.tensor([image_size, image_size]).unsqueeze(0) | |
cameras = PerspectiveCameras(R=R, T=T, device=device, image_size=image_size) | |
return cameras |