OpenCV中的BFMatcher匹配出现错误

20

我正在使用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

错误与帖子相似。所给出的解释是不完整和不充分的。我想知道如何解决这个问题。我也使用了ORB描述符,并用NORM_HAMMING距离的BFMatcher。但错误仍然存在。 非常感谢您的任何帮助。

我使用的两张图片为:

box.png

box.png

box_in_scene.png

box_in_scene.png

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


那么.detectAndCompute是从OpenCV 3x及以上版本开始出现的吗?我正在使用2.4版本,但它显示“找不到模块对象”... - alisa
这取决于OpenCV的版本。请遵循2.4或3.x中的任一版本。 - motiur
5个回答

13

搜索两张图片之间的描述符,请使用:

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输出,请参考文档

查看完整的示例请点击这里:Opencv3.0文档

其他信息

操作系统:Mac。
Python版本:2.7.10。
Opencv版本:3.0.0-dev [如果记得正确,是通过brew安装的]。


我正在使用它来处理多张图片。上面的代码是最简单的版本。你给出的示例代码对于两张图片可以正常工作。但是当我想要将一张图片的描述符与多张图片的描述符列表进行比较时,问题就出现了。 - motiur
我认为我在提出类似的问题:http://stackoverflow.com/questions/37731908/opencv2-batchdistance-error-215-when-looping-through-images-while-individual-co?rq=1 - motiur
嗨,我遇到了相同的错误。一切看起来都没问题。顺便说一下,BruteForceMatcher并不像它表面上那样有效,因为它没有进行训练。您可以在此链接找到更多关于DescriptorMatcher的信息:http://docs.opencv.org/2.4/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html#descriptormatcher-train - saurabheights
我也尝试了FlannMatcher(因为我的项目使用FlannMatcher/C++),但遇到了这个OpenCV的bug:https://github.com/opencv/opencv/issues/5667 - saurabheights
让我们在聊天中继续这个讨论 - saurabheights
显示剩余3条评论

6
我遇到了相同的错误。但在我的情况下,是因为我在cv2.BFMatcher_create中使用了带有cv2.NORM_HAMMING度量的SIFT。将度量更改为cv2.NORM_L1解决了这个问题。
引用BFMatcher文档:
“normType” - “NORM_L1”,“NORM_L2”,“NORM_HAMMING”,“NORM_HAMMING2”之一。对于SIFT和SURF描述符,L1和L2范数是更好的选择,ORB、BRISK和BRIEF应使用NORM_HAMMING,当WTA_K==3或4时,ORB应使用NORM_HAMMING2(请参见ORB::ORB构造函数描述)。

6

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


6

编辑:使用的版本为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. Creating matcher object

    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 capturing and processing frames

    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)
    

0
在我的情况下,使用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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接