【问题标题】:BFMatcher match in OpenCV throwing errorOpenCV 中的 BFMatcher 匹配抛出错误
【发布时间】:2017-02-17 20:11:54
【问题描述】:

我正在使用 SURF 描述符进行图像匹配。我打算将给定的图像与图像数据库进行匹配。

import cv2
import numpy as np
surf = cv2.xfeatures2d.SURF_create(400)

img1 = cv2.imread('box.png',0)
img2 = cv2.imread('box_in_scene.png',0)

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


bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=True)
#I am planning to add more descriptors
bf.add(des1)

bf.train()

#This is my test descriptor
bf.match(des2)

bf.match 的问题是我收到以下错误:

OpenCV Error: Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)) in batchDistance, file /build/opencv/src/opencv-3.1.0/modules/core/src/stat.cpp, line 3749
Traceback (most recent call last):
  File "image_match4.py", line 16, in <module>
    bf.match(des2)
cv2.error: /build/opencv/src/opencv-3.1.0/modules/core/src/stat.cpp:3749: error: (-215) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function batchDistance

错误类似于this 帖子。给出的解释不完整且不充分。我想知道如何解决此问题。我也使用了 ORB 描述符以及具有NORM_HAMMING 距离的 BFMatcher。错误再次出现。 任何帮助将不胜感激。

我为此使用的两张图片是:

box.png

box_in_scene.png

我在 linux 中使用 Python 3.5.2 和 OpenCV 3.1.x。

【问题讨论】:

  • 所以.detectAndCompute 出现在 OpenCV 3x 及以上版本中?我使用的是 2.4,上面写着 module object not found...
  • 取决于opencv版本。遵循 2.4 或 3.x。

标签: python opencv surf orb


【解决方案1】:

在我使用 ORB 的情况下,问题是它找不到框架的特征并检查它是否为空。

qImageKeypoints, qImageDescriptors = orb.detectAndCompute(query_img_bw, None)
trainKeypoints, trainDescriptors = orb.detectAndCompute(train_img_bw, None)

if trainDescriptors is None:
    return False
else:
    # check some matching of the two images
    matcher = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=False)
    matches = matcher.match(qImageDescriptors, trainDescriptors)

【讨论】:

    【解决方案2】:

    编辑:使用 Python 3.6、OpenCV 3.4.1 的版本

    根据用户的选择,我在准备使用 SIFTORB 的程序时遇到了很多困难。最后,我可以为 SIFTORB

    找到正确的 BFMatcher 参数
    import cv2
    import numpy as np
    
    # ask user whether to use SIFT or ORB
    detect_by = input("sift or orb")
    
    1. 创建匹配器对象

      if detect_by == "sift":
          matcher = cv2.BFMatcher(normType=cv2.NORM_L2, crossCheck=False)
      
      elif detect_by is "orb":
          matcher = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=False)
      
    2. 在捕获和处理帧时

      while there_is_frame_to_process:
          if detect_by is "sift":
              matches = matcher.knnMatch(np.asarray(gray_des, np.float32), np.asarray(target_des, np.float32), k=2)
      
          elif detect_by is "orb":
              matches = matcher.knnMatch(np.asarray(gray_des, np.uint8), np.asarray(target_des, np.uint8), k=2)
      

    【讨论】:

      【解决方案3】:

      我遇到了同样的错误。但就我而言,这是因为我在cv2.BFMatcher_create 中使用带有cv2.NORM_HAMMING 指标的SIFT。将指标更改为 cv2.NORM_L1 解决了这个问题。

      引用BFMatcher的文档:

      normTypeNORM_L1NORM_L2NORM_HAMMINGNORM_HAMMING2 之一。 L1L2 规范是 SIFT 和 SURF 描述符的首选, NORM_HAMMING 应与 ORB、BRISK 和 Brief 一起使用,NORM_HAMMING2 WTA_K==34 时应与 ORB 一起使用(请参阅 ORB::ORB 构造函数 描述)。

      【讨论】:

        【解决方案4】:

        我发现我遇到了同样的错误。花了一段时间才弄明白——我的一些图像有些无特色,因此没有找到关键点,detectAndCompute 为描述符返回了None。在传递给BFMatcher.add() 之前,可能值得检查None 元素的描述符列表。

        【讨论】:

          【解决方案5】:

          要在两个图像的描述符之间搜索,请使用:

          img1 = cv2.imread('box.png',0)
          img2 = cv2.imread('box_in_scene.png',0)
          
          kp1,des1 = surf.detectAndCompute(img1,None)
          kp2,des2 = surf.detectAndCompute(img2,None)
          
          
          bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False)
          matches = bf.match(des1,des2)
          

          在多张图片中搜索

          add 方法用于添加多个测试图像的描述符。一旦所有描述符都被索引,您运行train 方法来构建底层数据结构(例如:KdTree,它将用于在 FlannBasedMatcher 的情况下进行搜索)。然后,您可以运行match 来查找哪个测试图像与哪个查询图像更匹配。你可以查看K-d_tree,看看它如何用于搜索多维向量(Surf 给出了 64 维向量)。

          注意:-BruteForceMatcher,顾名思义,没有内部搜索优化数据结构,因此有空的train方法。

          多图像搜索的代码示例

          import cv2
          import numpy as np
          surf = cv2.xfeatures2d.SURF_create(400)
          
          # Read Images
          train = cv2.imread('box.png',0)
          test = cv2.imread('box_in_scene.png',0)
          
          # Find Descriptors    
          kp1,trainDes1 = surf.detectAndCompute(train, None)
          kp2,testDes2  = surf.detectAndCompute(test, None)
          
          # Create BFMatcher and add cluster of training images. One for now.
          bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False) # crossCheck not supported by BFMatcher
          clusters = np.array([trainDes1])
          bf.add(clusters)
          
          # Train: Does nothing for BruteForceMatcher though.
          bf.train()
          
          matches = bf.match(testDes2)
          matches = sorted(matches, key = lambda x:x.distance)
          
          # Since, we have index of only one training image, 
          # all matches will have imgIdx set to 0.
          for i in range(len(matches)):
              print matches[i].imgIdx
          

          对于 bf.match 的 DMatch 输出,请参阅docs

          在此处查看完整示例:Opencv3.0 docs

          其他信息

          操作系统:Mac。
          Python:2.7.10.
          Opencv:3.0.0-dev [如果没记错,使用 brew 安装]。

          【讨论】:

          • 我将它用于多个图像。上面的代码是最简单的版本。您提供的示例代码适用于两个图像。我想将一个图像的描述符与多个图像的描述符列表进行比较。问题就发生在那里。
          • 对不起,我错过了。给我一些时间来看看这个问题。
          • 我想我在问这个类似的问题:stackoverflow.com/questions/37731908/…
          • 嗨,我面临同样的错误。一切似乎都很好。顺便说一句,BruteForceMatcher 并没有真正发生,因为它没有训练。 docs.opencv.org/2.4/modules/features2d/doc/…
          • 我也尝试过 FlannMatcher(因为我的项目使用了 FlannMatcher/C++),但遇到了这个 opencv 错误:github.com/opencv/opencv/issues/5667
          猜你喜欢
          • 1970-01-01
          • 2016-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多