如何计算高分辨率图像之间的匹配特征?

nic*_*ine 6 python opencv feature-detection

我正在尝试在我使用 OpenCV 检测到的两个图像之间匹配 SIFT 特征:

sift = cv2.xfeatures2d.SIFT_create()
kp, desc = sift.detectAndCompute(img, None)
Run Code Online (Sandbox Code Playgroud)

这两个图像似乎都包含许多特征,每个大约 15,000 个,用绿点显示。

在此处输入图片说明 在此处输入图片说明

但是在匹配它们之后,我只保留了 87 个,有些是异常值。

在此处输入图片说明

我试图弄清楚我是否做错了什么。我匹配两个图像的代码是:

def match(this_filename, this_desc, this_kp, othr_filename, othr_desc, othr_kp):

    E_RANSAC_PROB = 0.999
    F_RANSAC_PROB = 0.999
    E_PROJ_ERROR = 15.0
    F_PROJ_ERROR = 15.0
    LOWE_RATIO = 0.9
    # FLANN Matcher
    # FLANN_INDEX_KDTREE = 1 # 1? https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_matcher/py_matcher.html#basics-of-brute-force-matcher
    # index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    # search_params = dict(checks=50)   # or pass empty dictionary
    # flann = cv2.FlannBasedMatcher(index_params, search_params)
    # matcherij = flann.knnMatch(this_desc, othr_desc, k=2)
    # matcherji = flann.knnMatch(othr_desc, this_desc, k=2)

    # BF Matcher
    this_matches = {}
    othr_matches = {}


    bf = cv2.BFMatcher()
    matcherij = bf.knnMatch(this_desc, othr_desc, k=2)
    matcherji = bf.knnMatch(othr_desc, this_desc, k=2)

    matchesij = []
    matchesji = []

    for i,(m,n) in enumerate(matcherij):
        if m.distance < LOWE_RATIO*n.distance:
            matchesij.append((m.queryIdx, m.trainIdx))

    for i,(m,n) in enumerate(matcherji):
        if m.distance < LOWE_RATIO*n.distance:
            matchesji.append((m.trainIdx, m.queryIdx))


    # Make sure matches are symmetric
    symmetric = set(matchesij).intersection(set(matchesji))
    symmetric = list(symmetric)

    this_matches[othr_filename] = [ (a, b) for (a, b) in symmetric ]
    othr_matches[this_filename] = [ (b, a) for (a, b) in symmetric ]

    src = np.array([ this_kp[index[0]].pt for index in this_matches[othr_filename] ])
    dst = np.array([ othr_kp[index[1]].pt for index in this_matches[othr_filename] ])

    if len(this_matches[othr_filename]) == 0:
        print("no symmetric matches")
        return 0

    # retain inliers that fit x.F.xT == 0
    F, inliers = cv2.findFundamentalMat(src, dst, cv2.FM_RANSAC, F_PROJ_ERROR, F_RANSAC_PROB)

    if F is None or inliers is None:
        print("no F matrix estimated")
        return 0

    inliers = inliers.ravel()

    this_matches[othr_filename] = [ this_matches[othr_filename][x] for x in range(len(inliers)) if inliers[x] ]
    othr_matches[this_filename] = [ othr_matches[this_filename][x] for x in range(len(inliers)) if inliers[x] ]

    return this_matches, othr_matches, inliers.sum()

Run Code Online (Sandbox Code Playgroud)

这是两张原始图片:https : //www.dropbox.com/s/pvi247be2ds0noc/images.zip?dl=0

Mar*_*ari 3

我不明白为什么在代码中您要过滤掉距离大于 0.9 ( LOWE_RATIO) 的匹配项。点已经匹配。通过过滤掉这些点,您可以将匹配的特征从大约 15000 个减少到 839 个,然后内点检测器仅将其中的 87 个识别为内点。


此外,使用下面使用 ORB(Oriented FAST 和 Rotated Brief)的代码,我得到了 500 个关键点和 158 个有意义的匹配。我相信它可能是 SIFT 的一个很好的替代方案:

import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('IMG_1598.png', cv2.COLOR_BGR2GRAY)  # queryImage
img2 = cv2.imread('IMG_1596.png', cv2.COLOR_BGR2GRAY)  # trainImage
# Initiate  detector
orb = cv2.ORB_create()

# find the keypoints and descriptors 
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)

# Sort them in the order of their distance.
matches = sorted(matches, key=lambda x: x.distance)
# Draw first 10 matches.
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=2)

plt.imshow(img3)
plt.show()
plt.savefig('foo.png')
Run Code Online (Sandbox Code Playgroud)

比赛是这样的: 在此输入图像描述