想要了解深入了解D3Feat产生的原因,建议可以先去看一下D2Net[1],再来看D3Feat.
D3Feat核心优势:
-
D3Feat提供了一种联合框架,在学习描述子的同时进行关键点的检测,传统匹配可能是detect and describe,而本文遵循describe to detect的范式,即不需要额外显式预测关键点,在提取描述子的同时进行关键点的选取。
-
采用KPConv作为特征提取backbone,全卷积的网络架构能够使整个网络前向传播速度很快,作一次inference基本在1s以内。
-
最终用来做RANSAC配准的点不再是随机选取,而是选取网络学习出来的关键点。(其实关键点这种策略在3DMatch中效果并不是特别明显,原因是3DMatch benchmark作过2.5cm下采样后,基本点数在20K左右,随机选取5K点和选取5K关键点,最后RANSAC出来效果其实相差不大,或者说并没有很显著的优势,但在小点数比如250点时优势会比较明显)
Work Flow:
-
采用KPConv作为backbone进行特征提取,本文中不作重点介绍,需要的可以去看原文。(代码方面不得不说原作者Hugues THOMAS真的很强,但是会相对比较难理解一些,建议上手KPConv代码可以先从白博的这里入手)
KPConv在这里可以粗浅的理解为一个Encoder-Decoder结构:输入点云 P ∈ R N × 3 P \in {R^{N \times 3}} P∈RN×3,输出feature map F ∈ R N × c F \in {R^{N \times c}} F∈RN×c, c c c = 32. -
重要假设:可以认为,关键点的特征是具有一些特殊属性,即与领域点的特征会有较大差别的,因此使用这一点来进行关键点的选取:
首先约定一些符号:
D k = F : k , D k ∈ R N {D^k} = {F_{:k}},{D^k} \in {R^N} Dk=F:k,Dk∈RN,即 D k {D^k} Dk代表feature map的第 k k k列
d i = F i : , d i ∈ R c {d_i} = {F_{i:}},{d_i} \in {R^c} di=Fi:,di∈Rc,即 d i {d_i} di代表feature map的第 i i i行
判断一个点是否为关键点的标准:
即: x i {x_i} xi是关键点 ⇔ \Leftrightarrow ⇔ d i {d_i} di中最大的那一维(假设是第 k k k维,即第 i i i行 k k k列)特征同时在 x i {x_i} xi的所有邻域点 N x i {N_{{x_i}}} Nxi在第 k k k维上特征中是最大的。
描述会有些绕,上面的式子其实还是比较好看懂的。 -
如何把上述关键点选取的准则soften以进行训练呢,作者定义两个score来描述上述两个 a r g m a x argmax argmax操作:
其实看懂了第二步,这一步也不难理解, β i k \beta _i^k βik与 α i k \alpha _i^k αik分别对应第二步中的两个 a r g m a x argmax argmax操作。
β i k \beta _i^k βik ⇔ \Leftrightarrow ⇔depth_wise_max_score
α i k \alpha _i^k αik ⇔ \Leftrightarrow ⇔local_max_score
接着两个相乘,得到最终的saliency score map ∈ R N × 1 \in {R^{N \times 1}} ∈RN×1,代表每个点是否为关键点的置信度。
在代码中就是这样操作的:
至此,网络输出一个dense descriptor ∈ R N × 32 \in {R^{N \times 32}} ∈RN×32,一个saliency score map ∈ R N × 1 \in {R^{N \times 1}} ∈RN×1.
Loss:
Descriptor Loss:首先为了监督提取的特征,文中说用Hardest Contrastive Loss,其实代码中使用的是Circle Loss[2],这个loss现在在metric learning中用的也比较多了,效果非常好,这里不作展开。
Detector Loss:本文主要是看detector loss的设计,由于缺少哪些点是关键点的这种ground truth信息,因此使用on-the-fly技术对关键点信息进行监督:
从式子来分析(这里还是假设用的是Contrastive Loss),当
d
p
o
s
(
i
)
<
d
n
e
g
(
i
)
{d_{pos}}(i) < {d_{neg}}(i)
dpos(i)<dneg(i)时,说明此时若在特征空间中作KNN query,点
i
i
i是大概率被视作correspondence的,这时就希望点
i
i
i的saliency score越大越好,因此两者相乘,一负一正,正好是loss降低的方向。反过来也是如此。
Training:
默认150 epochs,总时长:
在训练集上circle loss和detector loss的收敛曲线:
可以看到整体收敛曲线非常平稳,接着分别在5000、2500、1000、500、250个点上进行evaluate,reported metrics是inlier ratio与feature match recall (registration recall在D3Feat的pytorch版本上的测试代码中没有写,tensorflow版本有,但我比较懒就没自己去写registration recall的scripts).
Keypoints | 5000 | 2500 | 1000 | 500 | 250 |
---|---|---|---|---|---|
Feature Matching Recall | 95.76 | 95.74 | 95.61 | 94.64 | 93.31 |
Inlier Ratio | 43.06 | 42.76 | 42.45 | 40.73 | 37.86 |
文中结果:
可以看到整体复现性还是非常高的。
可视化250个关键点:
Summary:
从上图也可以看到,关键点基本都避免选取在平坦区域,说明detector策略还是比较成功的,只不过和之前的分析一样,在结果方面,D3Feat在大点数时几乎没有什么优势,registration recall没有随机选点的FCGF高,但是在小点数比如250点时优势会比较明显。
个人感觉是数据集3DMatch的限制,导致关键点策略会不那么亮眼,毕竟从2w个点里选5k个点,也选不出什么花来,后面还有RANSAC给你兜底…
Pretrained Model can be found at here:link