1. 前言

论文地址
代码地址

在这里插入图片描述

  detect-then-describe:对应 sparse local features,首先通过检测器得到特征点,然后提取特征点周围的 patch 得到描述符。
  缺点:差异大的图像对效果不好(昼夜、季节、弱纹理场景)
  原因:描述符由较大的区域得到,而特征点由很小区域的低级信息得到(角点等),导致检测的结果不稳定。

  作者表示,即使对应的特征点检测不到,但是描述符仍然可以成功匹配,所以放弃检测阶段,而是密集提取描述符,代价是匹配时间和内存消耗。

  detect-and-describe:本文的方法,通过 CNN 得到特征图,然后同时计算描述符并检测特征点。检测的特征点应当是在局部有不同的描述符的像素,这样会更适合匹配。
  缺点:(1)由于密集提取描述符,效率低,计算量大;(2)检测基于高级信息虽然鲁棒性好但是准确度低,但是也足够用于视觉定位和 SfM

2. 方法

在这里插入图片描述

2.1 特征提取

  首先是常规的用 CNN 提取图像 I I I 的特征 F = F ( I ) , F ∈ R h × w × n F = \mathcal{F} (I), F\in\mathbb{R} ^{h\times w\times n} F=F(I),FRh×w×n,论文中给了特征两种写法:
(1) d i j = F i j : ,   d ∈ R n \mathbf{d}_{i j}=F_{i j:},\ \mathbf{d} \in \mathbb{R}^{n} dij=Fij:, dRn 某个像素 i j ij ij 的特征向量
(2) D k = F : : k ,   D k ∈ R h × w D^{k}=F_{:: k},\ D^{k} \in \mathbb{R}^{h \times w} Dk=F::k, DkRh×w 某个维度 k k k 的特征图
  这里将特征提取函数 F \mathcal{F} F 理解为 n n n 个不同的特征检测函数 D k \mathcal{D}^k Dk,每个检测函数输出一个二维特征图 D k D^{k} Dk

2.2 特征点检测

  定义特征点 ( i , j ) (i,j) (i,j)
( i , j )  is a detection ⟺ D i j k  is a local max. in  D k with  k = arg ⁡ max ⁡ t D i j t \begin{array}{ll} (i, j) \text{ is a detection} \Longleftrightarrow & D_{i j}^{k} \text{ is a local max. in } D^{k} \\ &\text {with } k=\underset{t}{\arg \max } D_{i j}^{t} \end{array} (i,j) is a detectionDijk is a local max. in Dkwith k=targmaxDijt

即两个条件,像素点 ( i , j ) (i,j) (i,j) 的特征向量中最大值索引为 k k k,且这个最大特征值在 D k D^{k} Dk 的局部区域也是最大值。
  为了在训练过程中便于反向传播,定义局部最大值得分,其中 N ( i , j ) \mathcal{N}(i, j) N(i,j) 是以 ( i , j ) (i,j) (i,j) 为中心的 3 × 3 3\times3 3×3 区域:
α i j k = exp ⁡ ( D i j k ) ∑ ( i ′ , j ′ ) ∈ N ( i , j ) exp ⁡ ( D i ′ j ′ k ) \alpha_{i j}^{k}=\frac{\exp \left(D_{i j}^{k}\right)}{\sum_{\left(i^{\prime}, j^{\prime}\right) \in \mathcal{N}(i, j)} \exp \left(D_{i^{\prime} j^{\prime}}^{k}\right)} αijk=(i,j)N(i,j)exp(Dijk)exp(Dijk)

通道选择得分:
β i j k = D i j k / max ⁡ t D i j t \beta_{i j}^{k}=D_{i j}^{k} / \max _{t} D_{i j}^{t} βijk=Dijk/tmaxDijt

  Next, in order to take both criteria into account, we maximize the product of both scores across all feature maps k k k to obtain a single score map:
  同时考虑两个得分标准,在所有特征图上最大化两个得分的乘积,得到一个一维的特征图(2021.12.9 可能是翻译的不对,后来看这句话有点迷惑,个人理解就是每个像素有个特征向量,特征向量的每个通道对应上面的操作计算出各自的得分;得分最高的作为整个特征向量也就是这个像素的得分,从而构成得分图):
γ i j = max ⁡ k ( α i j k β i j k ) \gamma_{i j}=\max _{k}\left(\alpha_{i j}^{k} \beta_{i j}^{k}\right) γij=kmax(αijkβijk)

  最后通过归一化得到每个像素的检测得分:
s i j = γ i j / ∑ ( i ′ , j ′ ) γ i ′ j ′ s_{i j}=\gamma_{i j} / \sum_{\left(i^{\prime}, j^{\prime}\right)} \gamma_{i^{\prime} j^{\prime}} sij=γij/(i,j)γij

