gpt4 book ai didi

python - 多 View 特征点的OpenCV Flann匹配

转载 作者:太空宇宙 更新时间:2023-11-03 22:20:51 24 4
gpt4 key购买 nike

我正在尝试准备重叠航拍图像以进行束平差以创建地形的 3D 重建。到目前为止,我有一个脚本可以计算哪些图像重叠并构建这些图像对的列表。我的下一阶段是检测和计算每个图像的 SIFT 特征,然后将特征点与数据集中重叠的任何图像进行匹配。为此,我使用了 OpenCV 中提供的 FLANN 匹配器。

我的问题是,捆绑平差输入需要为每个特征点提供唯一的点 ID。据我所知,FLANN 匹配器一次只能匹配两个图像的特征点。那么,如果我在 5 个摄像头中有一个相同的点可见,我该如何为这个点提供一个在 5 个摄像头中保持一致的 ID?如果我现在在匹配过程中保存点时简单地给它一个 ID,则同一个点将具有不同的 ID,具体取决于使用哪些相机组来计算它。

bundle adjustment 输入格式为:

camera_id (int), point_id(int), point_x(float), point_y(float)

我使用它是因为我正在遵循的捆绑调整代码教程使用了 BAL数据集(即 ceres solverscipy )。

我最初的想法是计算和描述所有图像中的所有 SIFT 点并添加到 1 个列表中。从这里我可以删除任何重复的关键点描述符。一旦我在我的数据集中有了一个唯一的 SIFT 点列表,我就可以依次为每个点添加一个 ID。然后每次我匹配一个点时,我可以在这个列表中查找点描述符并根据该列表分配点 ID。虽然我觉得这可行,但它看起来很慢,并且没有使用我用于匹配的 K-TREE 匹配方法。

最后,我的问题是......有没有办法在 OpenCV python 中使用 FLANN 匹配器实现多个 View (>2) 的特征匹配?或者...摄影测量/SLAM 社区是否有解决此问题的通用方法?

到目前为止我的代码:

matches_list = []
sift = cv2.xfeatures2d.SIFT_create()

FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params)

for i in overlap_list:

img1 = cv2.imread(i[0], 0)
img2 = cv2.imread(i[1], 0)

img1 = cv2.resize(img1, (img1.shape[1]/4, img1.shape[0]/4), interpolation=cv2.INTER_CUBIC)
img2 = cv2.resize(img2, (img2.shape[1]/4, img2.shape[0]/4), interpolation=cv2.INTER_CUBIC)

kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

matches = flann.knnMatch(des1,des2,k=2)
for j,(m,n) in enumerate(matches):
if m.distance < 0.7*n.distance:
pt1 = kp1[m.queryIdx].pt
pt2 = kp2[m.trainIdx].pt
matches_list.append([i[0], i[1], pt1, pt2])

这将返回一个具有以下结构的列表,长度 = 特征匹配数:

matches_list[i] = [camera_1.jpg, camera_2.jpg, (cam1_x, cam1_y), (cam2_x, cam2_y)]

最佳答案

这个问题问的确切问题是“当我只有成对匹配时,我如何才能唯一地标记一组多个匹配项?”

这是一个标准的图论问题:从边集到连通分量。

只是为了一些直觉:

Connected components

想法是你有边(成对的特征匹配)。所以例如在上图中,(2, 1) 是一条边。以及 (1, 3) 和 (5, 6),依此类推。因此,由于 2 与 1 匹配,而 1 与 3 匹配,实际上,1、2 和 3 可能都是相同的特征。因此,您可以通过查找在此图中连接在一起的所有组件,将相同的功能组合在一起。请注意,该图只需要用这些对来描述,仅此而已。

您已经有了计算匹配的代码。我将提供一些代码来计算连接的组件。不能保证此代码特别快,但它对您使用的任何类型的数据都应该是健壮的。但是请注意,您发送的每个不同节点都必须具有不同的数据,因为这使用了集合。

def conncomp(edges):
"""Finds the connected components in a graph.

Parameters
----------
edges : sequence
A sequence of pairs where the pair represents an undirected edge.

Returns
-------
components : list
A list with each component as a list of nodes. Only includes single
nodes if the node is paired with itself in edges.
"""

# group edge pairs together into a dict
pair_dict = defaultdict(set)
nodes = set([num for pair in edges for num in pair])
for node in nodes:
for pair in edges:
if node in pair:
pair_dict[node] = pair_dict[node].union(set(pair))

# run BFS on the dict
components = []
nodes_to_explore = set(pair_dict.keys())
while nodes_to_explore: # while nodes_to_explore is not empty
node = nodes_to_explore.pop()
component = {node}
neighbors = pair_dict[node]
while neighbors: # while neighbors is non-emtpy
next_node = neighbors.pop()
if next_node in nodes_to_explore:
nodes_to_explore.remove(next_node)
next_nodes = set([val for val in pair_dict[next_node] if val not in component])
neighbors = neighbors.union(next_nodes)
component.add(next_node)
components.append(list(component))

return components

如上所述,此函数的输入是一个对(元组)列表。我只是发送配对 ID 列表,例如:

edges = [(img1_feat_i, img2_feat_j), ...]

其中 img1_feat_iimg2_feat_jknnMatchBFMatch 或您喜欢使用的任何内容匹配的功能 ID .

该函数将返回一个组件列表,例如

[[img1_feat_i, img2_feat_j, img3_feat_k, ...], ...]

每个组件(即每个子列表)在图像中都是相同的特征,因此您可以将所有这些不同的 ID 映射到该组件的一个唯一 ID。

关于python - 多 View 特征点的OpenCV Flann匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49629221/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com