Open jly0810 opened 1 year ago
您好,冒昧再次来访,我目前在做相同领域的工作,但我遇到了一些问题,很久没有解决,应该是坐标系变换方面的问题,希望从您这儿来寻求一些帮助。对于llff数据集,render path=1时,会进行螺旋式的拍摄,我想修改这一部分,使相机以中心相机为中点按一定的间隔水平排列,并修改光线的方向(使变换后的相机光线方向向量=相机原光线方向向量+相机相较于中心相机的偏移量),最终目的是实现相机的离轴拍摄效果。 我想问下您这块代码该如何实现。 以下是我的实现思路: 1、将llff.py的get_spiral()替换为如下的leval函数:目的是构造水平排列的60个相机的c2ws矩阵: def _trans_t(x, t): return np.array( [ [1, 0, 0, x], [0, 1, 0, 0], [0, 0, 1, t], [0, 0, 0, 1], ], dtype=np.float32, )
def _rot_phi(phi): return np.array( [ [1, 0, 0, 0], [0, np.cos(phi), -np.sin(phi), 0], [0, np.sin(phi), np.cos(phi), 0], [0, 0, 0, 1], ], dtype=np.float32, )
def _rot_theta(th): return np.array( [ [np.cos(th), 0, -np.sin(th), 0], [0, 1, 0, 0], [np.sin(th), 0, np.cos(th), 0], [0, 0, 0, 1], ], dtype=np.float32, ) def pose_spherical(offsetx : float, theta : float, phi : float, radius : float, vec_up : Optional[np.ndarray]=None): """ Generate spherical rendering poses, from NeRF. Forgive the code horror :return: r (3,), t (3,) """ c2w = _trans_t(offsetx, radius) c2w = _rot_phi(phi / 180.0 np.pi) @ c2w c2w = _rot_theta(theta / 180.0 np.pi) @ c2w c2w = ( np.array( [[-1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=np.float32, ) @ c2w ) if vec_up is not None: vec_up = vec_up / np.linalg.norm(vec_up) vec_1 = np.array([vec_up[0], -vec_up[2], vec_up[1]]) vec_2 = np.cross(vec_up, vec_1)
trans = np.eye(4, 4, dtype=np.float32) trans[:3, 0] = vec_1 trans[:3, 1] = vec_2 trans[:3, 2] = vec_up c2w = trans @ c2w c2w = c2w @ np.diag(np.array([1, -1, -1, 1], dtype=np.float32)) return c2w
def leval(c2ws_all):
offsetxs = [] num_views=60 # 路径上渲染的视点数 for i in range(0, num_views): offsetxs.append((i - num_views//2) * 0.03) # 相机偏移量 offsetxs = np.array(offsetxs) angles = np.linspace(-180, 180, num_views + 1)[:-1] # 定义vec_up up_rot = c2ws_all[:, :3, :3] ups = np.matmul(up_rot, np.array([0, -1.0, 0])[None, :, None])[..., 0] vec_up = np.mean(ups, axis=0) vec_up /= np.linalg.norm(vec_up) c2ws = [ pose_spherical( offsetx, 90, 0, 1, vec_up=vec_up, ) for angle, offsetx in zip(angles, offsetxs) ] return np.stack(c2ws, axis=0)
2、修改evaluation_feature_path()函数: 首先定义一个中心相机,使其为 center = c2ws[60//2] center = torch.FloatTensor(center) 然后修改rays_o, rays_d = get_rays(test_dataset.directions, c2w, center)的get_rays函数: 目的是模拟离轴变换 def get_rays(directions, c2w, center_c2w): rays_d = directions @ c2w[:3, :3].T # (H, W, 3) rays_o = c2w[:3, 3].expand(rays_d.shape) # (H, W, 3) center_rays_o = center_c2w[:3, 3].expand(rays_d.shape) # (H, W, 3)
tt = center_rays_o - rays_o # 当前相机指向中心相机间的偏移向量 rays_d = rays_d + tt # 当前相机的原始方向+偏移向量=当前相机模拟离轴变换之后的光线方向 rays_d = rays_d.view(-1, 3) rays_o = rays_o.view(-1, 3) return rays_o, rays_d
其他地方与原代码相同。非常希望可以得到您的答复和帮助!
您好,冒昧再次来访,我目前在做相同领域的工作,但我遇到了一些问题,很久没有解决,应该是坐标系变换方面的问题,希望从您这儿来寻求一些帮助。对于llff数据集,render path=1时,会进行螺旋式的拍摄,我想修改这一部分,使相机以中心相机为中点按一定的间隔水平排列,并修改光线的方向(使变换后的相机光线方向向量=相机原光线方向向量+相机相较于中心相机的偏移量),最终目的是实现相机的离轴拍摄效果。 我想问下您这块代码该如何实现。 以下是我的实现思路: 1、将llff.py的get_spiral()替换为如下的leval函数:目的是构造水平排列的60个相机的c2ws矩阵: def _trans_t(x, t): return np.array( [ [1, 0, 0, x], [0, 1, 0, 0], [0, 0, 1, t], [0, 0, 0, 1], ], dtype=np.float32, )
def _rot_phi(phi): return np.array( [ [1, 0, 0, 0], [0, np.cos(phi), -np.sin(phi), 0], [0, np.sin(phi), np.cos(phi), 0], [0, 0, 0, 1], ], dtype=np.float32, )
def _rot_theta(th): return np.array( [ [np.cos(th), 0, -np.sin(th), 0], [0, 1, 0, 0], [np.sin(th), 0, np.cos(th), 0], [0, 0, 0, 1], ], dtype=np.float32, ) def pose_spherical(offsetx : float, theta : float, phi : float, radius : float, vec_up : Optional[np.ndarray]=None): """ Generate spherical rendering poses, from NeRF. Forgive the code horror :return: r (3,), t (3,) """ c2w = _trans_t(offsetx, radius) c2w = _rot_phi(phi / 180.0 np.pi) @ c2w c2w = _rot_theta(theta / 180.0 np.pi) @ c2w c2w = ( np.array( [[-1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=np.float32, ) @ c2w ) if vec_up is not None: vec_up = vec_up / np.linalg.norm(vec_up) vec_1 = np.array([vec_up[0], -vec_up[2], vec_up[1]]) vec_2 = np.cross(vec_up, vec_1)
def leval(c2ws_all):
定义offsets
2、修改evaluation_feature_path()函数: 首先定义一个中心相机,使其为 center = c2ws[60//2] center = torch.FloatTensor(center) 然后修改rays_o, rays_d = get_rays(test_dataset.directions, c2w, center)的get_rays函数: 目的是模拟离轴变换 def get_rays(directions, c2w, center_c2w): rays_d = directions @ c2w[:3, :3].T # (H, W, 3) rays_o = c2w[:3, 3].expand(rays_d.shape) # (H, W, 3) center_rays_o = center_c2w[:3, 3].expand(rays_d.shape) # (H, W, 3)
其他地方与原代码相同。非常希望可以得到您的答复和帮助!