opencv - 模糊模板匹配?

标签 opencv computer-vision

我正在努力了解 CV 的基础知识。最初让我感兴趣的是模板匹配(在与 CV 无关的 Pycon 演讲中提到过),所以我想我应该从这里开始。

我从这张图片开始:

Scene from SMB3

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

The Plumber

我理解围绕图像滑动模板以查看最合适的概念,并且按照教程,我能够使用以下代码找到马里奥:

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()

到目前为止一切顺利,但后来我意识到这是非常脆弱的。它只会找到具有特定背景并显示特定动画帧的马里奥。

所以我很好奇,考虑到马里奥将始终具有相同的马里奥风格属性(大小、颜色),是否有一种技术可以让我找到他,无论他的当前帧是静止的还是其中之一各种运行周期 Sprite ?有点像您可以对字符串执行的模糊匹配,但适用于图像。

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

另一个问题是从模板中删除背景。也许这会帮助 MatchTemplate 函数找到马里奥,即使他与模板不完全匹配?截至目前,我不完全确定它是如何工作的(我看到 MatchTemplate 中有一个掩码参数,但我必须进一步调查)

我的主要问题是,模板匹配是否是检测基本相同但有所不同(例如他走路时)的图像的方法,还是我应该研究另一种技术?

更新:

尝试匹配其他马里奥


根据 mmgp 的建议,它应该可以用于匹配其他事物,我进行了几次测试。

我用这个作为模板来匹配:

Super mario

然后拍了几个屏幕截图来测试匹配。

首先,我成功找到了马里奥,并得到了最大值 1。

enter image description here

但是,试图找到跳跃的马里奥会导致完全失败。

Misfire

现在承认,模板中的马里奥和场景中的马里奥面向相反的方向,并且是不同的动画帧,但我认为它们仍然比任何东西都更匹配很多图像中的其他部分 - 如果仅针对颜色。但它将平台定位为与模板最接近的匹配。

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

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

enter image description here

但奇怪的是,我得到了与跳跃马里奥图像相同的精确结果——直到相似度值:0.728053808212。马里奥在画面中与他在画面中一样准确。

真奇怪!我不知道底层算法的实际细节,但我想,从标准偏差的角度来看,场景中至少与模板马里奥西装中的红色匹配的框会比蓝色更接近平均距离平台对吧?因此,它甚至不在我期望的一般区域,这更加令人困惑。

我猜这是我这边的用户错误,或者可能只是一个误解。

为什么有类似马里奥的场景与完全没有马里奥的场景一样匹配?

最佳答案

没有一种方法是万无一失的,但模板匹配确实很有可能在那里发挥作用。它可能需要一些预处理,并且在有更大的样本(例如短视频)来演示可能的问题之前,尝试更高级的方法没有多大意义,因为一些库为您实现了它们——尤其是如果您不知道它们应该在哪些条件下工作。

例如,这是我使用模板匹配(红色矩形)得到的结果——它们都使用模板 http://i.stack.imgur.com/EYs9B.png ,甚至最后一个:

enter image description here enter image description here enter image description here enter image description here

为了实现这一点,我首先只考虑模板和输入图像的红色 channel 。由此我们很容易计算出内部形态梯度,然后才进行匹配。为了在马里奥不存在时不得到矩形,需要为匹配设置一个最小阈值。这是经过这两次转换后的模板和图像之一:

enter image description here enter image description here

下面是一些示例代码来实现这一点:

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)

我预计它会在更多不同的情况下失败,但有几个简单的调整需要完成。

关于opencv - 模糊模板匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14792103/

相关文章:

machine-learning - 在caffe prototxt 文件中。 TRAIN 和 TEST 阶段做什么?

computer-vision - 如何计算旋转矩阵之间的差异?

c++ - OpenCV 保存 CV_32FC1 图像

java - 在android中使用opencv检测玩具车后面

python,windows 7,无法导入cv2

c++ - 计算平均值 : different result for masked image vs ROI

c++ - OpenCV imread 不起作用

c++ - cv::absdiff() 使用什么方法/算法?

python - 使用图像的局部平均颜色来减少闪电差异

opencv - 使用 Mathematica 的计算机视觉