文章目录
- 1. 体渲染公式推导
- 2. 体渲染公式离散化
- 3. 代码解读
1. 体渲染公式推导
如下图所示,渲染图像上点
P
P
P 的颜色值
c
c
c 是累加射线
O
P
→
\overrightarrow{OP}
OP 在近平面和远平面范围内采样的一系列点的颜色值得到的。
具体的计算公式如下:
C
(
r
)
=
∫
t
n
t
f
T
(
t
)
σ
(
r
(
t
)
)
c
(
r
(
t
)
,
d
)
d
t
C(\mathbf{r}) = \int_{t_n}^{t_f} T(t) \sigma(\mathbf{r}(t)) c(\mathbf{r}(t), \mathbf{d}) dt
C(r)=∫tntfT(t)σ(r(t))c(r(t),d)dt其中:
- T ( t ) = exp ( − ∫ t n t σ ( r ( s ) ) d s ) T(t) = \exp ( -\int_{t_n}^t \sigma(\mathbf{r}(s)) ds) T(t)=exp(−∫tntσ(r(s))ds), T ( t ) T(t) T(t) 为累积透射率,表示光线从起点传播到位置 t t t 时未被阻挡的概率
- σ ( x ) \sigma(\mathbf{x}) σ(x) 表示体密度,反映光线在空间位置 x \mathbf{x} x 处被微小粒子阻挡的概率密度
- r ( t ) = o + t d \mathbf{r}(t) = \mathbf{o} + t \mathbf{d} r(t)=o+td, o \mathbf{o} o 为相机位置, d \mathbf{d} d 为射线 O P → \overrightarrow{OP} OP 的方向向量,即用 r ( t ) \mathbf{r}(t) r(t) 表示射线 O P → \overrightarrow{OP} OP
- t n t_n tn 和 t f t_f tf 分别表示近平面和远平面
- C ( r ) C(\mathbf{r}) C(r) 表示射线 O P → \overrightarrow{OP} OP 在渲染图像上点 P P P 的颜色值
现在来推导一下上述的体渲染公式,分为两部分: T ( t ) T(t) T(t) 和 C ( r ) C(\mathbf{r}) C(r)。
1.1. T ( t ) T(t) T(t) 的推导
假设事件
A
A
A 表示光线在区间
[
0
,
t
+
d
t
]
[0, t + dt]
[0,t+dt] 没有被阻挡,事件
B
B
B 表示光线在区间
[
0
,
t
]
[0, t]
[0,t] 没有被阻挡,事件
C
C
C 表示光线在区间
(
t
,
t
+
d
t
]
(t, t + dt]
(t,t+dt] 没有被阻挡,则有
P
(
A
)
=
P
(
B
)
P
(
C
)
P(A) = P(B)P(C)
P(A)=P(B)P(C),其中
P
(
A
)
=
T
(
t
+
d
t
)
P(A)=T(t + dt)
P(A)=T(t+dt),
P
(
B
)
=
T
(
t
)
P(B) = T(t)
P(B)=T(t),
P
(
C
)
=
1
−
σ
(
t
)
d
t
P(C) = 1 - \sigma(t)dt
P(C)=1−σ(t)dt。
值得注意的是,由于
σ
(
t
)
\sigma(t)
σ(t) 表示光线在空间位置
t
t
t 处被微小粒子阻挡的概率密度,由于
d
t
dt
dt 非常小,因此可以将
σ
(
t
)
d
t
\sigma(t)dt
σ(t)dt 近似为光线在空间位置
t
+
d
t
t + dt
t+dt 处被微小粒子阻挡的概率,则光线在空间位置
t
+
d
t
t + dt
t+dt 没有被阻挡的概率为
1
−
σ
(
t
)
d
t
1 - \sigma(t)dt
1−σ(t)dt。
即有:
T
(
t
+
d
t
)
=
T
(
t
)
(
1
−
σ
(
t
)
d
t
)
T(t + dt) = T(t)(1 - \sigma(t)dt)
T(t+dt)=T(t)(1−σ(t)dt)进一步转换可得:
T
(
t
+
d
t
)
−
T
(
t
)
d
t
=
−
T
(
t
)
σ
(
t
)
\dfrac{T(t + dt) - T(t)}{dt} = - T(t)\sigma(t)
dtT(t+dt)−T(t)=−T(t)σ(t)当
d
t
→
0
dt→0
dt→0 的时候,有
T
′
(
t
)
=
T
(
t
+
d
t
)
−
T
(
t
)
d
t
=
d
T
d
t
T'(t) = \dfrac{T(t + dt) - T(t)}{dt}=\dfrac{dT}{dt}
T′(t)=dtT(t+dt)−T(t)=dtdT,因此可得微分方程:
d
T
T
(
t
)
=
−
σ
(
t
)
d
t
\dfrac{dT}{T(t)} = - \sigma(t)dt
T(t)dT=−σ(t)dt现在我们要计算在区间
[
t
n
,
t
]
[t_n, t]
[tn,t] 中光线未被阻挡的概率
T
(
t
n
→
t
)
T(t_n → t)
T(tn→t),有
∫
t
n
t
d
T
T
(
t
)
=
−
∫
t
n
t
σ
(
s
)
d
s
ln
T
(
t
)
∣
t
n
t
=
−
∫
t
n
t
σ
(
s
)
d
s
T
(
t
n
→
t
)
=
T
(
t
)
−
T
(
t
n
)
=
exp
(
−
∫
t
n
t
σ
(
s
)
d
s
)
\begin{align*} \int_{t_n}^{t} \frac{dT}{T(t)} &= -\int_{t_n}^{t} \sigma(s) ds \\ \ln T(t) \bigg|_{t_n}^{t} &= -\int_{t_n}^{t} \sigma(s) ds \\ T(t_n→t) = T(t) - T(t_n) &= \exp(-\int_{t_n}^{t} \sigma(s) ds) \end{align*}
∫tntT(t)dTlnT(t)
tntT(tn→t)=T(t)−T(tn)=−∫tntσ(s)ds=−∫tntσ(s)ds=exp(−∫tntσ(s)ds)
T
(
t
)
T(t)
T(t) 随路径长度增加而指数衰减,表示光线越深入场景,越可能被遮挡(透射率降低)。如果路径上有不透明物体,后续区域的颜色贡献会被完全遮挡(即
T
(
t
)
→
0
T(t) → 0
T(t)→0)。这与物理现象一致:光线被前景物体遮挡后,无法看到背景物体。
1.2. C ( r ) C(r) C(r) 的推导
在 NeRF 的体积渲染模型中,颜色贡献仅来自光子与介质粒子的碰撞(相互作用),即 σ ( r ( t ) ) ≠ 0 \sigma(\mathbf{r}(t)) ≠ 0 σ(r(t))=0。光线从近平面 t n t_n tn 到远平面 t f t_f tf 累积的总颜色为 C ( r ) C(\mathbf{r}) C(r)。在光线路径上,区间 [ t , t + d t ] [t, t + dt] [t,t+dt] 内的颜色贡献 d C dC dC 由以下三部分组成:
- 光线达到 t t t 的概率: T ( t ) T(t) T(t)
- 在 [ t , t + d t ] [t, t + dt] [t,t+dt] 内光线被阻挡(即光子与介质粒子的碰撞)的概率: σ ( r ( t ) ) d t \sigma(\mathbf{r}(t))dt σ(r(t))dt
- 相互作用的颜色贡献: c ( r ( t ) , d ) c(\mathbf{r}(t), \mathbf{d}) c(r(t),d)
则有:
d
C
=
T
(
t
)
⋅
σ
(
r
(
t
)
)
d
t
⋅
c
(
r
(
t
)
,
d
)
dC = T(t) · \sigma(\mathbf{r}(t))dt·c(\mathbf{r}(t), \mathbf{d})
dC=T(t)⋅σ(r(t))dt⋅c(r(t),d)对
d
C
dC
dC 从
t
n
t_n
tn 到
t
f
t_f
tf 进行积分可得:
C
(
r
)
=
∫
t
n
t
f
T
(
t
)
σ
(
r
(
t
)
)
c
(
r
(
t
)
,
d
)
d
t
C(\mathbf{r}) = \int_{t_n}^{t_f} T(t) \sigma(\mathbf{r}(t)) c(\mathbf{r}(t), \mathbf{d}) dt
C(r)=∫tntfT(t)σ(r(t))c(r(t),d)dt如果光线在路径
t
n
→
t
f
t_n → t_f
tn→tf 上未发生任何碰撞(所有
σ
(
r
(
t
)
)
=
0
\sigma(\mathbf{r}(t)) = 0
σ(r(t))=0),则
T
(
t
f
)
=
1
T(t_f) = 1
T(tf)=1,且
C
(
r
)
=
0
C(\mathbf{r}) = 0
C(r)=0。但在实际应用中,NeRF 通常引入背景颜色(例如环境光或者天空)作为默认值,则
C
(
r
)
C(\mathbf{r})
C(r) 的表达式改为:
C
(
r
)
=
∫
t
n
t
f
T
(
t
)
⋅
σ
(
r
(
t
)
)
⋅
c
(
r
(
t
)
,
d
)
d
t
+
T
(
t
f
)
⋅
c
b
a
c
k
g
r
o
u
n
d
C(\mathbf{r}) = \int_{t_n}^{t_f} T(t) \cdot \sigma(\mathbf{r}(t)) \cdot c(\mathbf{r}(t), \mathbf{d}) dt + T(t_f) · \mathbf{c_{background}}
C(r)=∫tntfT(t)⋅σ(r(t))⋅c(r(t),d)dt+T(tf)⋅cbackground这种情况下,即使没有碰撞点,背景颜色仍会作为最终像素值的一部分。
2. 体渲染公式离散化
由于计算机只能处理离散值,因此需要将前面推导的体渲染公式进行离散化。
首先,我们将区间
[
t
n
,
t
f
]
[t_n, t_f]
[tn,tf] 划分成
N
N
N 个等距的小区间,从每一个小区间中随机取样一个点作为采样点,如下所示:
t
i
∼
U
[
t
n
+
i
−
1
N
(
t
f
−
t
n
)
,
t
n
+
i
N
(
t
f
−
t
n
)
]
t_i \sim U\left[ t_n + \frac{i-1}{N}(t_f - t_n), \, t_n + \frac{i}{N}(t_f - t_n) \right]
ti∼U[tn+Ni−1(tf−tn),tn+Ni(tf−tn)]假设采样的
N
N
N 个点分别为
t
1
,
t
2
,
.
.
.
,
t
N
t_1,t_2,...,t_N
t1,t2,...,tN,现在计算两个采样点
t
i
t_i
ti 和
t
i
+
1
t_{i + 1}
ti+1 之间的颜色累积值
C
i
C_i
Ci,则有
C
i
=
∫
t
i
t
i
+
1
T
(
t
i
→
t
)
⋅
σ
(
t
)
⋅
c
(
r
(
t
)
,
d
)
d
t
=
σ
(
t
i
)
⋅
c
(
t
i
)
∫
t
i
t
i
+
1
T
(
t
i
→
t
)
d
t
=
σ
(
t
i
)
⋅
c
(
t
i
)
∫
t
i
t
i
+
1
exp
(
−
∫
t
i
t
σ
(
s
)
d
s
)
d
t
=
σ
(
t
i
)
⋅
c
(
t
i
)
∫
t
i
t
i
+
1
exp
(
−
σ
(
t
i
)
(
t
−
t
i
)
)
d
t
=
σ
(
t
i
)
⋅
c
(
t
i
)
exp
(
−
σ
(
t
i
)
(
t
−
t
i
)
)
−
σ
(
t
i
)
∣
t
i
t
i
+
1
=
c
(
t
i
)
⋅
(
1
−
exp
(
−
σ
(
t
i
)
(
t
i
+
1
−
t
i
)
)
)
\begin{align*} C_{i} &= \int_{t_i}^{t_{i + 1}} T(t_i→t)\cdot\sigma(t)\cdot c(\mathbf{r}(t), \mathbf{d}) dt \\ &=\sigma(t_i) \cdot c(t_i)\int_{t_i}^{t_{i + 1}} T(t_i→t) dt \\ &=\sigma(t_i) \cdot c(t_i)\int_{t_i}^{t_{i + 1}} \exp(-\int_{t_i}^{t}\sigma(s)ds) dt \\ &=\sigma(t_i)\cdot c(t_i)\int_{t_i}^{t_{i + 1}}\exp(-\sigma(t_i)(t - t_i)) dt \\ &=\sigma(t_i) \cdot c(t_i) \left. \frac{\exp{(-\sigma(t_i) (t - t_i))}}{-\sigma(t_i)} \right|_{t_i}^{t_{i + 1}} \\ &=c(t_i) \cdot (1 - \exp(-\sigma(t_i)(t_{i + 1} - t_i))) \end{align*}
Ci=∫titi+1T(ti→t)⋅σ(t)⋅c(r(t),d)dt=σ(ti)⋅c(ti)∫titi+1T(ti→t)dt=σ(ti)⋅c(ti)∫titi+1exp(−∫titσ(s)ds)dt=σ(ti)⋅c(ti)∫titi+1exp(−σ(ti)(t−ti))dt=σ(ti)⋅c(ti)−σ(ti)exp(−σ(ti)(t−ti))
titi+1=c(ti)⋅(1−exp(−σ(ti)(ti+1−ti)))值得注意的是,由于
d
=
t
i
+
1
−
t
i
d = t_{i + 1} - t_i
d=ti+1−ti 的数值很小,因此这里`假设区间
[
t
i
,
t
i
+
1
]
[t_i, t_{i + 1}]
[ti,ti+1] 的体密度为常量
σ
(
t
i
)
\sigma(t_i)
σ(ti),颜色值也为常量
c
(
t
i
)
c(t_i)
c(ti)。
C
(
r
)
=
∑
i
=
1
N
∫
t
i
t
i
+
1
T
(
t
)
⋅
σ
(
t
)
⋅
c
(
r
(
t
)
,
d
)
d
t
=
∑
i
=
1
N
∫
t
i
t
i
+
1
T
(
0
→
t
i
)
⋅
T
(
t
i
→
t
)
⋅
σ
(
t
)
⋅
c
(
r
(
t
)
,
d
)
d
t
=
∑
i
=
1
N
T
(
0
→
t
i
)
∫
t
i
t
i
+
1
T
(
t
i
→
t
)
⋅
σ
(
t
)
⋅
c
(
r
(
t
)
,
d
)
d
t
=
∑
i
=
1
N
T
(
0
→
t
i
)
⋅
c
(
t
i
)
⋅
(
1
−
exp
(
−
σ
(
t
i
)
(
t
i
+
1
−
t
i
)
)
)
\begin{align*} C(\mathbf{r}) &= \sum_{i=1}^{N} \int_{t_i}^{t_{i + 1}} T(t) \cdot \sigma(t) \cdot c(\mathbf{r}(t), \mathbf{d}) dt \\ &= \sum_{i=1}^{N} \int_{t_i}^{t_{i + 1}} T(0 → t_i) \cdot T(t_i → t) \cdot \sigma(t) \cdot c(\mathbf{r}(t), \mathbf{d}) dt \\ &= \sum_{i=1}^{N} T(0 → t_i) \int_{t_i}^{t_{i + 1}} T(t_i → t) \cdot \sigma(t) \cdot c(\mathbf{r}(t), \mathbf{d}) dt \\ &= \sum_{i=1}^{N} T(0 → t_i) \cdot c(t_i) \cdot (1 - \exp(-\sigma(t_i)(t_{i + 1} - t_i))) \end{align*}
C(r)=i=1∑N∫titi+1T(t)⋅σ(t)⋅c(r(t),d)dt=i=1∑N∫titi+1T(0→ti)⋅T(ti→t)⋅σ(t)⋅c(r(t),d)dt=i=1∑NT(0→ti)∫titi+1T(ti→t)⋅σ(t)⋅c(r(t),d)dt=i=1∑NT(0→ti)⋅c(ti)⋅(1−exp(−σ(ti)(ti+1−ti)))不妨设
T
i
=
T
(
0
→
t
i
)
T_i = T(0→t_i)
Ti=T(0→ti),
c
i
=
c
(
t
i
)
c_i = c(t_i)
ci=c(ti),
δ
i
=
t
i
+
1
−
t
i
\delta_i = t_{i + 1}-t_i
δi=ti+1−ti,
σ
i
=
σ
(
t
i
)
\sigma_i = \sigma(t_i)
σi=σ(ti),则上述公式可以简化为:
C
(
r
)
=
∑
i
=
1
N
T
i
⋅
(
1
−
exp
(
−
σ
i
δ
i
)
)
⋅
c
i
C(\mathbf{r}) = \sum_{i=1}^{N} T_i \cdot (1 - \exp(-\sigma_i \delta_i)) \cdot c_i
C(r)=i=1∑NTi⋅(1−exp(−σiδi))⋅ci 对
T
(
t
)
T(t)
T(t) 也进行离散化,根据上述公式,我们需要知道
T
(
t
i
)
T(t_i)
T(ti) 的离散化公式,如下:
T
i
=
T
(
t
i
)
=
T
(
0
→
t
i
)
=
exp
(
−
∫
0
t
i
σ
(
t
)
d
t
)
=
exp
(
∑
j
=
1
i
−
1
−
σ
j
δ
j
)
T_i = T(t_i) = T(0 \to t_i) = \exp \left( -\int_0^{t_i} \sigma(t) \, dt \right) = \exp \left( \sum_{j=1}^{i - 1} -\sigma_j \delta_j \right)
Ti=T(ti)=T(0→ti)=exp(−∫0tiσ(t)dt)=exp(j=1∑i−1−σjδj)注意这里的
j
j
j 只取值到
i
−
1
i - 1
i−1。
我们可以对体渲染公式做进一步简化,令
α
i
=
1
−
exp
(
−
σ
i
δ
i
)
\alpha_i = 1 - \exp(-\sigma_i \delta_i)
αi=1−exp(−σiδi),则有:
T
i
=
exp
(
∑
j
=
1
i
−
1
−
σ
j
δ
j
)
=
∏
j
=
1
i
−
1
exp
(
−
σ
j
δ
j
)
=
∏
j
=
1
i
−
1
(
1
−
α
j
)
=
(
1
−
α
1
)
(
1
−
α
2
)
⋅
⋅
⋅
(
1
−
α
i
−
1
)
T_i = \exp \left( \sum_{j=1}^{i - 1} -\sigma_j \delta_j \right) = \prod\limits_{j = 1}^{i - 1}\exp(-\sigma_j \delta_j) = \prod\limits_{j = 1}^{i - 1}(1 - \alpha_j) = (1-\alpha_1)(1-\alpha_2)···(1-\alpha_{i - 1})
Ti=exp(j=1∑i−1−σjδj)=j=1∏i−1exp(−σjδj)=j=1∏i−1(1−αj)=(1−α1)(1−α2)⋅⋅⋅(1−αi−1)
C
(
r
)
=
∑
i
=
1
N
(
1
−
α
1
)
(
1
−
α
2
)
⋅
⋅
⋅
(
1
−
α
i
−
1
)
α
i
⋅
c
i
=
∑
i
=
1
N
c
i
α
i
∏
j
=
1
i
−
1
(
1
−
α
j
)
C(\mathbf{r}) = \sum_{i=1}^{N} (1-\alpha_1)(1-\alpha_2)···(1-\alpha_{i - 1})\alpha_i \cdot c_i = \sum_{i=1}^{N} c_i \alpha_i \prod_{j=1}^{i-1} (1 - \alpha_j)
C(r)=i=1∑N(1−α1)(1−α2)⋅⋅⋅(1−αi−1)αi⋅ci=i=1∑Nciαij=1∏i−1(1−αj)令
w
i
=
α
i
∏
j
=
1
i
−
1
(
1
−
α
j
)
w_i = \alpha_i \prod_{j=1}^{i-1} (1 - \alpha_j)
wi=αi∏j=1i−1(1−αj),则
w
i
w_i
wi 可以看做是采样点
i
i
i 对最终颜色的贡献权重。
3DGS 中论文给出的渲染公式如下:
C
=
∑
i
∈
N
c
i
α
i
∏
j
=
1
i
−
1
(
1
−
α
j
)
C = \sum_{i \in N} c_i \alpha_i \prod_{j=1}^{i-1} (1 - \alpha_j)
C=i∈N∑ciαij=1∏i−1(1−αj)可以看出两者具有一样的数学表达式。
3. 代码解读
raw2outputs 函数实现了体渲染的计算。
1)计算采样点之间的间距
δ
i
=
t
i
+
1
−
t
i
\delta_i = t_{i + 1} - t_{i}
δi=ti+1−ti
dists = z_vals[..., 1:] - z_vals[..., :-1]
dists = torch.cat([dists, torch.Tensor([1e10]).expand(dists[..., :1].shape)], -1) # [N_rays, N_samples]
dists = dists * torch.norm(rays_d[..., None, :], dim=-1)
2)将模型预测的原始颜色值(raw[…, :3])通过 s i g m o i d sigmoid sigmoid 映射到 [ 0 , 1 ] [0,1] [0,1] 范围
rgb = torch.sigmoid(raw[..., :3]) # [N_rays, N_samples, 3]
3)在训练时向体积密度 σ \sigma σ 加噪声,防止过拟合
noise = 0.
if raw_noise_std > 0.:
noise = torch.randn(raw[..., 3].shape) * raw_noise_std
4)计算 α i = 1 − exp ( − σ i δ i ) \alpha_i = 1 - \exp(-\sigma_i\delta_i) αi=1−exp(−σiδi)
raw2alpha = lambda raw, dists, act_fn=F.relu: 1. - torch.exp(-act_fn(raw) * dists)
alpha = raw2alpha(raw[..., 3] + noise, dists) # [N_rays, N_samples]
5)计算每一条射线上的所有采样点的权重 w e i g h t s [ i ] weights[i] weights[i],并且 w e i g h t s [ i ] = α i ∏ j = 1 i − 1 ( 1 − α j ) weights[i] = \alpha_i \prod_{j=1}^{i-1} (1 - \alpha_j) weights[i]=αi∏j=1i−1(1−αj)
weights = alpha * torch.cumprod(torch.cat([torch.ones((alpha.shape[0], 1)), 1. - alpha + 1e-10], -1), -1)[:, :-1]
rgb_map = torch.sum(weights[..., None] * rgb, -2) # [N_rays, 3]
现在简单模拟一下这个过程的计算:
alpha = [
[0.1, 0.2],
[0.3, 0.4]
]
1 - alpha = [
[0.9, 0.8],
[0.7, 0.6]
]
torch.cat([torch.ones((alpha.shape[0], 1)), 1. - alpha + 1e-10], -1) 的输出为:
[
[1, 0.9, 0.8],
[1, 0.7, 0.6]
]
torch.cumprod(torch.cat([torch.ones((alpha.shape[0], 1)), 1. - alpha + 1e-10], -1), -1) 的输出为:
[
[1, 1*0.9, 1*0.9*0.8],
[1, 1*0.7, 1*0.7*0.6]
]
torch.cumprod(torch.cat([torch.ones((alpha.shape[0], 1)), 1. - alpha + 1e-10], -1), -1)[:, :-1] 的输出为:
[
[1, 0.9],
[1, 0.7]
]
alpha * torch.cumprod(torch.cat([torch.ones((alpha.shape[0], 1)), 1. - alpha + 1e-10], -1), -1)[:, :-1] 的输出为:
[[0.1*1, 0.2*0.9] → [0.1, 0.18],
[0.3*1, 0.4*0.7] → [0.3, 0.28]]
6)计算深度图
depth_map = torch.sum(weights * z_vals, -1)
disp_map = 1. / torch.max(1e-10 * torch.ones_like(depth_map), depth_map / torch.sum(weights, -1))
在 NeRF 中通过加权平均所有采样点的深度,得到每条射线的有效深度。有效深度可以看作是光线穿过场景时,最可能与物体表面相交的深度。有效深度的计算公式如下:
z
ˉ
=
∑
i
=
1
N
w
i
⋅
z
i
\bar{z} = \sum_{i=1}^{N} w_i \cdot z_i
zˉ=i=1∑Nwi⋅zi假设一条光线穿过一个简单的场景(如一个立方体):
采样点分布如下:
- 采样点 1:位于立方体的前方, σ 1 \sigma_1 σ1 很小, w 1 w_1 w1 接近于 0
- 采样点 2:位于立方体的内部, σ 2 \sigma_2 σ2 很大, w 2 w_2 w2 显著增大
- 采样点 3:位于立方体的后方, σ 3 \sigma_3 σ3 很小, w 3 w_3 w3 接近于 0
则该光线的有效深度为 z ˉ ≈ w 1 t 1 + w 2 t 2 + w 3 t 3 ≈ w 2 t 2 \bar{z} ≈ w_1t_1 + w_2t_2 + w_3t_3 ≈ w_2t_2 zˉ≈w1t1+w2t2+w3t3≈w2t2,即有效深度集中在立方体内部的采样点,符合直觉。
7)计算视差图
在 NeRF 中通过深度倒数计算视差,并添加极小值 1e-10 防止除零,计算公式如下:
disp
=
1
max
(
ϵ
,
z
ˉ
n
o
r
m
)
\text{disp} = \frac{1}{\max(\epsilon, \bar{z}_{norm})}
disp=max(ϵ,zˉnorm)1其中,
z
ˉ
n
o
r
m
=
z
ˉ
∑
i
=
1
N
w
i
\bar{z}_{norm} = \dfrac{\bar{z}}{\sum_{i=1}^{N} w_i}
zˉnorm=∑i=1Nwizˉ。
双目相机中视差
d
d
d 和 深度
D
D
D 的关系如下:
d
=
B
f
Z
d = \dfrac{Bf}{Z}
d=ZBf其中:
- B B B:双目相机的基线长度(两相机中心的水平距离)
- f f f:相机焦距
- Z Z Z:场景点的深度
- d d d:视差(同一场景点在左右图像中的像素偏差)
d
=
B
f
Z
d = \dfrac{Bf}{Z}
d=ZBf 计算的是绝对深度(实际物理距离),
B
B
B 和
f
f
f 两个参数都需要人为标定。
而 NeRF 中计算视差的公式为
d
=
1
Z
d=\dfrac{1}{Z}
d=Z1,这计算的是相对深度。相对深度描述的是场景中物体之间的相对远近关系,但不提供物体到相机或传感器的实际物理距离。
相对深度图缺乏真实尺度,但可以通过已知的基准点(如标定板)计算比例因子
α
\alpha
α,将相对深度映射到绝对深度,数学公式如下:
绝对深度
=
α
×
相对深度
绝对深度 = \alpha × 相对深度
绝对深度=α×相对深度