Base Line/python 기초 코드
Depth_Render.py
ylab
2022. 3. 16. 08:23
##Depth_Render.py
"""
무수한 주석처리 양해좀 ㅎㅎ
"""
import torch.nn as nn
import torch
#from engineer.render.PIFuhd import gl
# 기본으로 해줘야됨
from .Base_Render import _Base_Render
# 노말 체크
from .registry import NORMAL_RENDER
# face3D
from engineer.render.face3d import mesh
import numpy as np
from PIL import Image
######check
from math import cos, sin
def similarity_transform(vertices, s, R, t3d):
''' similarity transform. dof = 7.
3D: s*R.dot(X) + t
Homo: M = [[sR, t],[0^T, 1]]. M.dot(X)
Args:(float32)
vertices: [nver, 3].
s: [1,]. scale factor.
R: [3,3]. rotation matrix.
t3d: [3,]. 3d translation vector.
Returns:
transformed vertices: [nver, 3]
'''
t3d = np.squeeze(np.array(t3d, dtype = np.float32))
transformed_vertices = s * vertices.dot(R.T) + t3d[np.newaxis, :]
return transformed_vertices
def to_image(vertices, h, w, is_perspective = False):
''' change vertices to image coord system
3d system: XYZ, center(0, 0, 0)
2d image: x(u), y(v). center(w/2, h/2), flip y-axis.
Args:
vertices: [nver, 3]
h: height of the rendering
w : width of the rendering
Returns:
projected_vertices: [nver, 3]
'''
image_vertices = vertices.copy()
if is_perspective:
# if perspective, the projected vertices are normalized to [-1, 1]. so change it to image size first.
image_vertices[:,0] = image_vertices[:,0]*w/2
image_vertices[:,1] = image_vertices[:,1]*h/2
# move to center of image
image_vertices[:,0] = image_vertices[:,0] + w/2
image_vertices[:,1] = image_vertices[:,1] + h/2
# flip vertices along y-axis.
image_vertices[:,1] = h - image_vertices[:,1] - 1
return image_vertices
def angle2matrix(angles):
''' get rotation matrix from three rotation angles(degree). right-handed.
Args:
angles: [3,]. x, y, z angles
x: pitch. positive for looking down.
y: yaw. positive for looking left.
z: roll. positive for tilting head right.
Returns:
R: [3, 3]. rotation matrix.
'''
x, y, z = np.deg2rad(angles[0]), np.deg2rad(angles[1]), np.deg2rad(angles[2])
# x
Rx=np.array([[1, 0, 0],
[0, cos(x), -sin(x)],
[0, sin(x), cos(x)]])
# y
Ry=np.array([[ cos(y), 0, sin(y)],
[ 0, 1, 0],
[-sin(y), 0, cos(y)]])
# z
Rz=np.array([[cos(z), -sin(z), 0],
[sin(z), cos(z), 0],
[ 0, 0, 1]])
R=Rz.dot(Ry.dot(Rx))
return R.astype(np.float32)
@NORMAL_RENDER.register_module
class Noraml_Render(_Base_Render):
"""Render class for getting normal map
here attribute is based on vertex normal
we normalized value of them into [0,1]
Note that trimesh.verts_normals normal always from [-1, 1]
"""
def __init__(self, width: int, height: int, render_lib="face3d", flip=False):
super(Noraml_Render, self).__init__(width, height, render_lib)
self.__render = self.render_lib
self.name = "Normal_render"
self.flip_normal = flip
self.input_para["flip_normal"] = flip
self.render_image = None
self.render_mask = None
def set_attribute(self):
"""attribute you want to set when you render
For normal render class, we only need normal information, which means
"""
# vertices = self.render_mesh.vertices
#
# [-1,1]
# render_mesh !!!
#self.z = self.render_mesh.vertices[:, 2:]
h,w=self.height,self.width
R=angle2matrix([0,0,0])
t=[0,0,0]
self.vertices = self.render_mesh.vertices[:,:]
s=180/(np.max(self.vertices[:,1])-np.min(self.vertices[:,1]))
transformed_vertices = similarity_transform(self.vertices,s,R,t)
image_vertices = to_image(transformed_vertices,h,w)
self.z = image_vertices[:,2:]
self.z = self.z - np.min(self.z)
self.z = self.z / (np.max(self.z)-np.min(self.z))
self.z=self.z-1
#self.z=get_z_value(self.z)
self.attribute = self.z
####
def get_render(self):
"""capture render images
Parameters:
None
return:
render_image [H, W, C = 3]
render_mask [H, W] ---> 0 means background else frontground
"""
assert self.render_image is not None, "you need call draw method, previously"
assert self.render_mask is not None, "you need call draw method, previously"
return self.render_image, self.render_mask
def draw(self):
"""draw render image,
it needs you set_mesh, previously.
after call draw method, you will get two attribute, render image and render mask
"""
#####face3d 노말 랜더링 사용 부분
if self.render_lib == "face3d":
attribute = self.attribute
#attribute = np.concatenate(
# [self.attribute, np.ones([self.attribute.shape[0], 1])], axis=1
#)
# render_colors face에서 컬러 합치는 부분 attribute => 노말
# normal_map = mesh.render.render_colors(self.render_mesh.vertices, self.render_mesh.faces, attribute, self.height, self.width, c=4)
depth_image = mesh.render.render_colors(
self.render_mesh.vertices,
self.render_mesh.faces,
attribute,
self.height,
self.width,
c=1,
)
#mask = depth_image[..., 3]
mask = depth_image[...]
print(np.shape(depth_image))
#print(1111111111)
depth_image = depth_image[...]
#depth_image = depth_image[... 2:]
#depth_image = (depth_image + 1) / 2
# 배열 이미지로 변환 255는 정규화? 0~255 맞추기
depth_image=np.squeeze(depth_image,axis=2)
self.render_image = Image.fromarray((depth_image * 255).astype(np.uint8))
self.render_mask = mask
else:
raise NotImplementedError
Thank you for pifuhd & open-pifuhd