模块'对象没有属性'drawMatches'opencv python
computer-vision
image
image-processing
opencv
9
0

我只是在做一个OpenCV中特征检测的例子。该示例如下所示。它给我以下错误

模块”对象没有属性“ drawMatches”

我已经检查了OpenCV文档,但不确定为什么会出现此错误。有人知道为什么吗?

import numpy as np
import cv2
import matplotlib.pyplot as plt

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

# Initiate SIFT detector
orb = cv2.ORB()

# find the keypoints and descriptors with SIFT
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# Match descriptors.
matches = bf.match(des1,des2)

# Draw first 10 matches.
img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], flags=2)

plt.imshow(img3),plt.show()

错误:

Traceback (most recent call last):
File "match.py", line 22, in <module>
img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], flags=2)
AttributeError: 'module' object has no attribute 'drawMatches'
参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

drawMatches函数不是Python接口的一部分。
正如您在docs中看到的那样,目前仅针对C++进行了定义。

摘录自文档:

 C++: void drawMatches(const Mat& img1, const vector<KeyPoint>& keypoints1, const Mat& img2, const vector<KeyPoint>& keypoints2, const vector<DMatch>& matches1to2, Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT )
 C++: void drawMatches(const Mat& img1, const vector<KeyPoint>& keypoints1, const Mat& img2, const vector<KeyPoint>& keypoints2, const vector<vector<DMatch>>& matches1to2, Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const vector<vector<char>>& matchesMask=vector<vector<char> >(), int flags=DrawMatchesFlags::DEFAULT )

如果该函数具有Python接口,则会发现以下内容:

 Python: cv2.drawMatches(img1, keypoints1, [...]) 

编辑

实际上,有一个提交在5个月前引入了此功能。但是,官方文档中尚未(尚未)。
确保您使用的是最新的OpenCV版本(2.4.7)。为了完整起见,OpenCV 3.0.0的Functions接口看起来像这样

cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2[, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]]) → outImg
收藏
评论

我知道这个问题的答案是正确的,但是如果您使用的是OpenCV 2.4.8,而不是3.0(-dev),一种解决方法是使用opencv\sources\samples\python2\find_obj包含的样本中的某些功能opencv\sources\samples\python2\find_obj

import cv2
from find_obj import filter_matches,explore_match

img1 = cv2.imread('../c/box.png',0)          # queryImage
img2 = cv2.imread('../c/box_in_scene.png',0) # trainImage

# Initiate SIFT detector
orb = cv2.ORB()

# find the keypoints and descriptors with SIFT
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING)#, crossCheck=True)

matches = bf.knnMatch(des1, trainDescriptors = des2, k = 2)
p1, p2, kp_pairs = filter_matches(kp1, kp2, matches)
explore_match('find_obj', img1,img2,kp_pairs)#cv2 shows image

cv2.waitKey()
cv2.destroyAllWindows()

这是输出图像:

在此处输入图片说明

收藏
评论

我也参加聚会很晚,但是我为Mac OS X安装了OpenCV 2.4.9,而我的发行版中不存在drawMatches函数。我也尝试过使用find_obj的第二种方法,这对我也不起作用。因此,我决定编写自己的实现,以最大的能力模仿drawMatches ,这就是我制作的。

我提供了自己的图像,其中一个是摄影师的图像,另一个是相同的图像,但是逆时针旋转了55度。

我写的基础知识是分配一个输出RGB图像,其中行数是两个图像的最大值,以适应将两个图像都放置在输出图像中,而列只是两个列的总和。请注意,我假设两个图像都是灰度图像。

我将每个图像放置在它们对应的位置,然后遍历所有匹配的关键点。我提取了两个图像之间匹配的关键点,然后提取了它们的(x,y)坐标。我在每个检测到的位置绘制圆,然后绘制一条将这些圆连接在一起的线。

请记住,第二张图像中检测到的关键点是相对于其自身的坐标系的。如果要将其放置在最终的输出图像中,则需要使列坐标相对于第一个图像偏移列数,以使列坐标相对于输出图像的坐标系。

无需再费周折:

import numpy as np
import cv2

