def run_fuse(self): """ Run fusion. """ assert os.path.exists(self.options.depth_dir) common.makedir(self.options.out_dir) files = self.read_directory(self.options.depth_dir) timer = common.Timer() Rs = self.get_views() for filepath in files: # As rendering might be slower, we wait for rendering to finish. # This allows to run rendering and fusing in parallel (more or less). depths = common.read_hdf5(filepath) timer.reset() tsdf = self.fusion(depths, Rs) tsdf = tsdf[0] vertices, triangles = libmcubes.marching_cubes(-tsdf, 0) vertices /= self.options.resolution vertices -= 0.5 off_file = os.path.join(self.options.out_dir, ntpath.basename(filepath)[:-3]) libmcubes.export_off(vertices, triangles, off_file) print('[Data] wrote %s (%f seconds)' % (off_file, timer.elapsed()))
def test_export(): u = np.zeros((10, 10, 10)) u[2:-2, 2:-2, 2:-2] = 1.0 vertices, triangles = mcubes.marching_cubes(u, 0.5) mcubes.export_obj(vertices, triangles, "output/test.obj") mcubes.export_off(vertices, triangles, "output/test.off") mcubes.export_mesh(vertices, triangles, "output/test.dae")
def process_mesh(obj_path, view_ids, cam_Ks, cam_RTs): ''' script for prepare watertigt mesh for training :param obj (str): object path :param view_ids (N-d list): which view ids would like to render (from 1 to total_view_nums). :param cam_Ks (N x 3 x 3): camera intrinsic parameters. :param cam_RTs (N x 3 x 3): camera extrinsic parameters. :return: ''' cat, model = obj_path.split('/')[3:5] '''Decide save path''' output_file = os.path.join(watertight_mesh_path, cat, model, 'model.off') if os.path.exists(output_file): return None if not os.path.exists(os.path.join(watertight_mesh_path, cat, model)): os.makedirs(os.path.join(watertight_mesh_path, cat, model)) '''Begin to process''' obj_dir = os.path.join(shapenet_rendering_path, cat, model) dist_map_dir = [ os.path.join(obj_dir, 'depth_{0:03d}.exr'.format(view_id)) for view_id in view_ids ] dist_maps = read_exr(dist_map_dir) depth_maps = np.float32(dist_to_dep(dist_maps, cam_Ks, erosion_size=2)) cam_Rs = np.float32(cam_RTs[:, :, :-1]) cam_Ts = np.float32(cam_RTs[:, :, -1]) views = pyfusion.PyViews(depth_maps, cam_Ks, cam_Rs, cam_Ts) voxel_size = 1. / voxel_res truncation = truncation_factor * voxel_size tsdf = pyfusion.tsdf_gpu(views, voxel_res, voxel_res, voxel_res, voxel_size, truncation, False) mask_grid = pyfusion.projmask_gpu(views, voxel_res, voxel_res, voxel_res, voxel_size, False) tsdf[mask_grid == 0.] = truncation # rotate to the correct system tsdf = np.transpose(tsdf[0], [2, 1, 0]) # To ensure that the final mesh is indeed watertight tsdf = np.pad(tsdf, 1, 'constant', constant_values=1e6) vertices, triangles = mcubes.marching_cubes(-tsdf, 0) # Remove padding offset vertices -= 1 # Normalize to [-0.5, 0.5]^3 cube vertices /= voxel_res vertices -= 0.5 mcubes.export_off(vertices, triangles, output_file)
def batch_scan(input_obj): output_path = os.path.join(ShapeNetv2_Watertight_path, '/'.join(input_obj.split('/')[2:4]) + '.off') if os.path.exists(output_path): return else: if not os.path.exists(os.path.dirname(output_path)): os.mkdir(os.path.dirname(output_path)) obj_file = read_obj(input_obj, flags=('v', 'f')) vertices = obj_file['v'] faces = obj_file['f'] faces = np.array([[int(face_id.split('/')[0]) for face_id in item] for item in faces]) '''Scale to [-0.5, 0.5], center at 0.''' center = (vertices.max(0) + vertices.min(0)) / 2. scale = max(vertices.max(0) - vertices.min(0)) scale = scale / (1 - padding) vertices_normalized = (vertices - center) / scale '''Render depth maps''' camera_Rs = get_views(n_camera_views) depths = render(vertices=vertices_normalized, faces=faces, camera_Rs=camera_Rs) '''Fuse depth maps''' tsdf = fuse_depthmaps(depths, camera_Rs) # To ensure that the final mesh is indeed watertight tsdf = np.pad(tsdf, 1, 'constant', constant_values=1e6) vertices, triangles = mcubes.marching_cubes(-tsdf, 0) # Remove padding offset vertices -= 1 # Normalize to [-0.5, 0.5]^3 cube vertices /= resolution vertices -= 0.5 '''scale back''' vertices = vertices * scale + center mcubes.export_off(vertices, triangles, output_path)
import mcubes if __name__ == '__main__': if len(sys.argv) < 2: print('[Data] Usage python 10_reconstruct.py config_folder') exit(1) config_folder = sys.argv[1] + '/' assert os.path.exists( config_folder), 'directory %s does not exist' % config_folder for config_file in os.listdir(config_folder): print('[Data] reading ' + config_folder + config_file) config = utils.read_json(config_folder + config_file) sdf_file = common.filename(config, 'sdf_file') assert os.path.exists(sdf_file), 'file %s does not exist' % sdf_file sdfs = utils.read_hdf5(sdf_file) sdfs = sdfs.squeeze() reconstructed_directory = common.dirname(config, 'reconstructed_dir') utils.makedir(reconstructed_directory) for n in range(sdfs.shape[0]): vertices, triangles = mcubes.marching_cubes( -sdfs[n].transpose(1, 0, 2), 0) off_file = reconstructed_directory + '/%d.off' % n mcubes.export_off(vertices, triangles, off_file) print('[Data] wrote %s' % off_file)