相关文章:
原理挺简单的,但是这文章有点难啃,好多东西该讲没讲,该描述没描述。
在前面的步骤中,得到了匹配图像对 C \mathcal{C} C,这些图像对又被称为场景图(scene graph)
。为了提高 初始化 和 三角测量 模块的鲁棒性,故在此提出了一个多模型几何验证策略。
步骤如下:
general
场景下移动的(而不是纯旋转 or 平面场景);panoramic
)和平面场景planar
(问题是,这里写的第三步不就是用来干这个的?二次筛选?);general, panoramic, planar
标记场景图的模型类别,并使用 N H N_H NH、 N E N_E NE、 N F N_F NF 中最大的那个作为模型内点;一个错误的视图选取可能会导致一连串的相机误匹配和错误的三角测量;而且,对下一最佳视图选择会极大地影响姿势估计的质量以及三角测量的完整性和准确性。因此,准确的姿态估计对于稳健的 SfM 至关重要,因为如果姿态不准确,点的三角测量可能会失败。
一种流行的方法是,找到一张能观察到最多已经三角化过的点的图像。但有实验表面,使用 PnP 的相机姿势的准确性取决于 观测点的数量 及 其在图像中的分布。因此,作者提出一种使用多尺度格网来度量匹配点分布状况的方法:
如上图所示,作者将图像划分成不同尺度格网,然后对不同尺度的格网点分布状况进行打分,这样可以同时考虑到点的数量与分布的影响。总的来说,点的数量越多,分布越均匀,则该图像的得分越高。上图中纵向是点分布的差异与得分差异的对比,横向是点数量与得分的对比。分数的计算方式如下所示:
S c o r e 左上 = 1 × 2 + 4 × 4 + 6 × 8 = 66 S c o r e 右上 = 1 × 2 + 4 × 4 + 16 × 8 = 146 S c o r e 左下 = 4 × 2 + 6 × 4 + 6 × 8 = 80 S c o r e 右下 = 4 × 2 + 16 × 4 + 16 × 8 = 200 \begin{aligned} Score_{\text{左上}} &= 1\times2+4\times4+6\times8=66\\ Score_{\text{右上}} &= 1\times2+4\times4+16\times8=146\\ Score_{\text{左下}} &= 4\times2+6\times4+6\times8=80\\ Score_{\text{右下}} &= 4\times2+16\times4+16\times8=200\\ \end{aligned} Score左上Score右上Score左下Score右下=1×2+4×4+6×8=66=1×2+4×4+16×8=146=4×2+6×4+6×8=80=4×2+16×4+16×8=200可见在同样点数量下,点分布越均匀得分越高。对不同匹配图像进行打分后,选择得分最高的图像作为下一最佳匹配图像。实验表明,使用该策略可以提升重建的鲁棒性和精度。
为了处理任意级别的异常值污染,作者使用 RANSAC 提出了一种高效的、基于采样和多视图的三角化方法。
考虑特征轨迹 T = { T n ∣ n = 1 ⋯ N T } \mathcal{T}=\{T_n | n=1 \cdots N_T\} T={Tn∣n=1⋯NT} 为一组具有未知先验内点比率 ϵ \epsilon ϵ 的测量值。测量 T n T_n Tn 由归一化图像观测 x ˉ n ∈ R 2 \bar{\mathbf{x}}_n\in \mathbb{R}^2 xˉn∈R2 和 对应的相机位姿 P n ∈ S E ( 3 ) \mathbf{P}_n\in \mathbf{SE}(3) Pn∈SE(3) 组成,其定义了从世界到相机坐标系的映射。目标是最大限度地支持符合条件良好的双视图三角测量的测量:
X a b ∼ τ ( x ˉ a , x ˉ b , P a , P b ) with a ≠ b , \mathbf{X}_{ab}\sim\tau\left(\bar{\mathbf{x}}_a,\bar{\mathbf{x}}_b,\mathbf{P}_a,\mathbf{P}_b\right){ } \text{ with } a\neq b, Xab∼τ(xˉa,xˉb,Pa,Pb) with a=b,其中 τ \tau τ 指代任意一种三角化的方式,COLMAP 里用的是 DLT(Direct Linear Transform,直接线性变换)
; X a b \mathbf{X}_{ab} Xab 是被三角化的点。在上一节讲过,COLMAP 不会从全景图像进行三角测量,以避免由于不准确的姿态估计而导致错误的三角测量角度。
条件良好的模型满足两个约束:
一个足够大的三角化角度 α \alpha α:
cos α = t a − X a b ∥ t a − X a b ∥ 2 ⋅ t b − X a b ∥ t b − X a b ∥ 2 . \cos\alpha=\frac{\mathbf{t}_a-\mathbf{X}_{ab}}{\left\|\mathbf{t}_a-\mathbf{X}_{ab}\right\|_2}\cdot\frac{\mathbf{t}_b-\mathbf{X}_{ab}}{\left\|\mathbf{t}_b-\mathbf{X}_{ab}\right\|_2}. cosα=∥ta−Xab∥2ta−Xab⋅∥tb−Xab∥2tb−Xab.
三角化生成的三维点投影回图像上的深度值应该为正:
d = [ p 31 p 32 p 33 p 34 ] [ X a b T 1 ] T d=\begin{bmatrix}p_{31}&p_{32}&p_{33}&p_{34}\end{bmatrix}\begin{bmatrix}\mathbf{X}_{ab}^T&1\end{bmatrix}^T d=[p31p32p33p34][XabT1]T其中 p m m p_{mm} pmm 代表 P \mathbf{P} P 的第 m m m 行第 n n n 列元素。如果测量 T n T_n Tn 有正深度 d n d_n dn 且其重投影误差:
e n = ∥ x ˉ n − [ x ′ / z ′ y ′ / z ′ ] ∥ 2 with [ x ′ y ′ z ′ ] = P n [ X a b 1 ] \left.e_n=\left\|\bar{\mathbf{x}}_n-\begin{bmatrix}x'/z'\\y'/z'\end{bmatrix}\right.\right\|_2\text{with}\begin{bmatrix}x'\\y'\\z'\end{bmatrix}=\mathbf{P}_n\begin{bmatrix}\mathbf{X}_{ab}\\1\end{bmatrix} en= xˉn−[x′/z′y′/z′] 2with x′y′z′ =Pn[Xab1]小于某个阈值 t t t。
值得注意的是,三角化的过程中使用了RANSAC,即从上述特征追踪中随机选择至少两个点进行三角化,统计内点数(即,重投影误差小于阈值记为内点),选择内点数最多的那个作为三角化点。这个过程中存在一个问题就是,假如该点被追踪到了比较少的次数,此时随机采样会重复选择相同的一对点进行三角化,这样会造成不必要的资源消耗。为了不重复采点,本文使用了可产生不重复随机组的 random sampler 的方式;另外,为了能够保证以置信度为 η \eta η 的概率至少选择一对无外点的最小解集,该过程至少重复进行 K K K 次。(这里可以参考其他文献:假设内点所占总数据比率为 ϵ \epsilon ϵ,至少迭代多少次得到最佳:RANSAC基本原理)还好这一块还有点印象,论文内这一块没讲清楚,也没见其他人提到的,离谱。
为了减少累积误差,在图像配准和三角化后执行 BA。通常不需要在每个步骤之后执行全局 BA,因为增量 SfM 只会影响局部模型。因此,COLMAP 在每次图像配准后对连接最多的图像集执行局部 BA,仅在模型增长一定百分比后才执行全局 BA,以分摊时间消耗。
BA 是 SfM 的主要性能瓶颈,文中利用增量 SfM 和密集照片集合的固有特性,通过将冗余相机聚类为高场景重叠组来更有效地参数化 BA。
COLMAP 将摄像机和点划分为通过分隔变量连接的子图,具体操作如下:
图像与地图点根据重建过程中是否受到最新帧点影响分为两类。对于比较大的重建问题,大部分场景不受影响,因为模型通常在局部扩展。也就是说,最新的重建帧仅会影响其邻近的图像以及地图点,很大一部分图像/地图点并不会发生改变。文内将不受影响的那部分场景划分为一个个高度重叠图像的组 G = { G r ∣ r = 1 … N G } \mathcal{G}=\left\{G_r \mid r=1 \ldots N_G\right\} G={Gr∣r=1…NG},并参数化每个组 G r G_r Gr 为单个相机(即,将每组相机使用一个(自由)相机来代替,这样可以减少 BA 优化过程中自由参数的数量,也就降低了计算量)。受最新扩展影响的图像被独立分组,以允许对其参数进行最佳改进。
那么问题来了,什么才叫做高重合度呢? 作者提到,一个组内相机的共视区域必须高度重合。令场景中共有 N X N_X NX 个点, 那么每一张图像都可表示成一个二值向量 v i ∈ { 0 , 1 } N X \mathbf{v}_i \in\{0,1\}^{N_X} vi∈{0,1}NX,其中当某个地图点被观测到时为 1,否则为 0;有了以上定义之后,我们可以定义图像 a a a 与图像 b b b 之间的重合度 V a b V_{a b} Vab 为:
V a b = ∥ v a ∧ v b ∥ / ∥ v a ∨ v b ∥ V_{a b}=\left\|\mathbf{v}_a \wedge \mathbf{v}_b\right\| /\left\|\mathbf{v}_a \vee \mathbf{v}_b\right\| Vab=∥va∧vb∥/∥va∨vb∥接着对待处理帧的 K r K_r Kr 个空间最近邻的那些图像计算重合度得分并排序,若共视程度大于阈值且组内图像数量小于阈值,则将该图像加入该组,这样可以构造一组高重合度的相机集合。对于这一个相机组的 BA(Group BA) 损失被构造为如下形式:
E g = ∑ j ρ j ( ∥ π g ( G r , P c , X k ) − x j ∥ 2 2 ) E_g=\sum_j \rho_j\left(\left\|\pi_g\left(\mathbf{G}_r, \mathbf{P}_c, \mathbf{X}_k\right)-\mathbf{x}_j\right\|_2^2\right) Eg=j∑ρj(∥πg(Gr,Pc,Xk)−xj∥22)
上式中 G r ∈ S E ( 3 ) \mathbf{G}_r \in \mathbf{S E}(3) Gr∈SE(3) 表示该组共用的外参, P c \mathbf{P}_c Pc 表示组内每张图像的位姿。在进行优化的时候,组内每张图像的位姿为 P c r = P c G r \mathbf{P}_{cr}=\mathbf{P}_c\mathbf{G}_r Pcr=PcGr,其中 P c \mathbf{P}_c Pc 在优化过程中固定不变, G r \mathbf{G}_r Gr 可变。全局的损失函数 E ˉ \bar{E} Eˉ 是所有分组代价 和 非分组代价之和。如此,BA 优化的时候,自由变量的数量就大大减少了,BA 优化的效率得到了大幅度提升。
编译流程参考 COLMAP Installation
cd build
./src/colmap/exe/colmap gui