第 11 名解决方案 - motono0223
作者: motono0223 (Grandmaster)
发布时间: 2025-06-04
竞赛排名: 第 11 名
概述
代码笔记本
详细描述
创建图像对
- 全局特征提取器: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
- 后处理
过滤图像对
此步骤过滤掉对 SfM 不关键的图像对。剪枝加速了重建过程,并使 COLMAP 的增量映射有更多机会重建小簇。
图像匹配结果可以表示为一个网络,其中图像是节点,匹配计数是边;然后可以计算连接到每个节点的边数。
通过限制每个图像节点的边数(阈值 = 6)来移除非必要的对。如果节点超过六条边,则丢弃匹配数最少的边,直到只剩下六条。
- 在 COLMAP 的增量映射中,选择一个初始对,然后逐个注册附加图像;初始对是从数据库中存储的匹配中统计选择的。[1]
- 匹配结果有时会集中在少数图像上,导致增量映射输出偏向某些簇。
- 剪枝连接到具有许多匹配的图像的图像对,增加了初始对在较小簇内形成的可能性。
粗略聚类
- 使用 NetworkX 实现轻量级聚类例程。
- 对于每个图像对,从
matches.h5 读取匹配数;将具有 150 个或更多匹配的边添加到 G = nx.Graph()。
- 然后通过
nx.weakly_connected_components(G) 获得簇。
colmap (穷举匹配)
- 使用 pycolmap 的
exhaustive_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()
