返回列表

11th place solution

652. Image Matching Challenge 2025 | image-matching-challenge-2025

开始: 2025-04-01 结束: 2025-06-02 计算机视觉 数据算法赛
第 11 名解决方案 - motono0223
作者: motono0223 (Grandmaster)
发布时间: 2025-06-04
竞赛排名: 第 11 名

概述

Overview Image

代码笔记本

详细描述

创建图像对

  • 全局特征提取器:DinoV2/Base
  • Topk = 150

重排图像对

  • 由于图像对数量庞大,有必要减少图像匹配的处理时间。

  • 为了解决这个问题,在此过程中使用 ALIKED 模型(局部特征)对图像对进行重排和过滤。

  • 具体步骤如下:

    • 对于每张图像,使用 ALIKED 模型提取局部描述子。
      • 图像大小设置为 2048 像素,2048 个关键点,检测阈值为 0.01。
      • 所有描述子均使用 norm=1 进行归一化。
    • 计算每对图像的局部描述子之间的欧几里得距离矩阵。
      • 如果图像 1 有 N 个描述子,图像 2 有 M 个描述子,则使用 GPU 计算 NxM 距离矩阵。
    • 提取距离矩阵中每一行的最小值(得到 N 个最小值)。
    • 如果这些最小值低于 1.0 的阈值,则计为有效匹配。
      有效匹配数为 15 或更少的图像对将被丢弃。
  • 关键在于,由于 LightGlue (GNN) 计算成本高昂,因此使用距离矩阵作为轻量级近似来进行图像匹配的快速模拟。

图像匹配

  • 局部特征提取器:Aliked (n16)
    • resize_to: 1536 像素
    • max_num_keypoints: 8192 个点
    • detection_threshold: 0.01
  • 匹配器:LightGlue
  • 后处理
    • 匹配数量 > 15 个匹配

过滤图像对

  • 此步骤过滤掉对 SfM 不关键的图像对。剪枝加速了重建过程,并使 COLMAP 的增量映射有更多机会重建小簇。

  • 图像匹配结果可以表示为一个网络,其中图像是节点,匹配计数是边;然后可以计算连接到每个节点的边数。

  • 通过限制每个图像节点的边数(阈值 = 6)来移除非必要的对。如果节点超过六条边,则丢弃匹配数最少的边,直到只剩下六条。

    • 在 COLMAP 的增量映射中,选择一个初始对,然后逐个注册附加图像;初始对是从数据库中存储的匹配中统计选择的。[1]
    • 匹配结果有时会集中在少数图像上,导致增量映射输出偏向某些簇。
    • 剪枝连接到具有许多匹配的图像的图像对,增加了初始对在较小簇内形成的可能性。

粗略聚类

  • 使用 NetworkX 实现轻量级聚类例程。
  • 对于每个图像对,从 matches.h5 读取匹配数;将具有 150 个或更多匹配的边添加到 G = nx.Graph()
  • 然后通过 nx.weakly_connected_components(G) 获得簇。

colmap (穷举匹配)

  • 使用 pycolmapexhaustive_matching 进行计算。
  • 所有设置保持默认值 (pycolmap 0.6.1)。

colmap (增量映射)

  • 对于每个聚类图像集,在 pycolmap 中执行 incremental_mapping 四次。
  • 参数:
mapper_options = pycolmap.IncrementalPipelineOptions()
mapper_options.multiple_models   = True
mapper_options.min_model_size    = 2
mapper_options.max_num_models = 15
mapper_options.init_num_trials   = 1000

合并地图

  • 对于每个簇,合并地图。
  • 当满足以下条件时选择地图进行合并:
    • 地图之间共享六个或更多图像,且
    • 每个地图的 mean_reproj_error ≤ 2.0。
  • 合并使用 COLMAP 的原生 API 进行(而非 pycolmap):
    • model_merger 组合模型。
    • bundle_adjuster 优化相机参数。
      • --BundleAdjustment.refine_focal_length = 1
      • --BundleAdjustment.refine_principal_point = 1
      • --BundleAdjustment.refine_extra_params = 1

[1] pycolmap.incremental mapping()
Reference Image

同比赛其他方案