|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import torch |
|
import numpy as np |
|
|
|
|
|
class ViewProcessor: |
|
def __init__(self, config, render): |
|
self.config = config |
|
self.render = render |
|
|
|
def render_normal_multiview(self, camera_elevs, camera_azims, use_abs_coor=True): |
|
normal_maps = [] |
|
for elev, azim in zip(camera_elevs, camera_azims): |
|
normal_map = self.render.render_normal(elev, azim, use_abs_coor=use_abs_coor, return_type="pl") |
|
normal_maps.append(normal_map) |
|
|
|
return normal_maps |
|
|
|
def render_position_multiview(self, camera_elevs, camera_azims): |
|
position_maps = [] |
|
for elev, azim in zip(camera_elevs, camera_azims): |
|
position_map = self.render.render_position(elev, azim, return_type="pl") |
|
position_maps.append(position_map) |
|
|
|
return position_maps |
|
|
|
def bake_view_selection( |
|
self, candidate_camera_elevs, candidate_camera_azims, candidate_view_weights, max_selected_view_num |
|
): |
|
|
|
original_resolution = self.render.default_resolution |
|
self.render.set_default_render_resolution(1024) |
|
|
|
selected_camera_elevs = [] |
|
selected_camera_azims = [] |
|
selected_view_weights = [] |
|
selected_alpha_maps = [] |
|
viewed_tri_idxs = [] |
|
viewed_masks = [] |
|
|
|
|
|
face_areas = self.render.get_face_areas(from_one_index=True) |
|
total_area = face_areas.sum() |
|
face_area_ratios = face_areas / total_area |
|
|
|
candidate_view_num = len(candidate_camera_elevs) |
|
self.render.set_boundary_unreliable_scale(2) |
|
|
|
for elev, azim in zip(candidate_camera_elevs, candidate_camera_azims): |
|
viewed_tri_idx = self.render.render_alpha(elev, azim, return_type="np") |
|
viewed_tri_idxs.append(set(np.unique(viewed_tri_idx.flatten()))) |
|
viewed_masks.append(viewed_tri_idx[0, :, :, 0] > 0) |
|
|
|
is_selected = [False for _ in range(candidate_view_num)] |
|
total_viewed_tri_idxs = set() |
|
total_viewed_area = 0.0 |
|
|
|
for idx in range(6): |
|
selected_camera_elevs.append(candidate_camera_elevs[idx]) |
|
selected_camera_azims.append(candidate_camera_azims[idx]) |
|
selected_view_weights.append(candidate_view_weights[idx]) |
|
selected_alpha_maps.append(viewed_masks[idx]) |
|
is_selected[idx] = True |
|
total_viewed_tri_idxs.update(viewed_tri_idxs[idx]) |
|
|
|
total_viewed_area = face_area_ratios[list(total_viewed_tri_idxs)].sum() |
|
for iter in range(max_selected_view_num - len(selected_view_weights)): |
|
max_inc = 0 |
|
max_idx = -1 |
|
|
|
for idx, (elev, azim, weight) in enumerate( |
|
zip(candidate_camera_elevs, candidate_camera_azims, candidate_view_weights) |
|
): |
|
if is_selected[idx]: |
|
continue |
|
new_tri_idxs = viewed_tri_idxs[idx] - total_viewed_tri_idxs |
|
new_inc_area = face_area_ratios[list(new_tri_idxs)].sum() |
|
|
|
if new_inc_area > max_inc: |
|
max_inc = new_inc_area |
|
max_idx = idx |
|
|
|
if max_inc > 0.01: |
|
is_selected[max_idx] = True |
|
selected_camera_elevs.append(candidate_camera_elevs[max_idx]) |
|
selected_camera_azims.append(candidate_camera_azims[max_idx]) |
|
selected_view_weights.append(candidate_view_weights[max_idx]) |
|
selected_alpha_maps.append(viewed_masks[max_idx]) |
|
total_viewed_tri_idxs = total_viewed_tri_idxs.union(viewed_tri_idxs[max_idx]) |
|
total_viewed_area += max_inc |
|
else: |
|
break |
|
|
|
self.render.set_default_render_resolution(original_resolution) |
|
|
|
return selected_camera_elevs, selected_camera_azims, selected_view_weights |
|
|
|
def bake_from_multiview(self, views, camera_elevs, camera_azims, view_weights): |
|
project_textures, project_weighted_cos_maps = [], [] |
|
project_boundary_maps = [] |
|
|
|
for view, camera_elev, camera_azim, weight in zip(views, camera_elevs, camera_azims, view_weights): |
|
project_texture, project_cos_map, project_boundary_map = self.render.back_project( |
|
view, camera_elev, camera_azim |
|
) |
|
project_cos_map = weight * (project_cos_map**self.config.bake_exp) |
|
project_textures.append(project_texture) |
|
project_weighted_cos_maps.append(project_cos_map) |
|
project_boundary_maps.append(project_boundary_map) |
|
texture, ori_trust_map = self.render.fast_bake_texture(project_textures, project_weighted_cos_maps) |
|
return texture, ori_trust_map > 1e-8 |
|
|
|
def texture_inpaint(self, texture, mask, defualt=None): |
|
if defualt is not None: |
|
mask = mask.astype(bool) |
|
inpaint_value = torch.tensor(defualt, dtype=texture.dtype, device=texture.device) |
|
texture[~mask] = inpaint_value |
|
else: |
|
texture_np = self.render.uv_inpaint(texture, mask) |
|
texture = torch.tensor(texture_np / 255).float().to(texture.device) |
|
|
|
return texture |
|
|