OpenCV 模板匹配和透明度

发布于 2024-10-13 19:04:05 字数 130 浏览 8 评论 0原文

OpenCV 在模板匹配过程中如何处理图像的透明度?

问题是模板图像需要有透明部分,因为在原始图像中这些地方可能有任何东西。

我尝试了所有的方法,但没有一个产生积极的结果(例如,未正确检测到原始图像中模板的位置)。

What's the way OpenCV handles transparency in image during template matching?

The problem is that the template image needs to have transparent parts, because in the original image there could be anything at those places.

I tried all of the methods, and none of them yielded positive results (e.g. position of template in original image wasn't detected correctly).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

小糖芽 2024-10-20 19:04:05

OpenCV 似乎没有按照您想要的方式处理 alpha。

您有两个选择:

  1. 编写自己的互相关方法,该方法将使用 Alpha 通道
  2. 转换图像,使您的 Alpha 通道变得无关紧要

由于第一个选项很简单,我将在这里探讨第二个选项。我将重新使用我为类似问题提供的示例代码 早些时候。如果将互相关直接应用于图像,背景会干扰模板匹配(特别是浅色背景部分)。如果您尝试使用颜色通道,您会发现蓝色通道中的匹配会给出正确的结果。这取决于图像内容,并且不是解决问题的一致方法。

另一种选择是对图像和模板执行边缘检测(例如 Sobel),并执行交叉那么相关性。这是边缘检测到的图像(我在 GIMP 的 Luma 通道上使用了 Sobel 边缘检测器,然后进行了一些强度拉伸)。

地图

建筑

正如您所看到的,这里的 alpha 通道已变得无关紧要,因为大部分地形已变为零强度,并且不会对互相关计算做出贡献。所以现在可以直接应用互相关,给出所需的结果:

misha@misha-desktop:~/Desktop/stackoverflow$ python cross-correlation.py map-blue.png building-maskz-blue.png 
(163, 244)

最后,这是另一个相关的问题。

附言。这是什么游戏?

It doesn't seem like OpenCV handles alpha the way you want it to.

You have two options:

  1. Write your own cross-correlation method that will use the alpha channel
  2. Transform your images so your alpha channel becomes irrelevant

Since the first option is straightforward, I will explore the second option here. I'm going to re-use the sample code I provided to a similar question earlier. If you apply cross-correlation directly to your images, the background interferes with the template matching (in particular, light background parts). If you play around with color channels, you will find that matching in the blue channel gives the correct result. This depends on the image content and isn't a consistent way to solve the problem.

Another option is to perform edge detection (e.g. Sobel) on the image and template, and perform cross-correlation then. Here are the edge detected images (I used the Sobel edge detector on the Luma channel in GIMP, and then some intensity stretching).

map

building

As you can see, the alpha channel here has become irrelevant, as most of the terrain has become zero intensity and will not contribute to the cross-correlation calculation. So now cross-correlation can be directly applied, giving the desired result:

misha@misha-desktop:~/Desktop/stackoverflow$ python cross-correlation.py map-blue.png building-maskz-blue.png 
(163, 244)

Finally, here's another related question.

PS. What game is this?

梦醒时光 2024-10-20 19:04:05

对于这个问题,我有一个稍微更脑残的解决方案,实际上似乎工作得相当好:用噪声替换模板图像的 Alpha 通道,这或多或少使得透明区域在匹配过程中在统计上不显着。

例如,我的用例涉及在 iOS 屏幕截图中搜索表情符号字符。 iOS 键盘背景会根据上下文改变颜色,如果您在模板图像中使用特定的背景颜色,这会使匹配过程出现问题。

这是 alpha 上的原始模板图像:
alpha 上的原始模板图像

这是经过处理的模板,其中填充了 alpha 通道的噪声:
在此处输入图像描述

我通过 模板匹配示例代码。无论是深色还是浅色背景,都能以合理的置信度找到匹配项。

在深色背景上搜索:

matched on dark

在浅色背景上搜索:

matched on light

相比之下,将模板的 Alpha 通道保持透明(或使用深色或浅色背景)不会返回可接受的匹配项。

I have a slightly more brain-dead solution to this issue which actually seems to work reasonably well: Replace the template image's alpha channel with noise, which more or less makes the transparent regions statistically insignificant during the matching process.

For example, my use case involved searching for emoji characters in screen captures from iOS. The iOS keyboard background changes colors depending on context, which makes the matching process problematic if you commit to a particular background color in your template image.

Here's the raw template image on alpha:
raw template image on alpha

Here's the processed template with noise filling in for the alpha channel:
enter image description here

I sent the processed template image through the Template Matching sample code provided in the OpenCV documentation. On either dark or light background, the match is found with reasonable confidence.

Searching on dark backgrounds:

matched on dark

Searching on light backgrounds:

matched on light

In comparison, leaving the template's alpha channel transparent — or committing to a dark or light background — did not return acceptable matches.

腻橙味 2024-10-20 19:04:05

OpenCV 3.0 为模板与屏蔽模板匹配提供本机支持。请参阅新文档

参数:

图像...

寺庙...

结果...

方法...

掩码 搜索模板的掩码。它必须与 templ 具有相同的数据类型和大小。默认情况下未设置。

[稍微离题]

请注意,模板与蒙版参考图像(较大的图像)匹配是不可能的。这是有道理的,因为 OpenCV 使用基于 FFT 的模板匹配。

因此,如果您需要仅在参考图像的特定区域执行模板匹配,则需要为此实现您自己的方法或屏蔽 cv::matchTemplate 的输出。

从头开始实现它应该可以弥补您只想在非常特定的区域(即:哈里斯角周围)搜索模板的情况。

OpenCV 3.0 offers native support for template matching with masked templates. Refer to the new documentation:

Parameters:

image ...

templ ...

result ...

method ...

mask Mask of searched template. It must have the same datatype and size with templ. It is not set by default.

[Slight Digression]

Note that template matching with masked reference images (the larger image) is not possible though. And that makes sense, given OpenCV uses FFT based template matching.

Therefore, if you need to perform template matching only at specific regions of your reference images, you will need to implement your own method for that or mask the output of cv::matchTemplate.

Implementing it from scratch should compensate for cases where you only want to search for the template at very specific regions (i.e.: around harris corners).

靖瑶 2024-10-20 19:04:05

如果您尝试用黑色 RGB 颜色替换 Alpha 通道,则 SQDIFF/SQDIFF_N 选项将是一个解决方案。
至少这是我对同样问题的解决方案。从我的结果可以明显看出,这种方法对较亮的像素值很敏感,我抓住了这个机会。

The SQDIFF/SQDIFF_N option would be a solution if you tried to replace alpha channel with the black RGB color.
At least this was my solution to same problem. From my result is obvious that this method is sensitive to brighter pixel values, and I took an opportunity of that.

东京女 2024-10-20 19:04:05

OpenCV 将透明度作为图像的一部分进行处理,而不是忽略它,这可能会导致意外的结果。我处理它的方法是使用具有透明度的模板作为 templatematchTemplate() 中的 mask 参数。我已经在此处回答了类似的问题,并提供了更多详细信息,也许有帮助。

OpenCV handles transparency as being part of the image instead of ignoring it, which may cause unintentional results. The way I handle it, is by using a template with transparency as a template and a mask parameter in matchTemplate(). I've answered a similar question here with a bit more detail, maybe it helps.

烛影斜 2024-10-20 19:04:05

根据具体情况,您可以使用这种适用于真实图像的方法,即在不同环境中拍摄物体的许多照片,并将它们均匀地叠加在一起(确保不要将它们叠加在一起,因为最后一张图像将占用模板的 50%)

depending on the situation you could use this method that works well for real images and that is to take many photos of the object in different environments and equally overlay them all (make sure not to overlay them one on top of each other because the last image will take 50% of the template)

青衫儰鉨ミ守葔 2024-10-20 19:04:05

我认为你正在尝试做 OpenCV 中所谓的模板匹配与掩码。我认为你可以尝试在模板上设置 ROI(感兴趣区域)。 这个问题展示了如何做到这一点。 (请注意,在该问题中,ROI 是在目标图像上设置的,而不是在模板上设置的,但过程是相同的)。

I think you're trying to do what in OpenCV is called template matching with a mask. I think you could try setting a ROI (region of interest) on the template. This SO question shows how to do it. (note that in that question the ROI is set on the target image, not the template, but the procedure is the same).

七婞 2024-10-20 19:04:05

我不确定,但透明通道的处理方式与任何其他通道一样。如果模板中的像素是“透明”的,那么它在主图像上也应该是“透明的”。我只是在这里猜测。

I'm not sure, but the transparency channel is treated just like any other channel. If a pixel in a template is "transparent" it should be "transparent" on the main image as well. I'm just guessing here.

暖心男生 2024-10-20 19:04:05

我遇到了同样的问题,我想到了一个解决方案。假设referenceImageMask和templateMask在好像素中为1,在坏像素中为0。该referenceImage和templateImage已经被屏蔽并且坏像素中也有0。

然后,模板匹配的第一个结果将给出图像之间未归一化的互相关性。然而,一堆像素为零。

第二个模板匹配将为每个可能的偏移给出两个图像中同时不同于零(未屏蔽)的像素数。

然后,通过该数字标准化相关性应该给出您(和我)想要的值。两个图像中未屏蔽的像素的平均乘积。

Image<Gray, float> imCorr = referenceImage.MatchTemplate(templateImage,      Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
Image<Gray, float> imCorrMask = referenceImageMask.MatchTemplate(templateMask, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
_imCorr = _imCorr.Mul(_imCorrMask.Pow(-1));

更新:实际上,这个解决方案不起作用。由于 opencv 中互相关的实现使用 DFT,因此会出现数值问题,并且您无法使用第二个互相关来纠正第一个互相关。

I came across the same problem and I thought of a solution. Asuming that referenceImageMask and templateMask have 1s in the good pixels and 0s in the bad ones. And that referenceImage and templateImage have already been masked and have 0s in the bad pixels as well.

Then, the first result of template matching will give the not normalized cross correlation between the images. However, a bunch of pixels were zero.

The second template matching will give for each possible offset the number of pixels that were at the same time different from zero (unmasked) in both images.

Then, normalizing the correlation by that number should give the value you (and I) wanted. The average product for the pixels that are not masked in both images.

Image<Gray, float> imCorr = referenceImage.MatchTemplate(templateImage,      Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
Image<Gray, float> imCorrMask = referenceImageMask.MatchTemplate(templateMask, Emgu.CV.CvEnum.TM_TYPE.CV_TM_CCORR);
_imCorr = _imCorr.Mul(_imCorrMask.Pow(-1));

UPDATE: actually, this solution does not work. Because the implementation of the cross correlation in opencv uses the DFT there will be numeric issues and you cannot use the second crosscorrelation to correct the first one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文