如何在Python中使用OpenCV模块可视化描述符匹配
image-processing
opencv
python
8
0

我正在尝试将opencv与python一起使用。我在opencv 2.4的C ++版本中编写了一个与代码匹配的描述符(SIFT,SURF或ORB)。我想用python将此代码转换为opencv。我找到了一些有关如何在c ++中使用opencv函数的文档,但是在python中的许多opencv函数却找不到如何使用它们。这是我的python代码,当前的问题是我不知道如何在python中使用opencv c ++的“ drawMatches”。我找到了cv2.DRAW_MATCHES_FLAGS_DEFAULT,但我不知道如何使用它。这是我使用ORB描述符进行匹配的python代码:

im1 = cv2.imread(r'C:\boldt.jpg')
im2 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
im3 = cv2.imread(r'C:\boldt_resize50.jpg')
im4 = cv2.cvtColor(im3, cv2.COLOR_BGR2GRAY)

orbDetector2 = cv2.FeatureDetector_create("ORB")
orbDescriptorExtractor2 = cv2.DescriptorExtractor_create("ORB")
orbDetector4 = cv2.FeatureDetector_create("ORB")
orbDescriptorExtractor4 = cv2.DescriptorExtractor_create("ORB")

keypoints2 = orbDetector2.detect(im2)
(keypoints2, descriptors2) = orbDescriptorExtractor2.compute(im2,keypoints2)
keypoints4 = orbDetector4.detect(im4)
(keypoints4, descriptors4) = orbDescriptorExtractor4.compute(im4,keypoints4)
matcher = cv2.DescriptorMatcher_create('BruteForce-Hamming')
raw_matches = matcher.match(descriptors2, descriptors4)
img_matches = cv2.DRAW_MATCHES_FLAGS_DEFAULT(im2, keypoints2, im4, keypoints4, raw_matches)
cv2.namedWindow("Match")
cv2.imshow( "Match", img_matches);

该行的错误消息“ img_matches = cv2.DRAW_MATCHES_FLAGS_DEFAULT(im2,keypoints2,im4,keypoints4,raw_matches)”

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'long' object is not callable

我花了很多时间搜索文档和将opencv函数与python一起使用的示例。但是,我非常沮丧,因为在python中使用opencv函数的信息很少。如果有人可以教我如何在python中使用opencv模块的每个功能的文档,这将非常有帮助。感谢您的宝贵时间和帮助。

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

如错误消息所述,DRAW_MATCHES_FLAGS_DEFAULT的类型为“ long”。它是cv2模块定义的常数,而不是函数。不幸的是,您想要的函数“ drawMatches”仅存在于OpenCV的C ++接口中。

收藏
评论

我自己也写了一些东西,只使用OpenCV Python接口,而没有使用scipydrawMatches是OpenCV 3.0.0的一部分,而不是OpenCV 2的一部分,这是我当前正在使用的。即使我迟到了派对,这也是我自己的实现,它尽我所能模仿了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]

    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:cols1+cols2,:] = 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.destroyAllWindows()

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

在此处输入图片说明

在此处输入图片说明

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

import numpy as np
import cv2

img1 = cv2.imread('cameraman.png') # Original image
img2 = cv2.imread('cameraman_rot55.png') # Rotated image

# 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
drawMatches(img1, kp1, img2, kp2, matches[:10])

这是我得到的图像:

在此处输入图片说明

收藏
评论

您可以按照以下方式在Python中可视化功能匹配。注意使用scipy库。

# matching features of two images
import cv2
import sys
import scipy as sp

if len(sys.argv) < 3:
    print 'usage: %s img1 img2' % sys.argv[0]
    sys.exit(1)

img1_path = sys.argv[1]
img2_path = sys.argv[2]

img1 = cv2.imread(img1_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.CV_LOAD_IMAGE_GRAYSCALE)

detector = cv2.FeatureDetector_create("SURF")
descriptor = cv2.DescriptorExtractor_create("BRIEF")
matcher = cv2.DescriptorMatcher_create("BruteForce-Hamming")

# detect keypoints
kp1 = detector.detect(img1)
kp2 = detector.detect(img2)

print '#keypoints in image1: %d, image2: %d' % (len(kp1), len(kp2))

# descriptors
k1, d1 = descriptor.compute(img1, kp1)
k2, d2 = descriptor.compute(img2, kp2)

print '#keypoints in image1: %d, image2: %d' % (len(d1), len(d2))

# match the keypoints
matches = matcher.match(d1, d2)

# visualize the matches
print '#matches:', len(matches)
dist = [m.distance for m in matches]

print 'distance: min: %.3f' % min(dist)
print 'distance: mean: %.3f' % (sum(dist) / len(dist))
print 'distance: max: %.3f' % max(dist)

# threshold: half the mean
thres_dist = (sum(dist) / len(dist)) * 0.5

# keep only the reasonable matches
sel_matches = [m for m in matches if m.distance < thres_dist]

print '#selected matches:', len(sel_matches)

# #####################################
# visualization of the matches
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
view = sp.zeros((max(h1, h2), w1 + w2, 3), sp.uint8)
view[:h1, :w1, :] = img1  
view[:h2, w1:, :] = img2
view[:, :, 1] = view[:, :, 0]  
view[:, :, 2] = view[:, :, 0]

for m in sel_matches:
    # draw the keypoints
    # print m.queryIdx, m.trainIdx, m.distance
    color = tuple([sp.random.randint(0, 255) for _ in xrange(3)])
    cv2.line(view, (int(k1[m.queryIdx].pt[0]), int(k1[m.queryIdx].pt[1])) , (int(k2[m.trainIdx].pt[0] + w1), int(k2[m.trainIdx].pt[1])), color)


cv2.imshow("view", view)
cv2.waitKey()
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号