1. 提取特征得到的数据结构
提取特征后的 .h5
文件是一种层次化的文件结构,典型的数据组织方式如下:
feats-superpoint-n4096-r1600.h5
│
├── image_001.png
│ ├── descriptors : (256, N) 特征描述符矩阵
│ ├── image_size : (2,) 图像尺寸 (width, height)
│ ├── keypoints : (N, 2) 关键点坐标 (x, y)
│ └── scores : (N,) 每个关键点的分数
│
├── image_002.png
│ └── ...
│
└── ...
- descriptors:二维数组,大小为
(256, N)
,其中 256 是描述符的长度(例如 SuperPoint 生成的描述符长度),N 是关键点的数量。每一列表示一个关键点的特征描述符。 - image_size:包含图像的宽度和高度,便于后续处理时将图像缩放到合适的大小。
- keypoints:二维数组,大小为
(N, 2)
,表示图像中每个关键点的坐标(x, y)
。 - scores:一维数组,大小为
(N,)
,每个元素表示关键点的重要性或可信度分数。
1.1 在代码中加载并使用特征
可以使用 h5py
库来加载 .h5
文件,提取出特定图像的特征信息:
import h5py
import numpy as np
# 加载特征文件
with h5py.File('feats-superpoint-n4096-r1600.h5', 'r') as h5_file:
# 假设要处理 image_001.png 的特征
image_name = 'image_001.png'
# 获取关键点、描述符、分数和图像尺寸
keypoints = h5_file[image_name]['keypoints'][:]
descriptors = h5_file[image_name]['descriptors'][:]
scores = h5_file[image_name]['scores'][:]
image_size = h5_file[image_name]['image_size'][:]
# 打印一些信息
print(f"Keypoints shape: {keypoints.shape}")
print(f"Descriptors shape: {descriptors.shape}")
print(f"Scores shape: {scores.shape}")
print(f"Image size: {image_size}")
通过这种方式,可以读取任意图像的特征数据并进行操作。接下来,可以根据需求将这些特征用于图像检索、匹配、定位或三维重建等任务。
2.共视图像对
共视图像是指在三维重建过程中,多个图像拍摄了同一个场景中的相同部分(即有较多的相同三维点被观测到)。共视图像对的选择通常基于以下步骤:
- 计算共视关系:遍历所有图像对,计算它们之间的共视程度,即有多少三维点被这两个图像共同观测到。
- 选择最具共视性的图像对:对于每张图像,根据计算出的共视程度,选择与其共视程度最高的
num_covis
个图像。 - 成对保存:将每对共视程度最高的图像对存储到指定的输出文件中。
2.1生成的输出文件
输出文件(例如 pairs-db-covis20.txt
)是一个文本文件,保存的是图像对的名称,每一行表示一个图像对,例如:
image_0.png image_64.png
image_0.png image_136.png
...
- 结构:每行包含两个图像文件名,表示这两个图像之间有显著的共视关系。
- 用途:这些图像对将用于后续的特征匹配、三角化或重建等任务。
2.2如何使用共视图像对
生成的共视图像对文件通常用于以下任务:
- 特征匹配:在后续特征匹配时,可以只对这些共视图像对进行匹配,从而节省计算资源,提高匹配的准确性。
- 三维重建:共视图像对中拍摄了相同的场景部分,因此可以通过这些图像对中的特征点进行三角化,生成三维点云。
- 优化计算:通过限制匹配图像对的数量,可以显著减少后续计算量,避免对每张图像进行全图像集的匹配。
3.特征匹配信息的数据结构
feats-superpoint-n4096-r1600_matches-superglue_pairs-db-covis20.h5
│
├── image_001.png
│ ├── image_002.png
│ │ ├── matches0 : (N,) 每个关键点的匹配索引,N为关键点数
│ │ └── matching_scores0 : (N,) 每个匹配点的置信度分数
│ │
│ └── image_003.png
│ ├── matches0
│ └── matching_scores0
│
└── ...
matches0
的具体含义和结构
- 结构:
matches0
是一个一维数组,其长度为第一个图像中特征点的数量(假设为N
)。matches0[i]
表示第一个图像中第i
个特征点在第二个图像中的匹配点的索引。- 如果
matches0[i] = -1
,则表示第一个图像中的第i
个特征点没有在第二个图像中找到匹配点(即无效匹配)。 - 如果
matches0[i] >= 0
,则表示第一个图像中的第i
个特征点与第二个图像中matches0[i]
索引位置的特征点匹配。
举个例子
假设第一个图像有 5 个特征点,matches0
的内容如下:
matches0 = [ 3, -1, 2, 0, -1 ]
在这个例子中:
matches0[0] = 3
:表示第一个图像的第一个特征点与第二个图像的第 4 个特征点(索引 3)匹配。matches0[1] = -1
:表示第一个图像的第二个特征点在第二个图像中没有找到匹配点。matches0[2] = 2
:表示第一个图像的第三个特征点与第二个图像的第 3 个特征点(索引 2)匹配。matches0[3] = 0
:表示第一个图像的第四个特征点与第二个图像的第 1 个特征点(索引 0)匹配。matches0[4] = -1
:表示第一个图像的第五个特征点在第二个图像中没有找到匹配点。
3.1在代码中加载和处理匹配数据
以下是一个加载匹配数据的示例:
import h5py
import numpy as np
# 加载匹配文件
with h5py.File('feats-superpoint-n4096-r1600_matches-superglue_pairs-db-covis20.h5', 'r') as h5_file:
# 选择图像对 image_001.png 和 image_002.png
image_pair = h5_file['image_001.png/image_002.png']
# 获取匹配索引和匹配分数
matches = image_pair['matches0'][:]
matching_scores = image_pair['matching_scores0'][:]
# 过滤有效的匹配(索引为 -1 表示无匹配)
valid_matches = matches != -1
valid_indices = np.where(valid_matches)[0]
# 输出有效匹配信息
print(f"Valid matches count: {len(valid_indices)}")
print(f"Matching indices: {matches[valid_indices]}")
print(f"Matching scores: {matching_scores[valid_indices]}")