如何使用OpenCV和Python的掩码(或透明度)在图像中查找模板?

如何使用OpenCV和Python的掩码(或透明度)在图像中查找模板?,python,opencv,image-processing,Python,Opencv,Image Processing,假设我们正在寻找此模板: 我们模板的角是透明的,因此背景会有所不同,如下所示: 假设我们可以在模板中使用以下掩码: 很容易找到它 我尝试过的: 我尝试过matchTemplate,但它不支持遮罩(据我所知),在模板中使用alpha通道(透明度)无法实现这一点,因为它比较alpha通道而不是忽略这些像素 我还研究了“感兴趣区域”,我认为这将是解决方案,但有了它,您只能指定一个矩形区域。我甚至不确定它在模板上是否有效 我相信这可以通过编写自己的算法来实现,但我希望这可以通过。标准OpenC

假设我们正在寻找此模板:

我们模板的角是透明的,因此背景会有所不同,如下所示:

假设我们可以在模板中使用以下掩码:

很容易找到它

我尝试过的:

我尝试过
matchTemplate
,但它不支持遮罩(据我所知),在模板中使用alpha通道(透明度)无法实现这一点,因为它比较alpha通道而不是忽略这些像素

我还研究了“感兴趣区域”,我认为这将是解决方案,但有了它,您只能指定一个矩形区域。我甚至不确定它在模板上是否有效

我相信这可以通过编写自己的算法来实现,但我希望这可以通过。标准OpenCV,避免重新发明轮子。更不用说,它很可能比我自己的更为优化


那么,我怎样才能用OpenCV+Python做这样的事情呢?

您的问题的一个答案是。使用模板作为内核并过滤图像

目标垫子将在模板所在的位置有密集的明亮区域。您必须对结果进行聚类(例如平均偏移)

这样,您将得到一个非常简单的广义Hough变换的实现,或者一个.

,它工作得非常好

compare -verbose -dissimilarity-threshold 0.1 -subimage-search subimage bigimage
我用它来发现和模糊一些产品的水印。不要问


(有时你必须做你必须做的事。)

我需要做的一件事是用白噪声填充“遮罩”区域。然后,在查找匹配项时,它会被有效地清除掉相关性。否则,正如我猜想的那样,我会在遮罩区域得到错误匹配。

这可以仅使用
匹配模板
功能实现,但需要一些解决方法

让我们分析默认指标(
CV_TM_SQDIFF_NORMED
)。根据 默认指标如下所示

R(x,y)=和(I(x+x',y+y')-T(x',y')^2

其中,
I
是图像矩阵,
T
是模板,
R
是结果矩阵。对模板坐标
x'
y'
进行求和

因此,让我们通过插入权重矩阵
W
,来更改此度量,该矩阵的维度与
T

Q(x,y)=和W(x',y')*(I(x+x',y+y')-T(x',y'))^2

在这种情况下,通过设置
W(x',y')=0
,实际上可以忽略像素。那么,如何制定这样的指标呢?用简单的数学:

Q(x, y) = sum W(x', y')*(I(x+x', y+y') - T(x', y'))^2
        = sum W(x', y')*(I(x+x', y+y')^2 - 2*I(x+x', y+y')*T(x', y') + T(x', y')^2)
        = sum {W(x', y')*I(x+x', y+y')^2} - sum{W(x', y')*2*I(x+x', y+y')*T(x', y')} + sum{W(x', y')*T(x', y')^2)}
因此,我们将
Q
度量划分为三个独立的和。所有这些总数都可以计算出来 使用
matchTemplate
功能(使用
CV\u TM\u CCORR
方法)。即

最后一个元素是常数,因此,对于最小化,它没有任何影响。另一方面,看看我们的模板是否有完美的匹配(如果Q接近于零),这仍然可能对我有用。尽管如此,对于最后一个元素,我们实际上不需要
matchTemplate
函数,因为它可以直接计算

最后的伪代码如下所示:

result = matchTemplate(I^2, W, method=2) - matchTemplate(I, 2*W*T, method=2) + as.scalar(sum(W*T^2))
它真的按照定义做吗?数学上是的。 实际上,存在一些小的舍入误差,因为
matchTemplate
函数 适用于32位浮点,但我相信这不是什么大问题

请注意,您可以对
matchTemplate
提供的任何度量进行范围分析和加权等价

这对我来说确实有效。很抱歉,我没有给出实际代码。我在R工作,所以 我没有Python的代码。但这个想法很简单


我希望这会有所帮助。

Imagemagick 7.0.3.9现在具有屏蔽比较功能,因此您可以限制模板匹配区域。看

另外,我看到OpenCV 3.0现在有屏蔽模板匹配。看


但是,它仅适用于方法==CV_TM_SQDIFF和方法==CV_TM_CCORR_NORMED。参见

2021更新:我一整天都在努力寻找模板透明度的解决方案,我想我终于找到了一种方法。有一个
mask
参数,它的工作原理显然与OP希望的完全一样:在另一幅图像中搜索模板时忽略模板中的某些像素。由于我的模板中已经包含透明度,我决定将我的模板用作
模板
掩码
参数。令人惊讶的是,它成功了

我在opencv4nodejs中使用JavaScript,因此下面的python代码片段可能完全不存在,但理论是存在的,我相当肯定它应该可以工作

#导入OpenCV
将cv2作为cv导入
#阅读图像和模板
image=cv.imread(“image.png”,cv.imread\u COLOR)
template=cv.imread(“template.png”,cv.imread\u COLOR)
#匹配模板作为模板和掩码参数
结果=cv.matchTemplate(图像、模板、cv.TM\u CCORR\u规范、无、模板)


现在我想起来了,它看起来真的很愚蠢,太好了以至于不可能是真的,但我在大多数测试中都得到了很好的匹配(
0.98+
)。希望这有帮助

如果你把你试过的东西贴出来会有帮助的。无论如何,这是一个非常有趣的问题。谢谢你的评论。我已经添加了我尝试过的东西,但不认为值得一提。尝试使用SIFT匹配关键点/SURF@Froyo谢谢你的评论。这是可行的,但对于这样的事情来说,这似乎有些过头了,更不用说从我尝试过的例子中,关键点匹配速度非常慢。虽然超出了这个问题的范围,但是否有OpenCV关键点匹配器可以匹配多个关键点?例如,能够通过在同一张图像上找到多个停车标志。关键点匹配?我有答案
result = matchTemplate(I^2, W, method=2) - matchTemplate(I, 2*W*T, method=2) + as.scalar(sum(W*T^2))