Kunhao-Liu / StyleRF

[CVPR 2023] StyleRF: Zero-shot 3D Style Transfer of Neural Radiance Fields
https://kunhao-liu.github.io/StyleRF/
144 stars 11 forks source link

Changing the camera render path #20

Open jly0810 opened 1 year ago

jly0810 commented 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):

定义offsets

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

其他地方与原代码相同。非常希望可以得到您的答复和帮助!