【问题标题】:Flann KNN Matcher in OpenCV returns only one point instead of a pairOpenCV 中的 Flann KNN 匹配器仅返回一个点而不是一对
【发布时间】:2025-12-01 06:00:01
【问题描述】:

当我运行 Flann KNN 匹配器时,有时 KNN 匹配器只返回一个点,因为依赖于两个点的匹配器之后的代码失败:

flann = cv2.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(descriptors1, descriptors2, k=2)

# Retrieve good matches
good_matches = []

# ratio test as per Lowe's paper
for i, (m, n) in enumerate(matches):
    if m.distance < 0.7*n.distance:
        good_matches.append((m, n))

抛出此错误:

Traceback (most recent call last):
  File "main.py", line 161, in <module>
    main(vid, video_file)
 ...
  File "main.py", line 73, in consume_for_homography_error
    matches = flann_matcher(descriptors1, descriptors2)
  File "main.py", line 48, in flann_matcher
    for i, (m, n) in enumerate(matches):
ValueError: need more than 1 value to unpack

这里似乎有什么问题?

【问题讨论】:

  • 你找到解决这个问题的方法了吗?

标签: python python-2.7 opencv flann


【解决方案1】:

问题是匹配似乎被填充为固定长度的列表列表,在本例中为len(matches) == 500,即使找到的匹配数量少于该数量。

尝试添加这个:

matches = [match for match in matches if len(match) == 2]
(or even better)
good_matches = [match[0] for match in matches if len(match) == 2 and match[0].distance 
                                                        < .7*match[1].distance]


before the for loop to delete these (empty lists?).

【讨论】:

    【解决方案2】:

    有时,该算法无法为查询图像中的单个描述符找到 2 个潜在匹配项。发生这种情况时,您可能在该索引的列表中仅获得 1 个或可能为零的 DMatch 项。 如果列表中有一个 DMatch 条目,那么这是该描述符的最佳条目,并且没有其他可比较的条目,所以我们应该简单地接受它作为一个很好的匹配。例如:

    good = []
    for i in range(0, len(matches)):
        if len(matches[i]) == 1:
            m = matches[i][0]
            good.append([m])
        if len(matches[i]) > 1:
            (m,n) = matches[i]
            if m.distance < 0.75*n.distance:
                good.append([m])
    

    【讨论】:

      【解决方案3】:

      knnMatch 函数返回的匹配集合是 List 类型,其中每个元素又是 2 个 DMatch 对象的列表(因为 k=2)。因此,当您在匹配列表上应用枚举器时,您将在每次迭代中获得索引值和一个 List 对象。您的代码在每次迭代中都需要索引值和一个元组。这就是问题所在。请查看以下代码。

      flann = cv2.FlannBasedMatcher(index_params, search_params)
      
      matches = flann.knnMatch(descriptors1, descriptors2, k=2)
      
      # Retrieve good matches
      good_matches = []
      
      # ratio test as per Lowe's paper
      for m,n in matches:
          if m.distance < 0.7*n.distance:
          good_matches.append((m, n))
      

      【讨论】:

        最近更新 更多