OpenCV 在模板匹配期间处理图像透明度的方式是什么?
问题是模板图像需要有透明部分,因为在原始图像中,这些地方可能有任何东西。
我尝试了所有方法,但都没有产生积极的结果(例如未正确检测到原始图像中模板的位置)。
OpenCV 在模板匹配期间处理图像透明度的方式是什么?
问题是模板图像需要有透明部分,因为在原始图像中,这些地方可能有任何东西。
我尝试了所有方法,但都没有产生积极的结果(例如未正确检测到原始图像中模板的位置)。
看起来 OpenCV 并没有按照您想要的方式处理 alpha。
你有两个选择:
由于第一个选项很简单,我将在这里探讨第二个选项。我将重新使用我之前提供给类似问题的示例代码。如果您将互相关直接应用于图像,则背景会干扰模板匹配(特别是浅色背景部分)。如果您使用颜色通道,您会发现蓝色通道中的匹配给出了正确的结果。这取决于图像内容,并不是解决问题的一致方法。
另一种选择是对图像和模板进行边缘检测(例如Sobel),然后进行互相关。这是边缘检测图像(我在 GIMP 的 Luma 通道上使用了 Sobel 边缘检测器,然后进行了一些强度拉伸)。
如您所见,此处的 alpha 通道已变得无关紧要,因为大部分地形已变为零强度,并且不会对互相关计算做出贡献。所以现在可以直接应用互相关,得到想要的结果:
misha@misha-desktop:~/Desktop/stackoverflow$ python cross-correlation.py map-blue.png building-maskz-blue.png
(163, 244)
最后,这是另一个相关的问题。
PS。这是什么游戏?
对于这个问题,我有一个稍微有点脑残的解决方案,它实际上似乎工作得相当好:用噪声替换模板图像的 alpha 通道,这或多或少地使透明区域在匹配过程中在统计上不显着。
例如,我的用例涉及在 iOS 的屏幕截图中搜索表情符号字符。iOS 键盘背景会根据上下文更改颜色,如果您在模板图像中提交特定背景颜色,则匹配过程会出现问题。
这是 alpha 上的原始模板图像:
这是为 alpha 通道填充噪声的处理模板:
我通过OpenCV 文档中提供的模板匹配示例代码发送了处理后的模板图像。无论在深色或浅色背景下,都能以合理的置信度找到匹配项。
在深色背景上搜索:
在浅色背景上搜索:
相比之下,让模板的 Alpha 通道透明——或使用深色或浅色背景——不会返回可接受的匹配。
OpenCV 3.0 为模板匹配与掩码模板提供本机支持。请参阅新文档:
参数:
图片 ...
模板...
结果 ...
方法 ...
mask 搜索模板的掩码。它必须与 templ 具有相同的数据类型和大小。默认情况下未设置。
[稍微题外话]
请注意,模板与蒙面参考图像(较大的图像)匹配是不可能的。这是有道理的,因为 OpenCV 使用基于 FFT 的模板匹配。
因此,如果您只需要在参考图像的特定区域执行模板匹配,则需要为此实现自己的方法或屏蔽 cv::matchTemplate 的输出。
从头开始实现它应该可以弥补您只想在非常特定的区域(即:在哈里斯角附近)搜索模板的情况。
SQDIFF/SQDIFF_N
如果您尝试用黑色 RGB 颜色替换 alpha 通道,该选项将是一个解决方案。至少这是我对同样问题的解决方案。从我的结果可以看出,这种方法对较亮的像素值很敏感,我抓住了这个机会。
OpenCV 将透明度视为图像的一部分而不是忽略它,这可能会导致意外结果。我处理它的方式是使用具有透明度的模板作为atemplate
和. 我已经在这里更详细地回答了一个类似的问题,也许它会有所帮助。mask
matchTemplate()
我认为您正在尝试执行 OpenCV 中称为模板匹配的操作。我认为您可以尝试在模板上设置 ROI(感兴趣区域)。这个 SO question 显示了如何做到这一点。(请注意,在那个问题中,ROI 是在目标图像上设置的,而不是在模板上,但过程是相同的)。
我不确定,但透明度通道的处理方式与任何其他通道一样。如果模板中的像素是“透明的”,则它在主图像上也应该是“透明的”。我只是在这里猜测。
我遇到了同样的问题,我想到了一个解决方案。假设 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,所以会有数值问题,你不能使用第二个互相关来纠正第一个。