I want to create 12 images of an object (.obj file) from different angles. The idea is to use pyrender to render a view from upfront of the object, then rotate the camera in 12 steps around the object and render another view each time.
The problem with most of the rendered images is, that parts of the objects are cut off in the image.
I tried to change the parameters of the Orthographic camera (xmag, ymag, znear, zfar) which did not work. I also tried using a perspective camera, which reolved in the same problem. Changing light/camera positions didnt work either.
image_example:
def render_views(in_path, out_path):
def create_rotation_matrix(cam_pose, center, axis, angle):
# Step 1: Translate camera pose to the origin
translation_matrix = np.eye(4)
translation_matrix[:3, 3] = -center
translated_cam_pose = np.dot(translation_matrix, cam_pose)
# Step 2: Create rotation matrix
rotation_matrix = rotation_matrix_from_axis_angle(axis, angle)
# Step 3: Combine translated camera pose and rotation matrix
final_cam_pose = np.dot(rotation_matrix, translated_cam_pose)
return final_cam_pose
def rotation_matrix_from_axis_angle(axis, angle):
# Normalize the axis
axis = axis / np.linalg.norm(axis)
# Calculate components of the rotation matrix
c = np.cos(angle)
s = np.sin(angle)
t = 1 - c
x, y, z = axis
# Build the rotation matrix
rotation_matrix = np.array([
[t*x*x + c, t*x*y - z*s, t*x*z + y*s, 0],
[t*x*y + z*s, t*y*y + c, t*y*z - x*s, 0],
[t*x*z - y*s, t*y*z + x*s, t*z*z + c, 0],
[0, 0, 0, 1]
])
return rotation_matrix
### number of views to create
increment = 12
### factor to set light distance to object -> multiplied with largest dimension later
light_distance_factor = 1
### dimension factor, camera distance to object -> multiplied with largest dimension later
dim_factor = 1
### load obj_file and create mesh
mesh = trimesh.load(in_path)
mesh = pyrender.Mesh.from_trimesh(mesh)
### create light
# light = pyrender.PointLight(color=[1.0, 1.0, 1.0], intensity=2.0)
### create scene and add mesh of object
scene = pyrender.Scene()
scene.add(mesh)
### Find the largest dimension of the object to set camera and light distance accordingly
### Supposed to represent the distance of the two points furthest apart from each other
larg_dim = np.max(mesh.bounds[1]-mesh.bounds[0])
print('###\n ', larg_dim, '\n###')
### set camera distance
cam_dist = dim_factor * larg_dim
# print('###\n ', cam_dist, '\n###')
### set lights distance
light_distance = light_distance_factor * larg_dim
# if lights distance is under 5 it resolves in overlightening
if light_distance <= 5:
light_distance = 5
### create lights around the object and add to scene
for direction in ['front', 'back', 'left', 'right', 'top', 'bottom']:
light_pose = np.eye(4)
print(light_pose)
if direction == 'front':
light_pose[2, 3] = light_distance
elif direction == 'back':
light_pose[2, 3] = -light_distance
elif direction == 'left':
light_pose[0, 3] = -light_distance
elif direction == 'right':
light_pose[0, 3] = light_distance
elif direction == 'top':
light_pose[1, 3] = light_distance
elif direction == 'bottom':
light_pose[1, 3] = -light_distance
light = pyrender.PointLight(color=[1.0, 1.0, 1.0], intensity=50.0)
scene.add(light, pose=light_pose)
### set orthographic camera and add to scene
def_pose = np.eye(4)
camera = pyrender.OrthographicCamera(xmag=cam_dist, ymag=cam_dist, znear=0.05, zfar=3*larg_dim)
cam_node = scene.add(camera, pose=def_pose)
### create renderer
ren = pyrender.OffscreenRenderer(800, 800)
### create views
center_point = np.array([0, 0, 0])
axis_base = [0,1,0]
for inc in range(1,increment+1):
### get current camera-pose, rotate around axis, set new pose to scene
cam_pose = scene.get_pose(cam_node)
rot_axis = np.array(axis_base)
rot_angle = np.pi / increment
cam_pose = create_rotation_matrix(cam_pose, center_point, rot_axis, rot_angle)
scene.set_pose(cam_node, cam_pose)
### render scene
color, _ = ren.render(scene)
### save image
im = Image.fromarray(color)
im.save(os.path.join(out_path, 'renview' + '['+ str(inc) +'].png'))
render_views(src_path, dst_path)
Use the below function instead to generate new poses. You can change it from random if you like to.
Use the camera pose obtained from the above in all the scene.add() for the camera node