카테고리 없음

python pyrender

Small Octopus 2019. 11. 21. 21:14

# OBJ file을 읽어서 Rendering 하는 방법

# obj 파일을 읽어 드리기 위해 trimesh를 임포트한다.
import trimesh
# rendering을 위해 pyrender를 임포트한다.
import pyrender

# trimesh.load를 이용해 obj파일을 로드한다.  
fuze_trimesh = trimesh.load('./fuze.obj')

# trimesh.base.Trimesh 타입으로 로드 되며
# vertex와 tri face 정보를 담고 있다. 
print(type(fuze_trimesh))
# fuze_trimesh.vertices 변수에 tuple로 float64 v x 3 형태로 3차원 vertex들을 담고 있다.
print(fuze_trimesh.vertices.shape)
# fuze_trimesh.faces 변수에 tuple로 int64 f x 3 형태로 vertex index를 담고 있다.
print(fuze_trimesh.faces.shape)

# pyrender.Mesh.from_trimesh을 이용해서 pyrender에서 
# rendering 할 수 있는 객체로 변환한다.
mesh = pyrender.Mesh.from_trimesh(fuze_trimesh)

# Scene을 생성한다
scene = pyrender.Scene()
# rendering 할 객체를 추가한다.
scene.add(mesh)
# Viewer를 이용해서 rendering한다.
# use_raymond_lighting은 카메라 축과 동일하게 움직이는 
# three dictional light가 추가된다.
pyrender.Viewer(scene, use_raymond_lighting=True)

 

# Offscreen 에 rendering 하는 방법, 이미지 위에 그림

import trimesh
import pyrender
import numpy as np
import cv2

img_res = 224
image = cv2.imread('./IU.jpg')
#image = cv2.resize(image, (img_res, img_res))
image = image/255.0

fuze_trimesh = trimesh.load('./fuze.obj')

# vertices 와 face 가 주워졌다고 가정하면
vertices = fuze_trimesh.vertices
faces = fuze_trimesh.faces

# trimesh.Trimesh를 사용해서 vertices와 faces를 하나의
# mesh로 묶어준다.
tri_mesh = trimesh.Trimesh(vertices, faces)

# mesh에 회전변환을 줄 수 있다.
angle = np.radians(-100)
direction = [1, 1, 1]
rot = trimesh.transformations.rotation_matrix(angle, direction)
tri_mesh.apply_transform(rot)

# texture 재질 설정
# metallic-roughness material를 사용해보자
# metallicFactor: 금속성을 20% 주고
# alphaMode를 OPAQUE(불투명)로 설정, BLEND로 설정하면 alpha blending 된다.
material = pyrender.MetallicRoughnessMaterial(
metallicFactor=0.2,
alphaMode='OPAQUE',
baseColorFactor=(0.8, 0.3, 0.3, 1.0))

# trimesh에서 pyrender Mesh로 변환하면서 재질을 설정할 수있다.
render_mesh = pyrender.Mesh.from_trimesh(tri_mesh, material)

# scene 생성
scene = pyrender.Scene(ambient_light=(0.5, 0.5, 0.5))

# mesh 등록
scene.add(render_mesh, 'mesh')

# light 생성
light = pyrender.DirectionalLight(color=[1.0, 1.0, 1.0], intensity=1)

# camera 위치 설정
camera_pose = np.eye(4)
#camera_pose[:3, 3] = np.array([-2.0560150e-01, -4.1626684e-02,  4.2518742e+01])
camera_pose[:3, 3] = np.array([0, 0.1,  7])
# camera intricsic params
focal_length, cx, cy = 5000.0, img_res//2, img_res//2
camera = pyrender.IntrinsicsCamera(fx=focal_length, fy=focal_length, cx=cx, cy=cy)
scene.add(camera, pose=camera_pose)

# light 위치 설정
light_pose = np.eye(4)
# x는 0, y는 -1, z는 1 만큼 이동한 곳에서
# 비추어라, 이동만 줌
light_pose[:3, 3] = np.array([0, -1, 1])
scene.add(light, pose=light_pose)

# 다른 위치 라이트 추가
light_pose[:3, 3] = np.array([0, 1, 1])
scene.add(light, pose=light_pose)
#light_pose[:3, 3] = np.array([1, 1, 2])
#scene.add(light, pose=light_pose)

# OffscreenRenderer 생성
renderer = pyrender.OffscreenRenderer(viewport_width=img_res,
viewport_height=img_res,
point_size=1.0)

# image로 rendering
color, rend_depth = renderer.render(scene, flags=pyrender.RenderFlags.RGBA)

valid_mask = (rend_depth > 0)[:, :, None]
output_img = (color[:, :, :3] * valid_mask + (1 - valid_mask) * image)

cv2.imshow('render', np.uint8(output_img*255))
cv2.waitKey()