Opencv 模糊模板匹配?

Opencv 模糊模板匹配?,opencv,computer-vision,Opencv,Computer Vision,我正试图把我的头脑集中在简历的基本知识上。最初让我感兴趣的是模板匹配(在Pycon的一次与CV无关的演讲中提到过),所以我想从这里开始 我从这张图片开始: 我想从中找出马里奥。所以我把他删掉了: 我理解在图像周围滑动模板以查看最佳匹配的概念,并且根据教程,我能够使用以下代码找到mario: def match_template(img, template): s = time.time() img_size = cv.GetSize(img) template_siz

我正试图把我的头脑集中在简历的基本知识上。最初让我感兴趣的是模板匹配(在Pycon的一次与CV无关的演讲中提到过),所以我想从这里开始

我从这张图片开始:

我想从中找出马里奥。所以我把他删掉了:

我理解在图像周围滑动模板以查看最佳匹配的概念,并且根据教程,我能够使用以下代码找到mario:

def match_template(img, template):
    s = time.time()
    img_size = cv.GetSize(img)
    template_size = cv.GetSize(template)

    img_result = cv.CreateImage((img_size[0] - template_size[0] + 1, 
                            img_size[1] - template_size[1] + 1), cv.IPL_DEPTH_32F, 1)
    cv.Zero(img_result)

    cv.MatchTemplate(img, template, img_result, cv.CV_TM_CCORR_NORMED)
    min_val, max_val, min_loc, max_loc = cv.MinMaxLoc(img_result)
    # inspect.getargspec(cv.MinMaxLoc)
    print min_val
    print max_val 
    print min_loc 
    print max_loc
    cv.Rectangle(img, max_loc, (max_loc[0] + template.width, max_loc[1] + template.height), cv.Scalar(120.), 2)
    print time.time() - s
    cv.NamedWindow("Result")
    cv.ShowImage("Result", img)
    cv.WaitKey(0)
    cv.DestroyAllWindows()
到目前为止还不错,但后来我意识到这是难以置信的脆弱。它只会在特定的背景下找到马里奥,并显示特定的动画帧

所以我很好奇,考虑到马里奥总是有着同样的马里奥气质(大小、颜色),有没有一种技术可以让我找到他,不管他现在的身体是静止的,还是各种跑步循环精灵中的一个?有点像模糊匹配,你可以在字符串上做,但图像

也许因为他是唯一的红色物体,有没有一种方法可以简单地跟踪红色像素

另一个问题是从模板中删除背景。也许这会帮助MatchTemplate函数找到Mario,即使他与tempate不完全匹配?到目前为止,我还不完全确定这将如何工作(我看到MatchTemplate中有一个掩码参数,但我必须进一步研究)

我的主要问题是,模板匹配是否是检测基本相同但变化(比如他走路时)的图像的方法,还是我应该研究其他技术

更新: 尝试匹配其他马里奥人
根据mmgp的建议,它应该适用于匹配其他东西,我运行了两个测试

我使用此作为模板来匹配:

然后拍了几张屏幕截图来测试匹配情况

首先,我成功地找到了Mario,并获得了最大值1

然而,试图找到跳跃马里奥的结果是完全失火

现在可以肯定的是,模板中的马里奥和场景中的马里奥面向相反的方向,并且是不同的动画帧,但我认为它们仍然比图像中的任何其他帧匹配得多——如果仅仅是颜色的话。但它将平台定位为与模板最匹配的平台

请注意,此项的最大值为
0.728053808212

接下来,我尝试了一个没有马里奥的场景,看看会发生什么

但奇怪的是,我得到了准确的结果,就像跳转马里奥的图像一样——一直到相似度值:
0.728053808212
。马里奥在照片中和他不在照片中一样准确

真奇怪!我不知道底层算法的实际细节,但我可以想象,从标准偏差的角度来看,场景中至少与Mario套装中红色模板匹配的框会比蓝色平台更接近平均距离,对吗?所以,特别令人困惑的是,它甚至不在我所期望的一般领域

我猜这是我这边的用户错误,或者只是一个误会


为什么有类似马里奥的场景与没有马里奥的场景具有同样多的匹配?

模板匹配并不总是给出很好的结果。您应该研究关键点匹配

步骤1:找到关键点 让我们假设您成功地删除了Mario或获得了Mario的ROI图像。将此图像作为模板图像。现在,在主图像和模板中查找关键点。现在有两组关键点。一个用于图像,另一个用于Mario(模板)

您可以使用,具体取决于您的首选项

[编辑]:

这就是我用这种方法得到的基于SIFT和flann的knn匹配。我还没有完成边界框部分

由于模板非常小,所以SIFT和SURF不会给出很多关键点。但要获得大量的特征点,可以尝试使用Harris角点检测器。我在图片上应用了哈里斯角,我在马里奥身上得到了很好的分数

步骤2:匹配关键点 如果您使用了SIFT或SURF,那么您将拥有图像和模板的描述符。使用KNN或其他有效的匹配算法匹配这些关键点。如果您使用的是OpenCV,我建议您查看基于法兰的matcher。匹配关键点后,您可能希望过滤掉不正确的匹配。您可以通过K-最近邻来实现这一点,并且根据最近匹配的距离,您可以进一步过滤掉关键点。您可以使用向前向后错误进一步筛选匹配项

前后误差估计:
  • 将模板关键点与图像关键点匹配这将为您提供一组匹配
  • 将图像关键点与模板关键点匹配。这将为您提供另一组匹配项
  • 这两个集合的公共集合将过滤掉不正确的匹配
  • [编辑]: 如果您使用的是哈里斯角点检测器,您将只获得点,而不是关键点。您可以将它们转换为关键点,也可以编写自己的暴力数学。没那么难

    步骤3:估算 过滤关键点后,在对象附近会有一组关键点(在本例中为Mario)和几个分散的关键点。要消除这些分散的关键点,可以使用集群。DBSCAN群集将帮助您获得良好的点群集

    步骤4:边界框估计 现在您有了一组关键点。使用k-means,您应该尝试找到集群的中心。一旦获得簇的中心,就可以估计边界框

    我希望这有帮助

    [编辑]

    尝试使用哈里斯角点匹配点。在过滤完Harris角点后,我使用蛮力方法
    import sys
    import cv2
    import numpy
    
    img = cv2.imread(sys.argv[1])
    
    img2 = img[:,:,2]
    img2 = img2 - cv2.erode(img2, None)
    template = cv2.imread(sys.argv[2])[:,:,2]
    template = template - cv2.erode(template, None)
    
    ccnorm = cv2.matchTemplate(img2, template, cv2.TM_CCORR_NORMED)
    print ccnorm.max()
    loc = numpy.where(ccnorm == ccnorm.max())
    threshold = 0.4
    th, tw = template.shape[:2]
    for pt in zip(*loc[::-1]):
        if ccnorm[pt[::-1]] < threshold:
            continue
        cv2.rectangle(img, pt, (pt[0] + tw, pt[1] + th),
                (0, 0, 255), 2)
    
    cv2.imwrite(sys.argv[2], img)