概述
HLOC (Hierarchical-Localization) 是由瑞士ETH Zurich的CVG (Computer Vision and Geometry) 研究组开发的开源视觉定位与三维重建工具箱。它集成了多种深度学习特征提取和匹配方法,号称可无缝对接COLMAP等三维重建软件,但是实际Colmap一直在升级,数据库表格字段等都在不断修改,用新版本会出现数据无法适配问题。
核心定位:
- 模块化的视觉定位工具箱
- 支持 Structure-from-Motion (SfM) 全流程
- 提供端到端的特征提取、匹配、定位方案
GitHub仓库:https://github.com/cvg/Hierarchical-Localization
安装与测试
环境要求
| 项目 | 要求 |
|---|---|
| Python | 3.8+ (推荐 3.10) |
| PyTorch | 1.8+ |
| CUDA | 可选,用于GPU加速 |
| COLMAP | 3.8+ (可选,用于重建) |
安装方式
方式一:pip安装(推荐)
bash
# 基础安装
pip install hloc
# 安装LightGlue支持
pip install "hloc[lightglue]"
# 安装所有可选依赖
pip install "hloc[all]"
方式二:源码安装(开发调试)
bash
git clone https://github.com/cvg/Hierarchical-Localization
cd Hierarchical-Localization
pip install -e .
快速测试
python
from hloc import extract_features, match_features
# 测试特征提取
conf = extract_features.confs['superpoint']
print("SuperPoint配置:", conf)
# 测试LightGlue配置
match_conf = match_features.confs['superpoint-lightglue']
print("LightGlue配置:", match_conf)
验证安装成功
bash
python -c "from hloc import extract_features; print('HLOC安装成功')"
支持的模型类型
特征提取模型 (Feature Extractors)
| 模型 | 年份 | 类型 | 描述子维度 | 特点 |
|---|---|---|---|---|
| SuperPoint | 2018 | 稀疏 | 256 | 自监督学习,实时性好 |
| SuperPoint2 | 2024 | 稀疏 | 256 | SuperPoint改进版,精度更高 |
| DISK | 2021 | 稀疏 | 128 | 专为匹配训练,鲁棒性强 |
| ALIKED | 2023 | 稀疏 | 128 | 轻量级,速度最快 |
| SIFT | 1999 | 稀疏 | 128 | 传统方法,尺度不变 |
| LoFTR | 2021 | 半密集 | - | 无需检测,直接匹配 |
特征匹配模型 (Feature Matchers)
| 模型 | 年份 | 特点 | 适用场景 |
|---|---|---|---|
| LightGlue | 2023 | 轻量级,自适应层数 | 推荐,通用场景 |
| SuperGlue | 2020 | 图神经网络,固定层数 | 高精度场景 |
| LoFTR | 2021 | 无需特征检测,直接匹配 | 低纹理场景 |
常用组合
| 组合 | 特点 | 推荐场景 |
|---|---|---|
| SuperPoint + LightGlue | 速度快,精度适中 | 通用三维重建 |
| SuperPoint + SuperGlue | 精度高,速度较慢 | 高精度定位 |
| DISK + LightGlue | 鲁棒性好 | 大视角变化 |
| LoFTR | 无检测步骤 | 低纹理/重复纹理 |
| ALIKED + LightGlue | 最快速度 | 实时应用 |
模型特点对比
SuperPoint vs 传统SIFT
| 维度 | SuperPoint | SIFT |
|---|---|---|
| 检测方式 | 深度学习heatmap | 尺度空间极值检测 |
| 描述子 | 256维float | 128维float |
| 尺度不变性 | 较弱(单尺度) | 强(多尺度金字塔) |
| 旋转不变性 | 较弱(有orientation输出) | 强(主方向计算) |
| 速度 | GPU下实时 | CPU较快 |
| 大视角变化 | 鲁棒性较差 | 较好 |
LightGlue vs SuperGlue
| 维度 | LightGlue | SuperGlue |
|---|---|---|
| 架构 | 简化的GNN | 完整的GNN |
| 层数 | 自适应(1-9层) | 固定(9层) |
| 速度 | 快2-3倍 | 较慢 |
| 内存 | 低30-50% | 较高 |
| 精度 | 略低 | 更高 |
| 适用 | 通用场景 | 高精度需求 |
资源占用
GPU显存需求
| 模型 | 图像尺寸 | 显存占用 |
|---|---|---|
| SuperPoint (推理) | 640×480 | 200-500 MB |
| SuperPoint (推理) | 1920×1080 | 500-800 MB |
| SuperPoint (推理) | 4000×3000 | 800-1200 MB |
| LightGlue (匹配) | N×N特征 | 100-300 MB |
| SuperGlue (匹配) | N×N特征 | 300-600 MB |
| LoFTR (推理) | 640×480 | 800-1500 MB |
推理速度参考 (NVIDIA RTX 3080)
| 操作 | 图像尺寸 | 耗时 |
|---|---|---|
| SuperPoint特征提取 | 640×480 | ~15ms |
| SuperPoint特征提取 | 1920×1080 | ~40ms |
| LightGlue匹配 | 1024个特征 | ~10ms |
| SuperGlue匹配 | 1024个特征 | ~30ms |
CPU运行(无GPU)
- SuperPoint: 约50-100ms/张(640×480)
- LightGlue: 约100-200ms/对
- 建议:大规模处理建议使用GPU
适用场景
推荐使用场景
| 场景 | 推荐配置 | 说明 |
|---|---|---|
| 无人机航拍重建 | SuperPoint+LightGlue | 图像质量好,视角变化小 |
| 室内SLAM | SuperPoint+LightGlue | 实时性好 |
| 街景定位 | SuperGlue | 精度高,容忍一定视角变化 |
| 低纹理场景 | LoFTR | 直接密集匹配,无需检测 |
| 大视角变化 | DISK+LightGlue | 鲯棒性更强 |
不推荐场景
| 场景 | 原因 | 替代方案 |
|---|---|---|
| 航向角差异大(>30°) | SuperPoint检测不稳定 | 使用DISK或LoFTR |
| 极端尺度变化 | 单尺度检测限制 | 使用传统SIFT |
| 旋转差异大 | orientation不够鲁棒 | 结合图像旋转预处理 |
| 低纹理重复纹理 | 特征点稀少/混淆 | 使用LoFTR |
特征提取方法
基本用法
python
from hloc import extract_features
from pathlib import Path
# SuperPoint配置
conf = extract_features.confs['superpoint']
conf['max_keypoints'] = 4096 # 每张图最大特征点数
conf['resize_max'] = 1600 # 图像最大尺寸
# 执行特征提取
extract_features.main(
conf=conf,
image_dir=Path('images/'),
feature_path=Path('output/feats-superpoint.h5')
)
主要配置参数
| 参数 | 默认值 | 说明 |
|---|---|---|
max_keypoints |
1024 | 每张图最大特征点数量 |
resize_max |
None | 图像缩放最大尺寸 |
resize_force |
False | 是否强制缩放 |
keypoint_threshold |
0.005 | 检测阈值 |
输出格式
特征提取结果存储为HDF5文件:
python
# HDF5结构
feats-superpoint.h5
├── image1.jpeg
│ ├── keypoints: (N, 2) float32 # 特征点坐标
│ └── descriptors: (256, N) uint8 # 描述子
│ └── scores: (N,) float32 # 检测置信度
├── image2.jpeg
│ └── ...
关键点坐标说明
- 坐标原点:图像左上角 (0, 0)
- 坐标单位:像素
- COLMAP兼容:需要 +0.5 偏移
特征匹配方法
图像对生成
python
from hloc import pairs_from_exhaustive, pairs_from_retrieval
# 方式1:全连接配对(适合小规模)
pairs_from_exhaustive.main(
outputs=Path('pairs-exhaustive.txt'),
image_dir=Path('images/')
)
# 方式2:基于检索配对(适合大规模)
pairs_from_retrieval.main(
outputs=Path('pairs-retrieval.txt'),
image_dir=Path('images/'),
num_matched=10 # 每张图配对数量
)
LightGlue匹配
python
from hloc import match_features
conf = match_features.confs['superpoint-lightglue']
match_features.main(
conf=conf,
pairs=Path('pairs-exhaustive.txt'),
features=Path('feats-superpoint.h5'),
matches=Path('matches-lightglue.h5')
)
匹配输出格式
python
# matches-lightglue.h5结构
matches.h5
├── image1.jpeg
│ └── image2.jpeg
│ └── matches0: (N1,) int32 # img1每个kp对应的img2 kp索引
│ # matches0[i] = -1 表示无匹配
│ # matches0[i] = j 表示img1的第i个kp匹配img2的第j个kp
│ └── matching_scores0: (N1,) float32 # 匹匹置信度
匹配转COLMAP格式
python
import numpy as np
# LightGlue matches0 -> COLMAP interleaved format
matches0 = f[img1][img2]['matches0'][:]
valid_mask = matches0 >= 0
kp1_ids = np.where(valid_mask)[0].astype(np.uint32)
kp2_ids = matches0[valid_mask].astype(np.uint32)
# COLMAP格式: [kp1_0, kp2_0, kp1_1, kp2_1, ...]
match_data = np.column_stack([kp1_ids, kp2_ids])
match_data = match_data.flatten().astype(np.uint32)
模型微调
SuperPoint微调
官方支持程度:部分支持
- 预训练模型已足够好,通常无需微调
- 可通过homographic adaptation进行自监督训练
- 需要 自己实现训练代码
微调流程(参考):
python
# 1. 准备合成数据(homographic变换)
# 2. 使用homographic adaptation生成伪标签
# 3. 训练检测和描述分支
LightGlue微调
官方支持程度:不支持
- LightGlue是固定架构,不支持微调
- 如需定制,建议修改SuperGlue
替代方案
如需定制化特征提取:
- 使用 DISK:支持在自定义数据上训练
- 使用 ALIKED:有官方训练代码
- 使用传统方法 SIFT:无需训练
常见问题与升级方向
问题1:大角度差异匹配失败
现象:图像拍摄角度差异>30°的图像对匹配数为0
原因:
- SuperPoint单尺度检测,对大视角变化鲁棒性差
- 特征点重复检测率低
升级方向:
- 尝试 DISK 或 XFeat(专门为大视角变化设计)
问题2:尺度漂移问题
现象:重建结果尺度与真实尺度相差数十倍
原因:
- HLOC默认流程不使用GPS先验
incremental_mapping无法控制尺度
升级方向:
- 使用COLMAP的
pose_prior_mapper - 修改HLOC流程支持GPS输入
问题3:数据库兼容性
现象:HLOC输出与COLMAP新版本数据库Schema不兼容
原因:
- COLMAP 3.13+引入新表结构(frames, frame_data)
- pair_id编码方式变化
升级方向:
- 使用hloc官方提供的数据库导入函数
- 手动构建兼容数据库
- 使用COLMAP CLI而非pycolmap绑定
问题4:特征点检测不一致
现象:相似位置的特征点在不同图像中描述子差异大
原因:
- SuperPoint检测不稳定,同一物理点可能检测到不同kp
- 描述子受局部纹理影响
参考资料
官方资源
- GitHub仓库:https://github.com/cvg/Hierarchical-Localization
- 文档目录:https://github.com/cvg/Hierarchical-Localization/tree/master/doc
- 示例代码:https://github.com/cvg/Hierarchical-Localization/tree/master/pipeline
论文
- SuperPoint :SuperPoint: Self-Supervised Interest Point Detection and Description (2018)
- SuperGlue :SuperGlue: Learning Feature Matching with Graph Neural Networks (2020)
- LightGlue :LightGlue: Local Feature Matching at Light Speed (2023)
- LoFTR :LoFTR: Detector-Free Local Feature Matching with Transformers (2021)
- DISK :DISK: Learning local features with policy gradient (2021)
相关工具
- COLMAP:https://github.com/colmap/colmap
- LightGlue独立仓库:https://github.com/cvg/LightGlue
快速参考卡片
bash
# 安装
pip install hloc[lightglue]
# 特征提取
python -c "
from hloc import extract_features
extract_features.main(
conf={'superpoint': {'max_keypoints': 4096}},
image_dir='images/',
feature_path='feats.h5'
)"
# 匹配
python -c "
from hloc import match_features, pairs_from_exhaustive
pairs_from_exhaustive.main(outputs='pairs.txt', image_dir='images/')
match_features.main(
conf={'superpoint-lightglue': {}},
pairs='pairs.txt',
features='feats.h5',
matches='matches.h5'
)"