if False and os.path.exists( scene.render.filepath + "_albedo.exr") and os.path.exists( scene.render.filepath + "_normal.exr") and os.path.exists(scene.render.filepath + "_depth.exr"): print('Skip!') continue bpy.ops.render.render(write_still=True) # render still depth_arr, hard_mask_arr = util.read_depth_and_get_mask( scene.render.filepath + "_depth0001.exr") normal_arr = util.read_and_correct_normal( scene.render.filepath + "_normal0001.exr", correct_normal=correct_normal, mask_arr=hard_mask_arr) albedo_arr = util.read_exr_image(scene.render.filepath + "_albedo0001.exr") # and the clip value range depth_arr = np.clip(depth_arr, a_min=0, a_max=1) normal_arr = np.clip(normal_arr, a_min=-1, a_max=1) albedo_arr = np.clip(albedo_arr, a_min=0, a_max=1) # blender mask depth_arr = np.concatenate( [np.expand_dims(depth_arr, -1), np.expand_dims(hard_mask_arr, -1)], -1) normal_arr = np.concatenate( [normal_arr, np.expand_dims(hard_mask_arr, -1)], -1) albedo_arr = np.concatenate( [albedo_arr, np.expand_dims(hard_mask_arr, -1)], -1) # write out final renderings
def render_passes(depth_file_output, normal_file_output, albedo_file_output, args, rot_angles_list, subfolder_name='gt', output_format='exr'): scene = bpy.context.scene ######### filename for output ############## if 'ShapeNetCore' not in args.obj: model_identifier = args.obj.split('/')[-1].split('.')[0] correct_normal = False else: model_identifier = args.obj.split('/')[-3] correct_normal = True fp = os.path.join(args.output_folder, subfolder_name, model_identifier) scene.render.image_settings.file_format = 'PNG' # set output format to .png # setup camera and render cam_init_location = (0., 0.5, 0.) cam = get_default_camera() cam.location = cam_init_location cam.data.type = 'ORTHO' cam.data.ortho_scale = args.orth_scale cam.data.clip_start = 0 cam.data.clip_end = 100 # a value that is large enough cam_constraint = cam.constraints.new(type='TRACK_TO') cam_constraint.track_axis = 'TRACK_NEGATIVE_Z' cam_constraint.up_axis = 'UP_Y' b_empty = get_lookat_target(cam) cam_constraint.target = b_empty # track to a empty object at the origin # setup light sun_lamp = setup_sunlamp(b_empty) for xyz_angle in rot_angles_list: # rotate camera euler_rot_mat = euler2mat(radians(xyz_angle[0]), radians(xyz_angle[1]), radians(xyz_angle[2]), 'sxyz') new_cam_location = np.dot(euler_rot_mat, np.array(cam_init_location)) cam.location = new_cam_location # the sun lamp follows sun_lamp.location = new_cam_location scene.render.filepath = fp + '-rotx=%.2f_roty=%.2f_rotz=%.2f' % ( xyz_angle[0], xyz_angle[1], xyz_angle[2]) depth_file_output.file_slots[0].path = scene.render.filepath + "_depth" normal_file_output.file_slots[ 0].path = scene.render.filepath + "_normal" albedo_file_output.file_slots[ 0].path = scene.render.filepath + "_albedo" # render and write out bpy.ops.render.render(write_still=True) # render still depth_arr, hard_mask_arr = util.read_depth_and_get_mask( scene.render.filepath + "_depth0001.exr") normal_arr = util.read_and_correct_normal( scene.render.filepath + "_normal0001.exr", correct_normal=correct_normal, mask_arr=hard_mask_arr) albedo_arr = util.read_exr_image(scene.render.filepath + "_albedo0001.exr") # and the clip value range depth_arr = np.clip(depth_arr, a_min=0, a_max=1) normal_arr = np.clip(normal_arr, a_min=-1, a_max=1) albedo_arr = np.clip(albedo_arr, a_min=0, a_max=1) # write out passes if output_format == 'exr': util.write_exr_image(depth_arr, scene.render.filepath + "_depth.exr") #util.write_exr_image(xyz_sworld_arr, scene.render.filepath + "_wxyz.exr") util.write_exr_image(normal_arr, scene.render.filepath + "_normal.exr") #util.write_exr_image(normal_sworld_arr, scene.render.filepath + "_wnormal.exr") util.write_exr_image(albedo_arr, scene.render.filepath + "_albedo.exr") util.write_exr_image(hard_mask_arr, scene.render.filepath + "_mask.exr") elif output_format == 'png': depth_arr = np.array(depth_arr * 255, dtype=np.uint8) depth_pil = Image.fromarray(depth_arr) depth_pil.save(scene.render.filepath + "_depth.png") normal_arr = np.array((normal_arr + 1) / 2. * 255, dtype=np.uint8) normal_pil = Image.fromarray(normal_arr) normal_pil.save(scene.render.filepath + "_normal.png") albedo_arr = np.array(albedo_arr * 255, dtype=np.uint8) albedo_pil = Image.fromarray(albedo_arr) albedo_pil.save(scene.render.filepath + "_albedo.png") hard_mask_arr = np.array(hard_mask_arr * 255, dtype=np.uint8) mask_pil = Image.fromarray(hard_mask_arr) mask_pil.save(scene.render.filepath + "_mask.png") # remove renderings #os.remove(scene.render.filepath+'.png') os.remove(scene.render.filepath + "_normal0001.exr") os.remove(scene.render.filepath + "_depth0001.exr") os.remove(scene.render.filepath + "_albedo0001.exr")
def render_passes_CYCLES(depth_file_output, normal_file_output, albedo_file_output, matidx_file_output, glossdir_file_output, args, rot_angles_list, diag_length=1., subfolder_name='gt', output_format='exr'): scaling_factor_unit2scene = diag_length / 1. scaling_facotr_scene2unit = 1. / diag_length scene = bpy.context.scene ######### filename for output ############## if 'ShapeNetCore' not in args.obj: model_identifier = args.obj.split('/')[-1].split('.')[0] else: model_identifier = args.obj.split('/')[-3] fp = os.path.join(args.output_folder, subfolder_name, model_identifier) scene.render.image_settings.file_format = 'PNG' # set output format to .png # setup camera and render cam_init_location = (0.0 * scaling_factor_unit2scene, 0.5 * scaling_factor_unit2scene, 0.0 * scaling_factor_unit2scene) cam = get_default_camera() cam.location = cam_init_location cam.data.type = 'ORTHO' cam.data.ortho_scale = args.orth_scale * scaling_factor_unit2scene cam.data.clip_start = 0 cam.data.clip_end = 100 # a value that is large enough cam_constraint = cam.constraints.new(type='TRACK_TO') cam_constraint.track_axis = 'TRACK_NEGATIVE_Z' cam_constraint.up_axis = 'UP_Y' b_empty = get_lookat_target(cam) cam_constraint.target = b_empty # track to a empty object at the origin # setup light sun_lamp = setup_sunlamp(b_empty) for xyz_angle in rot_angles_list: # rotate camera euler_rot_mat = euler2mat(radians(xyz_angle[0]), radians(xyz_angle[1]), radians(xyz_angle[2]), 'sxyz') new_cam_location = np.dot(euler_rot_mat, np.array(cam_init_location)) cam.location = new_cam_location # the sun lamp follows sun_lamp.location = new_cam_location scene.render.filepath = fp + '-rotx=%.2f_roty=%.2f_rotz=%.2f'%(xyz_angle[0], xyz_angle[1], xyz_angle[2]) depth_file_output.file_slots[0].path = scene.render.filepath + "_depth" normal_file_output.file_slots[0].path = scene.render.filepath + "_normal" albedo_file_output.file_slots[0].path = scene.render.filepath + "_albedo" matidx_file_output.file_slots[0].path = scene.render.filepath + "_matidx" glossdir_file_output.file_slots[0].path = scene.render.filepath + "_glossdir" # render and write out bpy.ops.render.render(write_still=True, animation=False) # render still depth_arr, hard_mask_arr = util.read_depth_and_get_mask(scene.render.filepath + "_depth0001.exr", depth_scaling_factor=scaling_facotr_scene2unit) normal_arr = util.read_normal(scene.render.filepath + "_normal0001.exr", mask_arr=hard_mask_arr) # in CYCLES, the normal is in world system, rotate it to camera system normal_cam_arr = util.transform_points(np.reshape(normal_arr, (-1, 3)), blender_camera_util.get_world2bcam_R_matrix_from_blender(cam)) normal_cam_arr = np.reshape(normal_cam_arr, normal_arr.shape) normal_arr = normal_cam_arr albedo_arr = util.read_exr_image(scene.render.filepath + "_albedo0001.exr") matidx_arr = util.read_exr_image(scene.render.filepath + "_matidx0001.exr")[:,:,0] glossdir_arr = util.read_exr_image(scene.render.filepath + "_glossdir0001.exr") # and the clip value range depth_arr = np.clip(depth_arr, a_min=0, a_max=1) normal_arr = np.clip(normal_arr, a_min=-1, a_max=1) albedo_arr = np.clip(albedo_arr, a_min=0, a_max=1) glossdir_arr = np.clip(glossdir_arr, a_min=0, a_max=1) # roughness_arr = assemble_roughness_map(matidx_arr) # write out passes if output_format == 'exr': util.write_exr_image(depth_arr, scene.render.filepath + "_depth.exr") #util.write_exr_image(xyz_sworld_arr, scene.render.filepath + "_wxyz.exr") util.write_exr_image(normal_arr, scene.render.filepath + "_normal.exr") #util.write_exr_image(normal_sworld_arr, scene.render.filepath + "_wnormal.exr") util.write_exr_image(albedo_arr, scene.render.filepath + "_albedo.exr") util.write_exr_image(hard_mask_arr, scene.render.filepath + "_mask.exr") util.write_exr_image(glossdir_arr, scene.render.filepath + "_glossdir.exr") util.write_exr_image(roughness_arr, scene.render.filepath + "_roughness.exr") elif output_format == 'png': depth_arr = np.array(depth_arr*255, dtype=np.uint8) depth_pil = Image.fromarray(depth_arr) depth_pil.save(scene.render.filepath + "_depth.png") normal_arr = np.array((normal_arr+1)/2.*255, dtype=np.uint8) normal_pil = Image.fromarray(normal_arr) normal_pil.save(scene.render.filepath + "_normal.png") albedo_arr = np.array(albedo_arr*255, dtype=np.uint8) albedo_pil = Image.fromarray(albedo_arr) albedo_pil.save(scene.render.filepath + "_albedo.png") hard_mask_arr = np.array(hard_mask_arr*255, dtype=np.uint8) mask_pil = Image.fromarray(hard_mask_arr) mask_pil.save(scene.render.filepath + "_mask.png") glossdir_arr = np.array(glossdir_arr*255, dtype=np.uint8) glossdir_pil = Image.fromarray(glossdir_arr) glossdir_pil.save(scene.render.filepath + "_glossdir.png") roughness_arr = np.array(roughness_arr*255, dtype=np.uint8) roughness_pil = Image.fromarray(roughness_arr) roughness_pil.save(scene.render.filepath + "_roughness.png") # remove renderings #os.remove(scene.render.filepath+'.png') os.remove(scene.render.filepath + "_normal0001.exr") os.remove(scene.render.filepath + "_depth0001.exr") os.remove(scene.render.filepath + "_albedo0001.exr") os.remove(scene.render.filepath + "_matidx0001.exr") os.remove(scene.render.filepath + "_glossdir0001.exr")
def scan_point_cloud(depth_file_output, normal_file_output, albedo_file_output, matidx_file_output, args): scene = bpy.context.scene ######### filename for output ############## if 'ShapeNetCore' not in args.obj: model_identifier = args.obj.split('/')[-1].split('.')[0] correct_normal = False else: model_identifier = args.obj.split('/')[-3] correct_normal = True fp = os.path.join(args.output_folder, model_identifier) scene.render.image_settings.file_format = 'PNG' # set output format to .png # scan shapenet shape into point cloud with features all_points_normals_colors_mindices = None for i in range(0, 3): cam = get_default_camera() if i == 1: cam_init_location = (0, 0, 0.5) else: cam_init_location = (0, 0.5, 0) cam.data.type = 'ORTHO' cam.data.ortho_scale = args.orth_scale cam.data.clip_start = 0 cam.data.clip_end = 100 # a value that is large enough cam_constraint = cam.constraints.new(type='TRACK_TO') cam_constraint.track_axis = 'TRACK_NEGATIVE_Z' cam_constraint.up_axis = 'UP_Y' b_empty = get_lookat_target(cam) cam_constraint.target = b_empty # track to a empty object at the origin for rot_angle in range(0, 359, 20): if i == 0: xyz_angle = [rot_angle, 0, 0] elif i == 1: xyz_angle = [0, rot_angle, 0] elif i == 2: xyz_angle = [0, 0, rot_angle] # rotate camera euler_rot_mat = euler2mat(radians(xyz_angle[0]), radians(xyz_angle[1]), radians(xyz_angle[2]), 'sxyz') new_cam_location = np.dot(euler_rot_mat, np.array(cam_init_location)) cam.location = new_cam_location scene.render.filepath = fp + '-rotx=%.2f_roty=%.2f_rotz=%.2f' % ( xyz_angle[0], xyz_angle[1], xyz_angle[2]) depth_file_output.file_slots[ 0].path = scene.render.filepath + "_depth" normal_file_output.file_slots[ 0].path = scene.render.filepath + "_normal" albedo_file_output.file_slots[ 0].path = scene.render.filepath + "_albedo" matidx_file_output.file_slots[ 0].path = scene.render.filepath + "_matidx" # render and write out bpy.ops.render.render(write_still=True) # render still depth_arr, hard_mask_arr = util.read_depth_and_get_mask( scene.render.filepath + "_depth0001.exr") normal_arr = util.read_and_correct_normal( scene.render.filepath + "_normal0001.exr", correct_normal=correct_normal, mask_arr=hard_mask_arr) albedo_arr = util.read_exr_image(scene.render.filepath + "_albedo0001.exr") matidx_arr = util.read_exr_image(scene.render.filepath + "_matidx0001.exr")[:, :, 0] # and the clip value range depth_arr = np.clip(depth_arr, a_min=0, a_max=1) normal_arr = np.clip(normal_arr, a_min=-1, a_max=1) albedo_arr = np.clip(albedo_arr, a_min=0, a_max=1) # process renderings to get the point cloud xyz_arr = util.get_3D_points_from_ortho_depth( depth_arr, args.orth_scale) xyz_normal_rgb_midx = np.reshape( np.concatenate([ xyz_arr, normal_arr, albedo_arr, np.expand_dims(matidx_arr, -1) ], axis=-1), (-1, 10)) xyz_normal_rgb_midx = util.remove_bg_points(xyz_normal_rgb_midx) # transform from depth to 3D world point cloud RT_bcam2world = blender_camera_util.get_bcam2world_RT_matrix_from_blender( cam) # matrix for switching back axis of the obj file when output xyz_normal_rgb_midx[:, :3] = util.transform_points( xyz_normal_rgb_midx[:, :3], np.dot(R_axis_switching_BtoS, RT_bcam2world)) xyz_normal_rgb_midx[:, 3:6] = util.transform_points( xyz_normal_rgb_midx[:, 3:6], np.dot(R_axis_switching_BtoS, RT_bcam2world)) if all_points_normals_colors_mindices is None: all_points_normals_colors_mindices = xyz_normal_rgb_midx else: all_points_normals_colors_mindices = np.concatenate( [all_points_normals_colors_mindices, xyz_normal_rgb_midx], axis=0) # remove renderings os.remove(scene.render.filepath + '.png') os.remove(scene.render.filepath + "_normal0001.exr") os.remove(scene.render.filepath + "_depth0001.exr") os.remove(scene.render.filepath + "_albedo0001.exr") os.remove(scene.render.filepath + "_matidx0001.exr") return all_points_normals_colors_mindices
def render(depth_file_output, normal_file_output, albedo_file_output, args, rot_angles_list, subfolder_name='gt', output_format='exr'): scene = bpy.context.scene scene.render.resolution_x = args.reso scene.render.resolution_y = args.reso scene.render.resolution_percentage = 100 scene.render.alpha_mode = 'TRANSPARENT' scene.render.image_settings.file_format = 'PNG' # set output format to .png ######### filename for output ############## if 'ShapeNetCore' not in args.obj: model_identifier = args.obj.split('/')[-1].split('.')[0] else: model_identifier = args.obj.split('/')[-3] fp = os.path.join(args.output_folder, subfolder_name, model_identifier) # setup camera and render #cam_init_location = (0., 0., -1.3) cam = blender_util.get_default_camera() #cam.location = (0,0,0) cam.matrix_world = mathutils.Matrix.Identity(4) cam.data.sensor_height = args.reso cam.data.sensor_width = args.reso cam.data.lens = args.focal_len cam_constraint = cam.constraints.new(type='TRACK_TO') cam_constraint.track_axis = 'TRACK_NEGATIVE_Z' cam_constraint.up_axis = 'UP_Y' cam_constraint.use_target_z = True b_empty = blender_util.get_lookat_target(cam) for object in bpy.context.scene.objects: if object.name == 'Empty': object.select = True else: object.select = False bpy.ops.transform.rotate(value=-np.pi / 2.0, axis=(1, 0, 0)) cam_constraint.target = b_empty # track to a empty object at the origin K = blender_camera_util.get_calibration_matrix_K_from_blender(cam.data) for aidx, xyz_angle in enumerate(rot_angles_list): mat_loc = mathutils.Matrix.Translation((0.0, 0.0, args.cam_dist)) mat_rot_x = mathutils.Matrix.Rotation(radians(xyz_angle[0]), 4, 'X') mat_rot_y = mathutils.Matrix.Rotation(radians(xyz_angle[1]), 4, 'Y') mat_rot_z = mathutils.Matrix.Rotation(radians(xyz_angle[2]), 4, 'Z') mat_comb = mat_rot_z * mat_rot_y * mat_rot_x * mat_loc cam.matrix_world = mat_comb # the sun lamp follows #sun_lamp.location = new_cam_location scene.render.filepath = fp + '/_rgb_tmp/{:06d}'.format(aidx) #scene.render.filepath = fp + '-rotx=%.2f_roty=%.2f_rotz=%.2f'%(xyz_angle[0], xyz_angle[1], xyz_angle[2]) depth_file_output.file_slots[0].path = scene.render.filepath + "_depth" normal_file_output.file_slots[ 0].path = scene.render.filepath + "_normal" albedo_file_output.file_slots[ 0].path = scene.render.filepath + "_albedo" # render and write out bpy.ops.render.render(write_still=True) # render still depth_arr, hard_mask_arr = util.read_depth_and_get_mask( scene.render.filepath + "_depth0001.exr", far_thre=args.cam_dist + 0.6) normal_arr = util.read_and_correct_normal(scene.render.filepath + "_normal0001.exr", correct_normal=True, mask_arr=hard_mask_arr) albedo_arr = util.read_exr_image(scene.render.filepath + "_albedo0001.exr") # and the clip value range depth_arr = np.clip(depth_arr, a_min=0, a_max=1) normal_arr = np.clip(normal_arr, a_min=-1, a_max=1) albedo_arr = np.clip(albedo_arr, a_min=0, a_max=1) if output_format == 'png': depth_arr = np.array(depth_arr * 255, dtype=np.uint8) depth_pil = Image.fromarray(depth_arr) if not os.path.exists(os.path.join(fp, '_depth')): os.makedirs(os.path.join(fp, '_depth')) depth_pil.save( os.path.join(fp, '_depth', '{:06d}.png'.format(aidx))) normal_arr = np.array((normal_arr + 1) / 2. * 255, dtype=np.uint8) normal_pil = Image.fromarray(normal_arr) if not os.path.exists(os.path.join(fp, '_normal')): os.makedirs(os.path.join(fp, '_normal')) normal_pil.save( os.path.join(fp, '_normal', '{:06d}.png'.format(aidx))) albedo_arr = np.array(albedo_arr * 255, dtype=np.uint8) albedo_pil = Image.fromarray(albedo_arr) if not os.path.exists(os.path.join(fp, '_albedo')): os.makedirs(os.path.join(fp, '_albedo')) albedo_pil.save( os.path.join(fp, '_albedo', '{:06d}.png'.format(aidx))) hard_mask_arr = np.array(hard_mask_arr * 255, dtype=np.uint8) mask_pil = Image.fromarray(hard_mask_arr) if not os.path.exists(os.path.join(fp, '_mask')): os.makedirs(os.path.join(fp, '_mask')) mask_pil.save(os.path.join(fp, '_mask', '{:06d}.png'.format(aidx))) # remove renderings #os.remove(scene.render.filepath+'.png') os.remove(scene.render.filepath + "_normal0001.exr") os.remove(scene.render.filepath + "_depth0001.exr") os.remove(scene.render.filepath + "_albedo0001.exr") #os.remove('Image0001.exr') # intrinsic output if not os.path.exists(os.path.join(fp, 'intrinsics')): os.makedirs(os.path.join(fp, 'intrinsics')) intrinsic_params = np.array(K).flatten() np.savetxt(os.path.join(fp, 'intrinsics', '{:06d}.txt'.format(aidx)), intrinsic_params[None], fmt='%1.1f') # get camera pose: cam2world matrix RT = blender_camera_util.get_3x4_RT_matrix_from_blender(cam) RT4 = np.zeros((4, 4)) RT4[:3, :4] = RT RT4[3, 3] = 1 cam2world_mat = np.linalg.inv(RT4) #print(cam2world_mat) if not os.path.exists(os.path.join(fp, 'pose')): os.makedirs(os.path.join(fp, 'pose')) pose_params = np.array(cam2world_mat).flatten() np.savetxt(os.path.join(fp, 'pose', '{:06d}.txt'.format(aidx)), pose_params[None], fmt='%1.6f') # intrinsic output #print(K) f_out = K[0][0] cx = K[0][2] cy = K[1][2] im_width = args.reso im_height = args.reso with open(os.path.join(fp, 'intrinsics.txt'), 'w') as f: f.write("%1.6f %1.6f %1.6f %1.2f\n" % (float(f_out), float(cx), float(cy), 0.)) f.write("0. 0. 0.\n") f.write("1.\n") f.write("%d %d\n" % (im_width, im_height))