2.3 损失函数

  给定一对图像 ( I 1 , I 2 ) (I_1,I_2) (I1,I2) 和它们的匹配关系 c : A ↔ B c:A\leftrightarrow B c:AB,损失函数的目的是最小化相匹配的描述符 d ^ A ( 1 ) \hat{\mathbf{d}}_{A}^{(1)} d^A(1) d ^ B ( 2 ) \hat{\mathbf{d}}_{B}^{(2)} d^B(2) 的距离 p ( c ) p(c) p(c),同时最大化与其不匹配的描述符 d ^ N 1 ( 1 ) \hat{\mathbf{d}}_{N_1}^{(1)} d^N1(1) d ^ N 2 ( 2 ) \hat{\mathbf{d}}_{N_2}^{(2)} d^N2(2) 的距离 n ( c ) n(c) n(c)。整个损失是在 triplet margin ranking loss 的基础上修改的。

p ( c ) = ∥ d ^ A ( 1 ) − d ^ B ( 2 ) ∥ 2   n ( c ) = min ⁡ ( ∥ d ^ A ( 1 ) − d ^ N 2 ( 2 ) ∥ 2 , ∥ d ^ N 1 ( 1 ) − d ^ B ( 2 ) ∥ 2 ) p(c)=\left\|\hat{\mathbf{d}}_{A}^{(1)}-\hat{\mathbf{d}}_{B}^{(2)}\right\|_{2} \\ \ \\ n(c)=\min \left(\left\|\hat{\mathbf{d}}_{A}^{(1)}-\hat{\mathbf{d}}_{N_{2}}^{(2)}\right\|_{2},\left\|\hat{\mathbf{d}}_{N_{1}}^{(1)}-\hat{\mathbf{d}}_{B}^{(2)}\right\|_{2}\right) p(c)=d^A(1)d^B(2)2 n(c)=min(d^A(1)d^N2(2)2,d^N1(1)d^B(2)2)

不匹配的负样本是选择匹配像素周围一定区域以外,且与该描述符距离最小的样本
N 1 = arg ⁡ min ⁡ P ∈ I 1 ∥ d ^ P ( 1 ) − d ^ B ( 2 ) ∥ 2  s.t.  ∥ P − A ∥ ∞ > K N_{1}=\underset{P \in I_{1}}{\arg \min }\left\|\hat{\mathbf{d}}_{P}^{(1)}-\hat{\mathbf{d}}_{B}^{(2)}\right\|_{2} \text { s.t. }\|P-A\|_{\infty}>K N1=PI1argmind^P(1)d^B(2)2 s.t. PA>K

给定边界条件 M M M,损失定义为:
m ( c ) = max ⁡ ( 0 , M + p ( c ) 2 − n ( c ) 2 ) m(c)=\max \left(0, M+p(c)^{2}-n(c)^{2}\right) m(c)=max(0,M+p(c)2n(c)2)

  此时,损失 m ( c ) m(c) m(c) 会抑制任意可能导致错误匹配的特征对,从而加强描述符的独特性。为了检测的可重复性,在损失中加入一个检测项,作为最终的损失:
L ( I 1 , I 2 ) = ∑ c ∈ C s c ( 1 ) s c ( 2 ) ∑ q ∈ C s q ( 1 ) s q ( 2 ) m ( p ( c ) , n ( c ) ) \mathcal{L}\left(I_{1}, I_{2}\right)=\sum_{c \in \mathcal{C}} \frac{s_{c}^{(1)} s_{c}^{(2)}}{\sum_{q \in \mathcal{C}} s_{q}^{(1)} s_{q}^{(2)}} m(p(c), n(c)) L(I1,I2)=cCqCsq(1)sq(2)sc(1)sc(2)m(p(c),n(c))

其中 s c ( 1 ) s c ( 2 ) s_{c}^{(1)} s_{c}^{(2)} sc(1)sc(2) 是检测得分, C \mathcal{C} C 是所有匹配点的集合。

  把左半部分作为检测项,右半部分作为特征项,从各个公式可以发现,检测项越大,是特征点的概率越高,特征项越小,特征越准确(或者说越容易得到正确的匹配);这样一来当最小化损失时,越可能是特征点的部分他的特征就越准确,而不太可能是特征点的位置,特征不准确也影响不大。

3. 细节

  原始数据集是 MegaDepth,选出稀疏 SfM 点云重叠高于50%的作为图像对。每一对图像,通过深度信息将第二张图像的所有点投影到第一张图像中,并通过核查深度图去除遮挡的像素。
  训练的时候对每一对图像随机裁剪出一个以一个对应关系为中心的 256 × 256 256\times 256 256×256 的区域,训练的 batch size 取1,并确保有至少128个对应关系。
  测试的时候修改了一些网络结构,让输出的特征图分辨率提高(输入图像的四分之一),从而得到更多的特征点,点的位置也会更准。

4. 个人总结

  D2-Net 所用的训练数据是利用深度信息获取像素级对应关系的图像对,这样便有足够的标签让网络的特征正确匹配。之后的问题就在于如何确定特征点的位置,这边的解决方案就是(参考传统算法)设计一套规则,在特征图上进行运算得到像素级的得分图。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