Spaces:
Paused
Paused
| ''' | |
| Modify from | |
| https://github.com/Kai-46/nerfplusplus/blob/master/data_loader_split.py | |
| ''' | |
| import os | |
| import glob | |
| import scipy | |
| import imageio | |
| import numpy as np | |
| import torch | |
| ######################################################################################################################## | |
| # camera coordinate system: x-->right, y-->down, z-->scene (opencv/colmap convention) | |
| # poses is camera-to-world | |
| ######################################################################################################################## | |
| def find_files(dir, exts): | |
| if os.path.isdir(dir): | |
| files_grabbed = [] | |
| for ext in exts: | |
| files_grabbed.extend(glob.glob(os.path.join(dir, ext))) | |
| if len(files_grabbed) > 0: | |
| files_grabbed = sorted(files_grabbed) | |
| return files_grabbed | |
| else: | |
| return [] | |
| def load_data_split(split_dir, skip=1, try_load_min_depth=True, only_img_files=False): | |
| def parse_txt(filename): | |
| assert os.path.isfile(filename) | |
| nums = open(filename).read().split() | |
| return np.array([float(x) for x in nums]).reshape([4, 4]).astype(np.float32) | |
| if only_img_files: | |
| img_files = find_files('{}/rgb'.format(split_dir), exts=['*.png', '*.jpg']) | |
| return img_files | |
| # camera parameters files | |
| intrinsics_files = find_files('{}/intrinsics'.format(split_dir), exts=['*.txt']) | |
| pose_files = find_files('{}/pose'.format(split_dir), exts=['*.txt']) | |
| intrinsics_files = intrinsics_files[::skip] | |
| pose_files = pose_files[::skip] | |
| cam_cnt = len(pose_files) | |
| # img files | |
| img_files = find_files('{}/rgb'.format(split_dir), exts=['*.png', '*.jpg']) | |
| if len(img_files) > 0: | |
| img_files = img_files[::skip] | |
| assert(len(img_files) == cam_cnt) | |
| else: | |
| img_files = [None, ] * cam_cnt | |
| # mask files | |
| mask_files = find_files('{}/mask'.format(split_dir), exts=['*.png', '*.jpg']) | |
| if len(mask_files) > 0: | |
| mask_files = mask_files[::skip] | |
| assert(len(mask_files) == cam_cnt) | |
| else: | |
| mask_files = [None, ] * cam_cnt | |
| # min depth files | |
| mindepth_files = find_files('{}/min_depth'.format(split_dir), exts=['*.png', '*.jpg']) | |
| if try_load_min_depth and len(mindepth_files) > 0: | |
| mindepth_files = mindepth_files[::skip] | |
| assert(len(mindepth_files) == cam_cnt) | |
| else: | |
| mindepth_files = [None, ] * cam_cnt | |
| return intrinsics_files, pose_files, img_files, mask_files, mindepth_files | |
| def rerotate_poses(poses, render_poses): | |
| poses = np.copy(poses) | |
| centroid = poses[:,:3,3].mean(0) | |
| poses[:,:3,3] = poses[:,:3,3] - centroid | |
| # Find the minimum pca vector with minimum eigen value | |
| x = poses[:,:3,3] | |
| mu = x.mean(0) | |
| cov = np.cov((x-mu).T) | |
| ev , eig = np.linalg.eig(cov) | |
| cams_up = eig[:,np.argmin(ev)] | |
| if cams_up[1] < 0: | |
| cams_up = -cams_up | |
| # Find rotation matrix that align cams_up with [0,1,0] | |
| R = scipy.spatial.transform.Rotation.align_vectors( | |
| [[0,-1,0]], cams_up[None])[0].as_matrix() | |
| # Apply rotation and add back the centroid position | |
| poses[:,:3,:3] = R @ poses[:,:3,:3] | |
| poses[:,:3,[3]] = R @ poses[:,:3,[3]] | |
| poses[:,:3,3] = poses[:,:3,3] + centroid | |
| render_poses = np.copy(render_poses) | |
| render_poses[:,:3,3] = render_poses[:,:3,3] - centroid | |
| render_poses[:,:3,:3] = R @ render_poses[:,:3,:3] | |
| render_poses[:,:3,[3]] = R @ render_poses[:,:3,[3]] | |
| render_poses[:,:3,3] = render_poses[:,:3,3] + centroid | |
| return poses, render_poses | |
| def load_nerfpp_data(basedir, rerotate=True): | |
| tr_K, tr_c2w, tr_im_path = load_data_split(os.path.join(basedir, 'train'))[:3] | |
| te_K, te_c2w, te_im_path = load_data_split(os.path.join(basedir, 'test'))[:3] | |
| assert len(tr_K) == len(tr_c2w) and len(tr_K) == len(tr_im_path) | |
| assert len(te_K) == len(te_c2w) and len(te_K) == len(te_im_path) | |
| # Determine split id list | |
| i_split = [[], []] | |
| i = 0 | |
| for _ in tr_c2w: | |
| i_split[0].append(i) | |
| i += 1 | |
| for _ in te_c2w: | |
| i_split[1].append(i) | |
| i += 1 | |
| # Load camera intrinsics. Assume all images share a intrinsic. | |
| K_flatten = np.loadtxt(tr_K[0]) | |
| for path in tr_K: | |
| assert np.allclose(np.loadtxt(path), K_flatten) | |
| for path in te_K: | |
| assert np.allclose(np.loadtxt(path), K_flatten) | |
| K = K_flatten.reshape(4,4)[:3,:3] | |
| # Load camera poses | |
| poses = [] | |
| for path in tr_c2w: | |
| poses.append(np.loadtxt(path).reshape(4,4)) | |
| for path in te_c2w: | |
| poses.append(np.loadtxt(path).reshape(4,4)) | |
| # Load images | |
| imgs = [] | |
| for path in tr_im_path: | |
| imgs.append(imageio.imread(path) / 255.) | |
| for path in te_im_path: | |
| imgs.append(imageio.imread(path) / 255.) | |
| # Bundle all data | |
| imgs = np.stack(imgs, 0) | |
| poses = np.stack(poses, 0) | |
| i_split.append(i_split[1]) | |
| H, W = imgs.shape[1:3] | |
| focal = K[[0,1], [0,1]].mean() | |
| # Generate movie trajectory | |
| render_poses_path = sorted(glob.glob(os.path.join(basedir, 'camera_path', 'pose', '*txt'))) | |
| render_poses = [] | |
| for path in render_poses_path: | |
| render_poses.append(np.loadtxt(path).reshape(4,4)) | |
| render_poses = np.array(render_poses) | |
| render_K = np.loadtxt(glob.glob(os.path.join(basedir, 'camera_path', 'intrinsics', '*txt'))[0]).reshape(4,4)[:3,:3] | |
| render_poses[:,:,0] *= K[0,0] / render_K[0,0] | |
| render_poses[:,:,1] *= K[1,1] / render_K[1,1] | |
| if rerotate: | |
| poses, render_poses = rerotate_poses(poses, render_poses) | |
| render_poses = torch.Tensor(render_poses) | |
| return imgs, poses, render_poses, [H, W, focal], K, i_split | |