返回列表

[39th place] Superpoint+Lightglue & Keynet_Affnet_Hardnet_Adalam

611. Image Matching Challenge 2024 - Hexathlon | image-matching-challenge-2024

开始: 2024-03-25 结束: 2024-06-03 计算机视觉 数据算法赛
[第39名] Superpoint+Lightglue & Keynet_Affnet_Hardnet_Adalam

[第39名] Superpoint+Lightglue & Keynet_Affnet_Hardnet_Adalam

作者:Roy Wei

排名:第39名

发布日期:2024-06-06

首先,我要感谢组织者和Kaggle工作人员组织了这次比赛,感谢Hloc、Lightglue和pycolmap的作者,感谢我的队友@cody11null的出色工作。尽管 preliminary standing 没有达到我们的预期,但作为团队我们学到了很多。代表团队,我还要感谢@maxchen303去年发布的notebook。这是我们进行实验的baseline,我想很多团队都欠他一个大大感谢!

附:我们团队尝试了很多模型,并获得了一些见解。另外,CVPR期间我会在西雅图地区,我很乐意被邀请在workshop上展示我们的工作☺️ @oldufo


解决方案概述

解决方案概览

我们的思考

我们团队对IMC2024最大的印象是随机性。由于colmap的随机性会导致分数差异,很难建立起令人信服的本地pipeline,这使得一些简单技巧的效果变得模糊。此外,那些对结果零风险的技巧,如未注册图像本地化、多次重建,都不能显著提升分数。

尽管密集匹配在相机位置估计方面具有很大潜力,但正如去年获胜方案所提到的,它本质上与整个场景的重建不兼容。我们尝试了量化和其他各种技巧来建立视图轨迹,但都失败了。

本地结果

模型组合 平均mAA
Keynet+Affnets+Hardnet+Adalam 集成 23.5% ~ 24%
SP+LG* 25.7% ~ 26%
LoFTR < 15%
密集匹配 + 量化 <10%

*我们的实验表明,DoG + Affnet 在所有方法中表现最好,在准确性方面与集成方法相当。

*SP+LG平均得分更高,因为在lizard数据集上表现更好(多注册了约10张图片)以及在pond上略有提升。然而,在重建建筑结构方面,它不如Keynet+Affnets+Hardnet+Adalam(其他数据集亦然)。这启发我们重建模型时分别使用和不使用SP+LG来挤出一些额外精度。

对我们有效的做法:

  1. 在发送给模型前选择不同的合适分辨率 - 对于Superpoint和Lightglue,使用Hloc时最佳分辨率为2000(我们能够确认提升,因为每个数据集的分数都有小幅提升)。对于Keynet-Affnet-Hardnet,我们堆叠了基于1024和1600分辨率提取的关键点。对于小于1024的图像,我们使用相同的分辨率,因为放大设置为false。

  2. 使用Hloc进行图像本地化 - 对于lizard和pond等数据集,许多图像未注册。我们在最简单的阈值下成功恢复了额外的2-3张图像。

  3. 多次重建:我们设置不同的阈值来过滤匹配点过少的图像对,然后进行重建。我们使用以下公式估计每个模型的分数:score = num_images * num_3dpoints / projection_error。这帮助我们选择最佳模型,但与本地相比,它在LB上的提升更大(约为1%)。

巧合的是,我们最佳的提交甚至没有使用后面两个在本地有效的技巧,这再次表明运气才是关键 😬

无效的做法

  1. 密集匹配 - 最终总是导致0张图像注册。这并不令人惊讶,因为当图像与不同图像配对时,图像中的关键点会有所不同,因此始终只有两个2D坐标可以投影到3D点,模型因此无法稳健构建。遗憾的是,RoMa在手动检查它生成的图像对时表现相当好。我们尝试使用detector-free sfm来解决这个问题,但不幸的是无法在Kaggle上编译它。

  2. Omniglue - 我以为这会提升当前的SP+LG pipeline,但并没有。在尝试了不同配置后,它仍然无法在本地数据集上超越LG(大约有30~10张更多的图像未注册)。

  3. DISK + LG - 与keynet+affnet+hardnet关键点拼接会降低分数。此外,我们还发现kornia.feature存在一个bug,阻止模型从本地机器加载。 @oldufo

def modify_lightgluematcher():
    def new_init(self, feature_name: str = "disk", params = {}):
        super(KF.LightGlueMatcher, self).__init__(feature_name)
        self.feature_name = feature_name
        self.params = params
        self.matcher = KF.LightGlue(None, **params)
        
    KF.LightGlueMatcher.__init__ = new_init

我们没有做的

  1. 玻璃相关的技巧 - 看起来更高的分辨率在本地测试中对玻璃有更好的效果,但我们从未在网上实现过。我们还假设测试集中的玻璃器皿图像的相机位置与训练集中的相似,只是顺序不同。然而,我们不知道如何恢复顺序……(所以为第1名的创新方法点赞!)

如果你们对我们的解决方案有任何问题,欢迎在下方评论。 ❤️

同比赛其他方案