def drawMatches(img1, kp1, img2, kp2, matches):
    """
    My own implementation of cv2.drawMatches as OpenCV 2.4.9
    does not have this function available but it's supported in
    OpenCV 3.0.0

    This function takes in two images with their associated 
    keypoints, as well as a list of DMatch data structure (matches) 
    that contains which keypoints matched in which images.

    An image will be produced where a montage is shown with
    the first image followed by the second image beside it.

    Keypoints are delineated with circles, while lines are connected
    between matching keypoints.

    img1,img2 - Grayscale images
    kp1,kp2 - Detected list of keypoints through any of the OpenCV keypoint 
              detection algorithms
    matches - A list of matches of corresponding keypoints through any
              OpenCV keypoint matching algorithm
    """

    # Create a new output image that concatenates the two images together
    # (a.k.a) a montage
    rows1 = img1.shape[0]
    cols1 = img1.shape[1]
    rows2 = img2.shape[0]
    cols2 = img2.shape[1]

    # Create the output image
    # The rows of the output are the largest between the two images
    # and the columns are simply the sum of the two together
    # The intent is to make this a colour image, so make this 3 channels
    out = np.zeros((max([rows1,rows2]),cols1+cols2,3), dtype='uint8')

    # Place the first image to the left
    out[:rows1,:cols1] = np.dstack([img1, img1, img1])

    # Place the next image to the right of it
    out[:rows2,cols1:] = np.dstack([img2, img2, img2])

    # For each pair of points we have between both images
    # draw circles, then connect a line between them
    for mat in matches:

        # Get the matching keypoints for each of the images
        img1_idx = mat.queryIdx
        img2_idx = mat.trainIdx

        # x - columns
        # y - rows
        (x1,y1) = kp1[img1_idx].pt
        (x2,y2) = kp2[img2_idx].pt

        # Draw a small circle at both co-ordinates
        # radius 4
        # colour blue
        # thickness = 1
        cv2.circle(out, (int(x1),int(y1)), 4, (255, 0, 0), 1)   
        cv2.circle(out, (int(x2)+cols1,int(y2)), 4, (255, 0, 0), 1)

        # Draw a line in between the two points
        # thickness = 1
        # colour blue
        cv2.line(out, (int(x1),int(y1)), (int(x2)+cols1,int(y2)), (255,0,0), 1)


    # Show the image
    cv2.imshow('Matched Features', out)
    cv2.waitKey(0)
    cv2.destroyWindow('Matched Features')

    # Also return the image if you'd like a copy
    return out

为了说明这一点,下面是我使用的两个图像:

摄影师图像

旋转的摄影师图像

我使用OpenCV的ORB检测器检测关键点,并使用归一化的汉明距离作为相似性的距离度量,因为这是一个二进制描述符。因此:

import numpy as np
import cv2

img1 = cv2.imread('cameraman.png', 0) # Original image - ensure grayscale
img2 = cv2.imread('cameraman_rot55.png', 0) # Rotated image - ensure grayscale

# Create ORB detector with 1000 keypoints with a scaling pyramid factor
# of 1.2
orb = cv2.ORB(1000, 1.2)

# Detect keypoints of original image
(kp1,des1) = orb.detectAndCompute(img1, None)

# Detect keypoints of rotated image
(kp2,des2) = orb.detectAndCompute(img2, None)

# Create matcher
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# Do matching
matches = bf.match(des1,des2)

# Sort the matches based on distance.  Least distance
# is better
matches = sorted(matches, key=lambda val: val.distance)

# Show only the top 10 matches - also save a copy for use later
out = drawMatches(img1, kp1, img2, kp2, matches[:10])

这是我得到的图像:

匹配功能


knnMatchcv2.BFMatcher

我想在上面的代码中做一个记录,前提是您假设匹配项出现在1D列表中。但是,如果你决定使用knnMatch从方法cv2.BFMatcher例如,什么是返回是一个列表的列表。具体来说,给定img1的描述符des1img2的描述符des2 ,从knnMatch返回的列表中的每个元素都是来自knnMatchk匹配项的另一个列表,它们与des2中的每个描述符des1 。因此,来自knnMatch输出的第一个元素是来自des2k匹配项的列表,这些匹配des2最接近在des1找到的第一个描述符。 knnMatch输出的第二个元素是来自des2k匹配的列表,这些匹配最接近在des1找到的第二个描述符,依此类推。

为了充分利用knnMatch必须将要匹配的邻居总数限制为k=2 。原因是因为您要使用至少两个匹配点来验证比赛的质量,并且如果质量足够好,则需要使用这些点来绘制比赛并在屏幕上显示。您可以使用一个非常简单的比率测试(贷记给David Lowe )来确保从des2的第一个匹配点到des2中的描述符的距离与从des2的第二个匹配点相比des1一段距离。因此,要将knnMatch返回的内容knnMatch为我上面编写的代码所需的内容,请遍历匹配项,使用上述比率测试并检查是否通过。如果是这样,请将第一个匹配的关键点添加到新列表中。

假设您像声明BFMatcher实例之前一样创建了所有变量,那么现在您可以这样做,以使knnMatch方法适合使用drawMatches

# Create matcher
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# Perform KNN matching
matches = bf.knnMatch(des1, des2, k=2)

# Apply ratio test
good = []
for m,n in matches:
    if m.distance < 0.75*n.distance:
       # Add first matched keypoint to list
       # if ratio test passes
       good.append(m)

# Or do a list comprehension
#good = [m for (m,n) in matches if m.distance < 0.75*n.distance]

# Now perform drawMatches
out = drawMatches(img1, kp1, img2, kp2, good)

我想将上述修改归因于用户@ryanmeasel ,发现这些修改的答案在他的帖子中: OpenCV Python:没有drawMatchesknn函数

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题