如何根据与其他匹配的距离来过滤外围匹配?

时间:2018-01-09 02:52:57

标签: python opencv feature-detection

如何根据与其他匹配的距离来过滤外围匹配?

我试图在大图像中找到一个类似的小图像。模板匹配似乎没有很好地处理微小差异所以我正在尝试功能匹配方法。在经过多次修补之后,我可以让它在匹配方面做得相当不错,但异常值会导致问题。我的代码中有单应性,这似乎没有必要,但它对获得正确的匹配有积极的影响。还有其他一些更有效的选择吗?

最终,我想找到匹配项(见图1)过滤掉不与较小图像对齐的关键点,(见图2)确定较大图像内的较小图像的边界,然后找到该边界中心的坐标。

https://ibb.co/c0xC6m

https://ibb.co/mjSZK6

其他图片:

要搜索的图片:(由于错误说我的代码格式不正确,因此它们不会被格式化为图像。)

https://i.stack.imgur.com/VyVAv.png

未经编辑的世界地图:

https://i.stack.imgur.com/5u3FN.png

原始搜索结果:

https://i.stack.imgur.com/VrX63.png

import cv2
import numpy as np
from matplotlib import pyplot as plt
import remove_map_dots as rm

MIN_MATCH_COUNT = 0

img1 = rm.removemapdots()
img2 = cv2.imread('worldmapsnippet1.png')

surf = cv2.xfeatures2d.SURF_create(hessianThreshold=10, upright=True, extended=True)

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

FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)

flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)

good = []
for m, n in matches:
    good.append(m)

if len(good)>MIN_MATCH_COUNT:
    src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
    dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 10) #RANSAC LMEDS RHO
    matchesMask = mask.ravel().tolist()

    h, w, _ = img1.shape
    pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
    dst = cv2.perspectiveTransform(pts, M)

    img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)
    print(h)
    print(w)
else:
    print("Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT))
    matchesMask = None

draw_params = dict(matchColor = (0, 255, 0), # draw matches in green color
                   singlePointColor = None,
                   matchesMask = matchesMask, # draw only inliers
                   flags = 2)

img3 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)
plt.imshow(img3), plt.show()

1 个答案:

答案 0 :(得分:1)

正如评论中所讨论的,模板匹配方法的问题确实是模板和图像的大小。模板大于模板的相应区域,给出错误的读数。简单的解决方案是调整模板大小,使区域与地图中正确大小的区域完全对应。

功能匹配也可以用于此,但模板匹配在这里更有意义。两个图像之间的唯一区别是翻译,模板匹配可以很好地处理。

通过模板匹配,它也很容易做出很好的优化,例如将搜索区域缩小到地图中最后找到的位置。您还可以通过查看最后找到的几个位置来创建阈值 - 这样您就可以知道何时找不到正确的位置并需要重新查看整个地图。例如,如果你传送它不会在最后一个位置,所以你需要翻阅整个图像。但是你知道你最后(比如说)5帧的你的SSD图像的min是[100,150,130,180,100]所以如果你的下一帧不同(比如min在你所在的地区是500)然后你再次检查整个地图并找到最小值,并再次开始跟踪该地区。