카테고리 없음
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()