Skip to content

Latest commit

 

History

History
119 lines (102 loc) · 5.02 KB

03.光线的数学表示与光线采样.md

File metadata and controls

119 lines (102 loc) · 5.02 KB

颠覆传统三维重建方法之nerf(三)---光线的数学表示与光线采样

nerf说:一条光线上所有位置上的颜色和密度的合成,就是成像图上的像素RGB值; 我们来看看这条光线怎么表示? 以及怎么在光线上取一些点?

一. nerf的光线表示

光线是一条空间直线,准确的说是一条空间射线,定义公式如下:

  • 起点坐标 o:相机中心点。
  • 方向向量 d:从相机中心点出发,到图像某个像素坐标的向量,由两点坐标相减就得到。
  • t:光线上的点到起点的水平距离。 t取不同的值就是光线上不同的采样点。

如下图:

  • 400x400的图像可以生成160000条光线。

二. 复习向量与空间解析几何的空间直线的表示

P是空间直线上一点,S是方向向量,有如图的三种表示法

三. nerf光线公式的推导

进一步证明:因为Nerf的t取得是z轴距离,而不是光线的距离;而且只有中心光线方向是单位向量。

四. 光线采样

  • t=|z|:光线上的点到起点(相机中心)的距离。 t取不同的值就是光线上不同的采样点。nerf默认取61个点,60段。
  • r(t):光线上点的三维坐标xyz;
  • d:光线方向向量,也是三个值;中心光线向量是单位向量。

五. 应用与分析

  1. 先看代码
    #计算光线的起点和方向向量
    def get_rays(H, W, K, c2w):
        i, j = torch.meshgrid(torch.linspace(0, W-1, W), torch.linspace(0, H-1, H))
        i = i.t()
        j = j.t()
        dirs = torch.stack([(i-K[0][2])/K[0][0], -(j-K[1][2])/K[1][1], -torch.ones_like(i)], -1)
        rays_d = torch.sum(dirs[..., np.newaxis, :] * c2w[:3,:3], -1) 
        rays_o = c2w[:3,-1].expand(rays_d.shape)
        return rays_o, rays_d
    
     #计算光线采样
     z_vals = tf.linspace(near, far, N_samples) 
     pts = rays_o[...,None,:] + rays_d[...,None,:] * z_vals[...,:,None]
    
  2. 代码阅读
    • dirs是相机坐标系下的光线方向。
    • rays_d是世界坐标系下的光线方向,为什么用点乘+求和:因为输入是行向量(python没有一维列向量)不能直接像列向量那样用矩阵乘法。
    • rays_o是世界坐标系下的光线起点。
  3. 代码分析:
    • c2w:相机坐标系到世界坐标系的转换:只包含旋转和位移。
    • 证明表示,中心光线方向向量d需要是单位向量,而且nerf使用的是右手三维坐标系,所以nerf取-1代码如下: -torch.ones_like(i)
    • 方向是向量:整体位移方向还是不变,所以只需要旋转, 所以只需乘旋转矩阵R=c2w[:3,:3]。
    • 光心是原点:(0,0,0)怎么旋转都在原地,所以只需要位移, 所以只需乘位移矩阵T=c2w[:3,-1]。