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)
最后,这里有另一个相关的问题。
附注:这是什么游戏?
OpenCV 3.0提供原生支持带有掩膜模板的模板匹配。请参考新文档:
参数:
image ...
templ ...
result ...
method ...
mask 模板掩膜。它必须与templ具有相同的数据类型和尺寸。默认情况下未设置。
[稍微偏离话题]
需要注意的是,不可能对带有掩膜的参考图像(较大的图像)进行模板匹配。这是有道理的,因为OpenCV使用基于FFT的模板匹配。
因此,如果您仅需要在参考图像的特定区域执行模板匹配,则需要自己实现该方法或遮罩cv :: matchTemplate的输出。
从头开始实现应该能够弥补只想在非常特定的区域(即:在哈里斯角附近)搜索模板的情况。
比如说,我的应用场景是从iOS的屏幕截图中寻找表情符号。iOS键盘背景会根据上下文变换颜色,如果你在模板图片中使用了特定的背景颜色,匹配过程就会出现问题。
这里是alpha通道的原始模板图片:
这里是经处理后,噪点填补了alpha通道的模板图片:
我将经过处理的模板图片输入OpenCV文档提供的模板匹配样例代码进行匹配。无论是在黑暗背景还是浅色背景下,匹配都能够以相当高的准确率进行。
在黑色背景下搜索:
在浅色背景上搜索:
相比之下,将模板的alpha通道保持透明,或者承诺使用深色或浅色背景,都不能返回可接受的匹配结果。SQDIFF/SQDIFF_N
选项是一种解决方案,如果您尝试用黑色RGB颜色替换alpha通道。
至少这是我解决同样问题的方法。从我的结果来看,这种方法对较亮的像素值比较敏感,我抓住了这个机会。
matchTemplate()
中使用mask
参数。我在这里回答了一个类似的问题,并提供了更详细的解释,也许可以帮到你。我不确定,但透明通道的处理方式与其他通道相同。如果模板中的像素是“透明”的,则在主图像上也应该是“透明”的。这只是我的猜测。
我遇到了同样的问题,然后想出了一个解决方案。假设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,所以会出现数值问题,你不能使用第二个交叉相关来纠正第一个。