- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个项目,我想在图像中找到一堆箭头,如下所示:ibb.co/dSCAYQ使用以下模板:ibb.co/jpRUtQ
我在 Python 中使用 cv2 的模板匹配功能。我的算法是将模板旋转 360 度并匹配每次旋转。我得到以下结果:ibb.co/kDFB7k
如您所见,除了 2 个非常靠近的箭头(例如另一个箭头位于模板的黑色区域)外,它的效果很好。
我正在尝试使用掩码,但似乎 cv2 根本没有应用我的掩码,即无论掩码数组具有什么值,匹配都是相同的。已经尝试了两天,但 cv2 的有限文档没有帮助。
这是我的代码:
import numpy as np
import cv2
import os
from scipy import misc, ndimage
STRIPPED_DIR = #Image dir
TMPL_DIR = #Template dir
MATCH_THRESH = 0.9
MATCH_RES = 1 #specifies degree-interval at which to match
def make_templates():
base = misc.imread(os.path.join(TMPL_DIR,'base.jpg')) # The templ that I rotate to make 360 templates
for deg in range(360):
print('making template: ' + str(deg))
tmpl = ndimage.rotate(base, deg)
misc.imsave(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.jpg'), tmpl)
def make_masks():
for deg in range(360):
tmpl = cv2.imread(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.jpg'), 0)
ret2, mask = cv2.threshold(tmpl, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imwrite(os.path.join(TMPL_DIR, 'mask' + str(deg) + '.jpg'), mask)
def match(img_name):
img_rgb = cv2.imread(os.path.join(STRIPPED_DIR, img_name))
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
for deg in range(0, 360, MATCH_RES):
tmpl = cv2.imread(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.jpg'), 0)
mask = cv2.imread(os.path.join(TMPL_DIR, 'mask' + str(deg) + '.jpg'), 0)
w, h = tmpl.shape[::-1]
res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_CCORR_NORMED, mask=mask)
loc = np.where( res >= MATCH_THRESH)
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv2.imwrite('res.png',img_rgb)
有些事情我认为可能是错误的但不确定如何解决:
非常感谢任何帮助。
更新我修复了代码中的一个小错误; matchTemplate() 的参数中必须使用 mask=mask。这与使用 255 的掩码值相结合产生了差异。但是,现在我得到了大量的误报:<强> http://ibb.co/esfTnk 请注意,误报比真报的相关性更强。关于如何修复我的面具以解决此问题的任何指示?现在我只是简单地使用我的模板的黑白转换。
最佳答案
您已经弄清楚了第一个问题,但我将对它们进行一些扩展:
对于二进制掩码,它应该是 uint8
类型,其中值只是零或非零。零位置将被忽略,如果它们不为零,则包含在掩码中。您可以传递一个 float32
而不是作为掩码,在这种情况下,它可以让您加权像素;所以 0 的值是忽略,1 是包含,.5 是包含但只给它一半的权重作为另一个像素。请注意,只有 TM_SQDIFF
和 TM_CCORR_NORMED
支持掩码,但这没关系,因为您使用的是后者。 matchTemplate
的掩码仅为单 channel 。正如您所发现的,mask
不是位置参数,因此必须使用参数中的键调用它,mask=your_mask
。所有这些在 this page on the OpenCV docs 中都非常明确.
现在到新问题:
这与您使用的方法以及您使用 jpg
的事实有关。看看 formulas for the normed methods .在图像完全为零的地方,您将得到错误的结果,因为您将除以零。但这不是确切的问题——因为它返回 nan
并且 np.nan > value
总是返回 false,所以你永远不会从 中绘制正方形nan
值。
相反,问题出在边缘情况下,您会得到非零值的提示;并且因为您使用的是 jpg
图像,所以并非所有黑色值都恰好为 0;事实上,很多都不是。请注意公式中的平均值,当图像窗口中有 1、2、5 等值时,平均值将非常小,因此它会放大相关值。您应该改用 TM_SQDIFF
(因为它是唯一允许掩码的其他方法)。此外,因为您使用的是 jpg
,所以您的大部分掩码都毫无值(value),因为任何非零值(甚至 1)都算作包含。您应该使用 png
作为掩码。只要模板有合适的掩码,模板使用 jpg
还是 png
都没有关系。
使用 TM_SQDIFF
,您不是在寻找最大值,而是在寻找最小值——您希望模板和图像补丁之间的差异最小。您知道差异应该非常小——像素完美匹配恰好为 0,您可能不会得到。您可以稍微调整一下阈值。请注意,您总是会为每次旋转获得非常接近的值,因为模板的性质——小箭头条几乎不会添加那么多正值,并且不一定保证一个度数的离散化是完全正确的(除非你那样制作图像)。但是,即使箭头指向完全错误的方向,也仍然会非常接近,因为有很多重叠;并且朝向正确方向的箭头将真正接近正确方向的值。
在运行代码时预览平方差的结果是什么:
res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_SQDIFF, mask=mask)
cv2.imshow("result", res.astype(np.uint8))
if cv2.waitKey(0) & 0xFF == ord('q'):
break
你可以看到基本上模板的每个方向都非常匹配。
无论如何,它似乎达到了 8 的阈值:
我在您的代码中唯一修改的是将所有图像更改为 png
,切换到 TM_SQDIFF
,确保 loc
查找值小于阈值而不是大于阈值,并使用 8 的 MATCH_THRESH
。至少我认为这就是我所做的全部更改。看看以防万一:
import numpy as np
import cv2
import os
from scipy import misc, ndimage
STRIPPED_DIR = ...
TMPL_DIR = ...
MATCH_THRESH = 8
MATCH_RES = 1 #specifies degree-interval at which to match
def make_templates():
base = misc.imread(os.path.join(TMPL_DIR,'base.jpg')) # The templ that I rotate to make 360 templates
for deg in range(360):
print('making template: ' + str(deg))
tmpl = ndimage.rotate(base, deg)
misc.imsave(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.png'), tmpl)
def make_masks():
for deg in range(360):
tmpl = cv2.imread(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.png'), 0)
ret2, mask = cv2.threshold(tmpl, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imwrite(os.path.join(TMPL_DIR, 'mask' + str(deg) + '.png'), mask)
def match(img_name):
img_rgb = cv2.imread(os.path.join(STRIPPED_DIR, img_name))
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
for deg in range(0, 360, MATCH_RES):
tmpl = cv2.imread(os.path.join(TMPL_DIR, 'tmp' + str(deg) + '.png'), 0)
mask = cv2.imread(os.path.join(TMPL_DIR, 'mask' + str(deg) + '.png'), 0)
w, h = tmpl.shape[::-1]
res = cv2.matchTemplate(img_gray, tmpl, cv2.TM_SQDIFF, mask=mask)
loc = np.where(res < MATCH_THRESH)
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv2.imwrite('res.png',img_rgb)
关于带 mask 的灰度图像上的 Python openCV matchTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44690002/
我有两个包含两个接近矩形的形状的蒙版。 面罩示例(黄色): 现在,我要确定其中一个遮罩比另一个遮罩更接近实际矩形。 有可能实现吗? 最佳答案 获取轮廓和(旋转的)矩形边界框之间的面积差。面积差异最小的
我最近从 numpy 1.11 升级到 numpy 1.13 希望摆脱这个屏蔽数组警告,但它仍然存在: MaskedArrayFutureWarning:在具有共享掩码的掩码数组上设置项目不会复制掩码
我需要在sencha中的选项卡面板中添加一个加载掩码,我在 Controller 中通过Ajax请求加载了一个商店,但是在商店加载之前我需要放置一个加载掩码,并且在商店加载之后已加载,我需要将其删除。
我希望能够设置或清除 uintX_t 的(多个)位。 i 是一个运行时变量 (uintX_t)。b 是一个运行时变量 (uintX_t),它被限制为 0 或 1。 mask 是编译时常量。 有没有比以
我有一个处理程序,更像是一个提交按钮。我想掩盖整个页面或该表单以显示等待消息,直到完成其余过程。我做到了,它在FF中有效,但在IE中没有成功,当我执行Ext.getCmp('').body.mask(
我有我使用 Snap SVG 的 JS 代码。在某些时候我使用 element.attr({mask:maskelement}); 在该片段中,element和 maskelement是我的 svg
我需要从图标(.ICO) 文件中获取XOR Mask 和AND Mask。 如果有人可以建议我如何从 Java 执行此操作,那就太棒了。如果没有,您是否知道有任何应用程序可以获取这两个掩码并允许您扔掉
我一直在尝试学习scenekit并完成了一本书,但只有碰撞检测部分不明白,也许是最重要的部分。有类别掩码、共谋掩码和物理体?.contactTestBitMask。 我想创建一个简单的游戏来实现这个目
我在 Canvas 上制作了一个矩形 mask ,我需要 mask 外的任何东西都具有 0.8 的不透明度,因此 mask 外的所有对象都被视为不透明请看一下 fiddle 。 http://jsfi
我有一个包含可滚动内容的 div。我想为其添加一个覆盖内容的颜色 mask ,但不会随内容滚动。 http://jsfiddle.net/6e9t1wt3/1/ *{box-sizing:bord
在我的代码中,我必须选择这两个表达式之一(其中 mask 和 i 是非常数整数 -1 > i & 1) 和 (mask & 1 << i) 哪个更快?,我们在Stack Overflow上找到一个类似
我有一个包含 Image 的 Imageview 。还有一个包含兔子形状的面具形状。我有一个代码可以给出以下结果。 - (UIImage*)mynewmaskImage:(UIImage *)imag
您可能熟悉 enum 位掩码方案,例如: enum Flags { FLAG1 = 0x1, FLAG2 = 0x2, FLAG3 = 0x4, FLAG4 = 0x8
在本文之后,我将尝试实现他们如何计算每个实体的对数概率的平均值(第3.3节)。更具体地说,每个实体的得分计算为其令牌上的日志概率的平均值。。我有一个实体列表和一些提示:。任务是为每个提示找到应该适合的
我正在尝试遮盖比 mask 小的背景图像。背景和蒙版之间的空间显示为黑色。 这是我正在使用的代码: batch.end(); batch.begin(); Gdx
因此,我一直在尝试将背景图像裁剪成圆形 六边形,我发现 webkit 令人惊叹的 mask 图像非常容易地解决了我所有的问题。遗憾的是,它仅适用于 Chrome 和 Safari(当然)。 我如何为非
我有两个Java项目数据服务应用程序和数据报告应用程序,数据服务应用程序生成用于某些处理和数据报告应用程序的某些数据应该使用数据服务应用程序来使用它生成的数据来生成一些报告,这两个应用程序都应该构建为
我有一个带有绿色背景的简单 Activity ,我正在尝试提供一个带有透明圆形区域的红色叠加层。这是我要实现的效果: Expected Image 根据我在网上找到的代码,我看到的是这样的: Resu
我关注了这个link创建一个名为 mask 的自定义操作。tensorflow op的主体是 def tf_mask(x, labels, epoch_, name=None): # add "la
正如标题所说,我有 self.view,我将其添加到它的 mask 中(link) 属性另一个 View ,但是当我使用 addSubview 添加更多 View 到 self.view 时,掩码被删
我是一名优秀的程序员,十分优秀!