Python 如何根据与其他匹配的接近程度筛选外围匹配?

Python 如何根据与其他匹配的接近程度筛选外围匹配?,python,opencv,feature-detection,Python,Opencv,Feature Detection,如何根据与其他匹配的接近程度筛选外围匹配 我试图在一个大图像中找到一个小的,相似的图像。模板匹配似乎不能很好地处理细微的差异,所以我正在尝试功能匹配方法。经过多次修补,我可以让它在匹配方面做得相当不错,但异常值会导致问题。我的代码中有单应性,这似乎不是必需的,但它对获得正确的匹配有积极的影响。还有其他更有效的替代方案吗 最后,我想找到匹配项,(见图1)过滤掉与较小图像不对齐的关键点,(见图2)确定较大图像中较小图像的边界,然后找到该边界中心的坐标 其他图像: 要搜索的图像:(它们没有格式化为

如何根据与其他匹配的接近程度筛选外围匹配

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

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

其他图像:

要搜索的图像:(它们没有格式化为图像,因为有一个错误说我的代码没有格式化。)

未经编辑的世界地图:

原始搜索结果:


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

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


通过模板匹配,还可以很容易地进行优化,比如将搜索区域缩小到地图中最后一个找到的位置附近。您还可以通过查看最后几个找到的位置来创建一个阈值,这样您就可以知道何时找不到正确的位置,需要重新查看整个地图。例如,如果你传送它,它不会在最后一个位置附近,所以你需要浏览整个图像。但是你知道你的SSD图像在最后(比如)5帧中的
min
是[100150130180100],因此如果你的下一帧有很大的不同(比如你所在区域的
min
是500),那么你可以再次检查整个地图,找到min,然后再次开始跟踪该区域。

findHomography()
使用
RANSAC
选项将为您过滤出异常值。这就是RANSAC的作用。您仍然在绘制所有关键点,即使在查找单应性时某些关键点已被过滤掉。
matchesMask
将告诉您是否使用了
良好的
匹配项。而且两张图像都是相同的。
findHomography()
确实可能会增加一点透视变换,但很少。一般来说,我不会太担心这个问题,但是由于这个例子非常简单,您可以尝试自己过滤异常值,并使用它来只查找平移和旋转(或者是
fullAffine=True
的仿射扭曲。但是请注意,在这种情况下,RANSAC不是一个选项,它只是使用最小二乘法来估计变换。RANSAC不是一个完美的过滤器。它采用四个匹配的随机样本,使用这四个点的最小二乘法计算单应性,然后根据h对点进行评分单应性工作得很好。然后它重复这个过程,直到点都是内联线的概率非常高。但是它没有通过所有可能的单应性(这在计算上太昂贵了),所以它并不总是能完美过滤。你能在没有标记的情况下发布两张原始图像吗?哦!我只是浏览了源代码,我看到了
estimategidtransform()
也使用RANSAC。我不知道。只有当RANSAC算法在分配的迭代次数内不收敛时,结果才会设置为
None
。对于您最初的问题:您感兴趣的主要内容是模板的中心,对吗?这就是我想的,很酷的项目!模板匹配让位于m从这个意义上讲,你关心的是什么“微小的差异”呢?如果有差异,你不需要精确的匹配——最小位置应该足够好用。特征匹配不是你想用的——它只关注特征位置周围的微小图像块,所以重复性不好e模式。
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()