LoFTR: Detector-Free Local Feature Matching with Transformers
受到:受到开创性作品 SuperGlue 的启发
摘要总结:
提出了一种局部图像特征匹配的新方法。更为突出说明的是室内场景下的特征点的匹配问题。
- 不是依次执行图像特征检测、描述和匹配,也就是传统的图像匹配算法主要是采用了手工制作的特征(例如具有 SIFT 描述符 的 Hessian 仿射检测器)在强烈的视点变化和恒定照明下获得了令人印象深刻的性能。
手工制作的特征”在这里指的是那些通过算法直接从图像数据中提取的特征,这些特征的提取和描述过程是由人类基于对图像属性的理解来设计的,而不是通过机器学习模型自动学习得到的。
-
论文提出了首先在粗略水平上建立像素级密集匹配,然后在精细水平上细化良好的匹配。
-
我们在 Transformer 中使用自注意力层和交叉注意力层来获取以两个图像为条件的特征描述符。
-
Transformer 提供的全局感受野使我们的方法能够在低纹理区域产生密集匹配。而特征检测器通常很难在这些区域产生可重复的兴趣点。
本文的创新点在于Transformer提供的全局感受野使得该方法能够在低纹理区域产生密集匹配。
相关背景介绍:
减少篇幅突出重点的知识,对引言和相关工作中的一些背景知识进行简单的总结和概括。
传统的sift特征点检测算法分为了三个步骤
- feature detection, :在检测阶段,首先将
角点
等显着点检测为每个图像中的兴趣点
- feature description, 然后在这些兴趣点的邻域区域周围提取
局部描述符
。 - and feature matching. 最近邻搜索或更复杂的匹配算法找到它们的点对点对应关系。
好处:特征检测器的使用减少了匹配的搜索空间,并且得到的稀疏对应足以满足大多数任务
之前自己看的几篇论文基于神经网络cnn(领域共识网络
)就无法区分不明显的区域。论文中它说是因为无法获得全局的感受野的问题,也间接的说明了全局感受野的重要性。
解决问题的方式:全局感受野,同时加入位置编码之后还会和位置相关。从而在匹配的时候会考虑到位置的信息。
之后我们着重介绍点匹配的发展阶段,这种局部的特征点匹配是如何发展到商汤科技和浙大的这篇cvpr2021的阶段的
阶段一:Detector-based Local Feature Matching
- Detector-based Local Feature Matching 基于检测器的局部特征匹配:SIFT ORB LIFT
- 基于学习的局部特征匹配方法SuperGlue:受两组兴趣点及其描述符作为输入,并通过
图神经网络 (GNN)
学习它们的匹配。SuperGlue 中的注意力范围也仅限于检测到的兴趣点。
阶段二:Detector-free Local Feature Matching
- Detector-free Local Feature Matching基于无检测器的局部特征匹配方法。
- SIFT Flow
- NCNet
- Sparse NCNet
- DRC-Net:提出了从粗到细的过程
阶段三:Transform处理长序列工作的兴起。
核心方法
核心:建议通过无检测器设计来解决特征检测器的可重复性问题
什么是特征检测器的可重复性问题呢?
特征检测器的可重复性问题指的是,在图像序列或不同视角下,特征检测器能否稳定地检测到相同的特征点。可重复性高的特征检测器能够在不同图像中准确地检测并匹配相同的特征点,这对于图像配准、立体视觉和三维重建等任务至关重要。
Local Feature Extraction
- 使用带有FPN的CNN网络(RestNet)主要是两个尺度1/8和1/2
- 表示形式分别为:
F ~ A and F ~ B \tilde{F}^{A} \text { and } \tilde{F}^{B} F~A and F~B
F ^ A and F ^ B \hat{F}^{A} \text { and } \hat{F}^{B} F^A and F^B
Local Feature Transformer (LoFTR) Module
也就是对应的比较核心的:(LoFTR) Module部分。——提取位置和上下文相关的局部特征
将1/8的特征图展平之后经过Transform之后得到的形式为:
F ~ t r A F ~ t r B \tilde{F}_{t r}^{A} \tilde{F}_{t r}^{B} F~trAF~trB
简单的介绍了一下Transform的基础信息,与信息检索类似,查询向量 Q 从值向量 V 中检索信息。根据 Q 和每个值 V 对应的关键向量 K 的点积计算出的注意力权重。
Attention ( Q , K , V ) = softmax ( Q K T ) V \operatorname{Attention}(Q, K, V)=\operatorname{softmax}\left(Q K^{T}\right) V Attention(Q,K,V)=softmax(QKT)V
直观上,注意力操作通过测量查询元素与每个关键元素之间的相似度来选择相关信息。 输出向量是按相似度分数加权的值向量的总和。 结果,如果相似度高,则从值向量中提取相关信息。 这个过程在图神经网络中也称为“消息传递”
线性的Transform层
将Q和K的长度表示为N,将它们的特征维度表示为D Transformer 中 Q 和 K 之间的点积随着输入序列的长度呈二次方增长的计算成本 (O(N2))。
提出通过用替代核函数 sim(Q,K) = φ(Q) · φ(K)T 替换原始注意力层中使用的指数核,将 Transformer 的计算复杂度降低到 O(N),其中 φ( ·) = elu(·) + 1。
模型不再需要计算和存储整个注意力矩阵,从而显著减少了内存和计算资源的需求.
sim
(
Q
,
K
)
=
ϕ
(
Q
)
⋅
ϕ
(
K
)
T
ϕ
(
.
)
=
elu
(
.
)
+
1
\begin{array}{c} \operatorname{sim}(Q, K)=\phi(Q) \cdot \phi(K)^{T} \\ \phi(.)=\operatorname{elu}(.)+1 \end{array}
sim(Q,K)=ϕ(Q)⋅ϕ(K)Tϕ(.)=elu(.)+1
之后论文的后面提到了参考DETR中的思想引入位置编码的概念。By adding the position encoding toF˜A andF˜B
这对于 LoFTR 在不明显的区域中产生匹配的能力至关重要自己理解也就是在匹配的时候具有位置信息的学习能力了。
虽然白墙的颜色是均匀的但是经过Transfrom之后因为位置的不同产生颜色上的变化的。
Self-attention and Cross-attention Layers
交替的经过自注意力层和交叉注意力层。输入的特征表示为:
f i and f j f_{i} \text { and } f_{j} fi and fj
图a:(a) 卷积的感受野图示图(b)Transform的感受野的形式。
Transformers 的全局感受野使得这种连接只需通过一个注意力层就可以建立。
Establishing Coarse-level Matches
在经过局部的Transfrom的特征提取模块之后,将得到的
F ~ t r A F ~ t r B \tilde{F}_{t r}^{A} \tilde{F}_{t r}^{B} F~trAF~trB
部分送入到粗粒度匹配的部分中去执行第一个阶段的匹配过程。通过下面的公式来计算:变换后特征之间的得分矩阵 S
S ( i , j ) = 1 τ ⋅ ⟨ F ~ t r A ( i ) , F ~ t r B ( j ) ⟩ . \mathcal{S}(i, j)=\frac{1}{\tau} \cdot\left\langle\tilde{F}_{t r}^{A}(i), \tilde{F}_{t r}^{B}(j)\right\rangle . S(i,j)=τ1⋅⟨F~trA(i),F~trB(j)⟩.
可以在S的两个维度上应用softmax(以下称为双softmax)通过归一化来获得相互最近邻匹配的概率:
P c ( i , j ) = softmax ( S ( i , ⋅ ) ) j ⋅ softmax ( S ( ⋅ , j ) ) i . \mathcal{P}_{c}(i, j)=\operatorname{softmax}(\mathcal{S}(i, \cdot))_{j} \cdot \operatorname{softmax}(\mathcal{S}(\cdot, j))_{i} . Pc(i,j)=softmax(S(i,⋅))j⋅softmax(S(⋅,j))i.
之后就可以基于上面算出的置信度矩阵Pc,来进行匹配的选择了Match Selection
选择置信度高于阈值 θc 的匹配,并进一步强制执行相互最近邻 (MNN) 标准它过滤可能的异常值粗匹配(这里的意思是说要互相的进行相关性运算,也就是A与B计算成立之后,还要通过B与A进行一个相关性的运算
)。 我们表示粗级匹配预测为下面的形式:
M c = { ( i ~ , j ~ ) ∣ ∀ ( i ~ , j ~ ) ∈ MNN ( P c ) , P c ( i ~ , j ~ ) ≥ θ c } \mathcal{M}_{c}=\left\{(\tilde{i}, \tilde{j}) \mid \forall(\tilde{i}, \tilde{j}) \in \operatorname{MNN}\left(\mathcal{P}_{c}\right), \mathcal{P}_{c}(\tilde{i}, \tilde{j}) \geq \theta_{c}\right\} Mc={(i~,j~)∣∀(i~,j~)∈MNN(Pc),Pc(i~,j~)≥θc}
这里的粗粒度可以看作是区域之间的匹配过程了。
Coarse-to-Fine Module
建立粗略匹配后,使用从粗到细的模块将这些匹配细化到原始图像分辨率。
- 将其位置(ˆi,ˆj)定位在精细级特征图上
F ^ A and F ^ B \hat{F}^{A} \text { and } \hat{F}^{B} F^A and F^B
也就是从粗的匹配进一步细化到细的匹配上:
(
i
~
,
j
~
)
−
>
(
i
^
,
j
^
)
(\tilde{i}, \tilde{j}) -> (\hat{i}, \hat{j})
(i~,j~)−>(i^,j^)
- 然后裁剪两组大小为 w × w 的局部窗口。 然后,较小的 LoFTR 模块将每个窗口内的裁剪特征变换 Nf 次产生两个变换后的局部特征图
F ^ t r A ( i ^ ) and F ^ t r B ( j ^ ) \hat{F}_{t r}^{A}(\hat{i}) \text { and } \hat{F}_{t r}^{B}(\hat{j}) F^trA(i^) and F^trB(j^)
其中i和j表示的是区域的中心位置信息。
-
然后,我们将 FA tr (ˆi) 的中心向量与 ˆB tr (ˆj) 中的所有向量相关联,从而生成一个热图,该热图表示 ˆj 与 ˆi 邻域中每个像素的匹配概率
-
通过计算概率分布的期望,我们得到待匹配的IB图上亚像素精度的最终位置。从而完成最终的匹配过程。
对于最后的训练部分因为是工业上落地的实现项目了,在训练的时候分为了室内场景的训练和室外场景的训练。训练所使用的数据集的大小和GPU资源不是我们能够在复刻的,因此后面的重点是学习预训练模型的加载的流程同时查看源码。
算法整体概括
论文原文中对于核心细节的描述过程较为的抽象,因此在这个部分在对其中涉及到的一些细节的部分进行补充说明。
Loftr特征点匹配算法与传统的特征点匹配算法的优势:
- 不需要先得到特征点,这也就解决了第一个问题
- End2End的方式,用起来比较方便,效果也更好
整体流程的核心就是Transform了下面是整个算法的一个核心的流程图
- 第一步:通过backbone进行特征提取。
- 注意:输入是两张图像分别得到不同层特征输入:[2,1,480,640]两张图像拼一起进行backbone
- 通过我们的backbone网络分别得到下采样2倍和下采样8倍的特征图。
- 使用核心的Transform的部分
-
这里就完全和Transform定义与特征点匹配相互对应起来了 对于经过特征提取的两个Feature map A和B来我们把A中的点定义为q B中的点定义为k它们之间做注意力机制,也就是我们常见的cross attention交叉注意力机制。
-
同时我们需要去匹配的A特征图,要在自己的像素之间做一个self-attention的机制使其具有一个全局的感受野避免匹配的重复性。
- 我们首先要先将这个特征图拉长也就是我们的Transform要求输入的应该是一个token序列。然后进行位置编码,传统的匹配中更多的考虑的是特征关系而去忽略了位置上的关系。所以这里要进行位置编码。
这里就对于的第一块,两张图像分别展开成序列,同时分别加上位置编码。也就是粗级局部特征变换
- 下面我们使用的方式是先做Self-Attention Layer在做Cross-Attention Layer按照这个顺序将它的整个过程重复N次
为什么要按照这种方式来设计呢?个人的理解是第一次先做自注意力是为了获取全局的信息,之后我们在做交叉注意力进行匹配,重复的做自注意力是为了告诉后面的特征点已匹配的部分信息,避免重复的匹配。所以按照这个顺序匹配了6次
- self-attention的意思是别选重复了先定义好自身的分工。理解为自身点选取的一个过程这里没有画全只是画了部分的点每个点要和其他的点计算注意力(点积)
- Cross-attention的意思找到之间的配对关系。也就是每个点和图像中的其他的点还要再去匹配一下
我们按照这种方式进行计算之后原来的A和B特征和背景比较相似的点,之后就可加入了位置信息,之前无法进行确认配对的 A A’ B B’点就可以根据位置的信息完成配对了
位置关系和自身特征更明确(CNN后结果类似,但transformer后鲜明了)
这里我们经过Transform之后就得到了输出的特征向量或者说是嵌入的token向量,之后要考虑的就是匹配的问题了。
- 第三:粗粒度的一个匹配过程
根据上一步,我们多次的Attention后我们已经得到了两个图重构后的特征向量信息了。
- 两张图源码中好像分别有4800个点,现在咱们就能得到4800*4800的一个关系矩阵了。
P c ( i , j ) = softmax ( S ( i , ⋅ ) ) j ⋅ softmax ( S ( ⋅ , j ) ) i . \mathcal{P}_{c}(i, j)=\operatorname{softmax}(\mathcal{S}(i, \cdot))_{j} \cdot \operatorname{softmax}(\mathcal{S}(\cdot, j))_{i} . Pc(i,j)=softmax(S(i,⋅))j⋅softmax(S(⋅,j))i.
- softmax表示分别对两张图中的内积结果做归一化,
得到概率值
这里的粗粒度的匹配完成的并不是像素点到像素点的匹配而是位置到位置的一个匹配 原因在4800个点并非是整个图像区域内的所有的点而是提取过特征信息之后的点。
得到计算的关系之后我们如何的进行匹配呢?
- 通过阈值进行一部分过滤操作去掉置信度水平过低的点。
- 我们通过计算从A图得到的一个点匹配上了B图上的一个点,那么从B图来说A这个点是我们关系最大的一个匹配点吗? 也就是要相互运算
现在我们完成的是粗粒度的匹配,也就是说经过Transform之后完成的实际上是区域之间的匹配问题。但是区域之间的点的匹配会存在一定的偏差。
- 由此我们引出了最后一步,进行最后一步的细粒度匹配的问题。
补充Pytorch中的unfold操作。
torch.nn.functional.unfold(input, kernel_size, dilation=1, padding=0, stride=1)
input:输入张量
kernel_size:int或tuple类型,表示要提取的区域的大小
dilation:int或tuple类型,控制核的点之间的间隔,默认为1
padding:int或tuple类型,输入的每一侧添加额外的0,默认为0
stride:int或 tuple 类型,控制窗口在输入张量上滑动的步长,默认为1
unfold 是展开的意思,在 torch 中则是只卷不积,相当于只滑窗,不进行元素相乘
在上一步的基础上继续调整,咱们就叫它Coarse-to-Fine(一个通用的解决方案。)这一部分细粒度的匹配过程是比较绕的。
这里举例,w和h分别是5x5的区域 c代表的是128维的特征。
在细粒度的匹配过程中又用到了Transform了在粗粒度匹配完成的基础上再去走细粒度的点。
-
先将我们的特征图来进行拆解。每个特征是128的特征向量来表示。假设我们粗粒度输出的区域是5 x 5的一个区域就会得到128 x 5 x 5 =3200个特征(粗粒度匹配的每个特征块的)
-
之前我们提到了粗粒度的匹配生成的是4800x4800的一个关系矩阵。所以最后得到的一个结果就是4800 x 3200的一个结果。4800是长条的个数,3200是特征的个数
-
转换维度得到:4800x25x128,也就是每个长条块是由25个点组成的
实际上:例如筛选后得到4800个点里面只有142个是相互匹配的142x25x128这样一个矩阵。对这142个已经匹配的区域,再做实际点的微调,也就是25个点再最匹配的
相当于一个区域由25个点组成,咱们要再这个区域里找到最准确的点位置
在细粒度中,我们针对25个位置还要走Self Attention和Cross Attention.也就是输入142x25x128这样一个矩阵经过和之前同样的一个运算的方式。
-
transformer过后,只是把各个点的特征进行了重构那接下来如何进行微调呢?
-
现在我们要算这25个点与其中心点的关系,相当于我要以中心点为圆心,算周围点跟它的概率关系,这样会得到一个热度图例如最后输出了142x5x5的一个概率图,相当于哪块跟中心点关系紧密
-
相当于这25个点都会对最终结果产生影响,我们算其期望:142*2(实际位置)